Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
284 views
in Technique[技术] by (71.8m points)

sql server - Using Dates from Cell or named Range in Sql Query

I have created a sheet to extract data from a Microsoft SQL database to produce a customer report between 2 date StartDate and EndDate.

I have been playing with a few things but have not been successful in anyway. I have searched but have not been able to find anything that was what I was after or able to understand.

The problem I believe is data type of the date I am using in Excel and trying to pass it to the SQL query. I understand I need to convert this in some way to make this possible and correct.

If I manually enter dates into the query it works fine. But not practical for customer use I am not experience with this and am just! stubbing my way through it. If someone would be so kind to me with this would be much appreciated.

Below is the code I am trying to use

Sub DataExtract()
'
DataExtract Macro
'

' Create a connection object.
 Dim cni96X As ADODB.Connection
 Set cni96X = New ADODB.Connection

' Set Database  Range

' Provide the connection string.
Dim strConn As String
Dim Lan As Integer
Dim OS As Integer
Dim PointID As String


' Set Variables
Lan = Range("Lan").Value
OS = Range("OS").Value
PointID = Range("PointID").Value
StartDate = Range("StartDate").Value
EndDate = Range("EndDate").Value


'Use the SQL Server OLE DB Provider.
 strConn = "PROVIDER=SQLOLEDB;"

'Connect to 963 database on the local server.
strConn = strConn & "DATA SOURCE=(local);INITIAL CATALOG=i96X;"

'Use an integrated login.
strConn = strConn & " INTEGRATED SECURITY=sspi;"

 'Now open the connection.
cni96X.Open strConn

' Create a recordset object.
Dim rsi96X As ADODB.Recordset
Dim rsi96X1 As ADODB.Recordset
Set rsi96X = New ADODB.Recordset
Set rsi96X1 = New ADODB.Recordset

With rsi96X
    ' Assign the Connection object.
     .ActiveConnection = cni96X
    ' Extract the required records1.
    .Open "SELECT ModuleLabel, originalAlarmTime FROM LastAlarmDetailsByTime WHERE (os = " & OS & " And theModule = N'" & PointID & "'AND AlarmCode = N'DI=1' And lan = " & Lan & " And originalAlarmTime BETWEEN N'" & StartDate & "' AND N'" & EndDate & "') ORDER BY originalAlarmTime DESC"
    ' Copy the records into sheet.
    Range("PointLabel, TimeCallInitiated").CopyFromRecordset rsi96X


With rsi96X1
    .ActiveConnection = cni96X
    ' Assign the Connection object.
    .Open "SELECT originalAlarmTime FROM LastAlarmDetailsByTime WHERE (os = " & OS & " And theModule = N'" & PointID & "'AND AlarmCode = N'CDI1' And lan = " & Lan & " And originalAlarmTime BETWEEN N'" & StartDate & "' AND N'" & EndDate & "')ORDER BY originalAlarmTime DESC"
     ' Copy the records into sheet.
    Sheet1.Range("TimeCallEnded").CopyFromRecordset rsi96X1
    ' Tidy up
    .Close

I hope this makes sense.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

You cannot specify the data types, the Access database engine (formerly Jet) must guess. You can influence its guesswork by changing certain registry settings (e.g. MaxScanRows) and including IMEX=1 in the connection string. For more details, see this knowledge base article.


Here's something I wrote on the subject many years ago (if you google for "ONEDAYWHEN=0" you can see it has been widely read though perhaps not carefully enough!):

The relevant registry keys (for Jet 4.0) are in:

Hkey_Local_Machine/Software/Microsoft/Jet/4.0/Engines/Excel/

The ImportMixedTypes registry key is always read (whether it is honored is discussed later). You can test this by changing the key to ImportMixedTypes=OneDayWhen and trying to use the ISAM: you get the error, "Invalid setting in Excel key of the Engines section of the Windows Registry." The only valid values are:

  • ImportMixedTypes=Text
  • ImportMixedTypes=Majority Type

Data type is determined column by column. 'Majority Type' means a certain number of rows (more on this later) in each column are scanned and the data types are counted. Both a cell's value and format are used to determine data type. The majority data type (i.e. the one with the most rows) decides the overall data type for the entire column. There's a bias in favor os numeric in the event of a tie. Rows from any minority data types found that can't be cast as the majority data type will be returned with a null value.

For ImportMixedTypes=Text, the data type for the whole column will be:

Jet (MS Access UI): 'Text' data type 
DDL: VARCHAR(255) 
ADO: adWChar ('a null-terminated Unicode character string') 

Note that this is distinct from:

Jet (MS Access UI): 'Memo' data type 
DDL: MEMO 
ADO: adLongVarWChar ('a long null-terminated Unicode string value') 

ImportMixedTypes=Text will curtail text at 255 characters as Memo is cast as Text. For a column to be recognized as Memo, majority type must be detected, meaning the majority of rows detected must contain 256 or more characters.

But how many rows are scanned for each column before is decided that mixed and/or what the majority type is? There is a second registry key, TypeGuessRows. This can be a value from 0-16 (decimal). A value from 1 to 16 inclusive is the number of rows to scan. A value of zero means all rows will be scanned.

There is one final twist. A setting of IMEX=1 in the connection string's extended property determines whether the ImportMixedTypes value is honored. IMEX refers to 'IMport EXport mode'. There are three possible values. IMEX=0 and IMEX=2 result in ImportMixedTypes being ignored and the default value of 'Majority Types' is used. IMEX=1 is the only way to ensure ImportMixedTypes=Text is honored. The resulting connection string might look like this:

Provider=Microsoft.Jet.OLEDB.4.0; 
Data Source=C: db.xls; 
Extended Properties='Excel 8.0;HDR=Yes;IMEX=1' 

Finally, although it is mentioned in MSDN articles that MAXSCANROWS can be used in the extended properties of the connection string to override the TypeGuessRows registry keys, this seems to be a fallacy. Using MAXSCANROWS=0 in this way never does anything under any circumstances. Put another way, is has just the same effect as putting ONEDAYWHEN=0 in the extended properties, being none (not even an error!) The same applied to ImportMixedTypes i.e. can't be used in the connection string to override the registry setting.

In summary, use TypeGuessRows to get Jet to detect whether a 'mixed types' situation exists or use it to 'trick' Jet into detecting a certain data type as being the majority type. In the event of a 'mixed types' situation being detected, use ImportMixedTypes to tell Jet to either use the majority type or coerce all values as Text (max 255 characters).


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...