【问题标题】:Using Dates from Cell or named Range in Sql Query在 Sql 查询中使用单元格中的日期或命名范围
【发布时间】:2012-04-23 10:48:20
【问题描述】:

我创建了一个工作表,用于从 Microsoft SQL 数据库中提取数据,以生成 2 个日期 StartDateEndDate 之间的客户报告。

我一直在玩一些东西,但无论如何都没有成功。我已经搜索过,但找不到任何我想要或能够理解的东西。

我认为问题是我在 Excel 中使用的日期的数据类型,并试图将其传递给 SQL 查询。我知道我需要以某种方式对其进行转换以使其成为可能且正确。

如果我在查询中手动输入日期,它可以正常工作。但不适合客户使用 我没有这方面的经验,我只是!用我的方式通过它。如果有人能对我这么好,将不胜感激。

以下是我尝试使用的代码

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

我希望这是有道理的。

【问题讨论】:

  • 您必须将日期格式设置为:StartDate = Formta(Range("StartDate").Value,[Format]) 其中[Format]YYYYMMDDYYYY-MM-DD

标签: sql sql-server excel vba


【解决方案1】:

您无法指定数据类型,Access 数据库引擎(以前称为 Jet)必须猜测。您可以通过更改某些注册表设置(例如MaxScanRows)并在连接字符串中包含IMEX=1 来影响其猜测。详情请见this knowledge base article


这是我多年前就该主题写的一些内容(如果您在 Google 上搜索“ONEDAYWHEN=0”,您会发现它已被广泛阅读,尽管可能不够仔细!):

相关的注册表项(用于 Jet 4.0)位于:

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

ImportMixedTypes 注册表项始终被读取(无论是 荣誉将在后面讨论)。您可以通过将密钥更改为 ImportMixedTypes=OneDayWhen 并尝试使用 ISAM:你得到了 错误,“引擎部分的 Excel 键中的设置无效 Windows 注册表。”唯一有效的值是:

  • ImportMixedTypes=Text
  • ImportMixedTypes=Majority Type

数据类型是逐列确定的。 “多数类型”是指 扫描每列中的一定数量的行(稍后会详细介绍) 并计算数据类型。单元格的值和格式都是 用于确定数据类型。多数数据类型(即具有 最多行)决定整个列的整体数据类型。 如果出现平局,则存在偏向于 os numeric 的偏见。来自的行 发现的任何少数数据类型无法转换为多数数据 type 将返回一个空值。

对于ImportMixedTypes=Text,整列的数据类型为:

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

请注意,这不同于:

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

ImportMixedTypes=Text 将减少 255 个字符的文本,因为 Memo 是 转换为Text。对于要识别为 Memo 的列,多数类型 必须检测到,这意味着检测到的大多数行必须包含 256 个或更多字符。

但是之前每列扫描多少行是由决定的 混合和/或多数类型是什么?有第二个注册表 键,TypeGuessRows。这可以是 0-16(十进制)之间的值。一个值 从 1 到 16(含)是要扫描的行数。零值 表示将扫描所有行。

最后有一个转折点。连接中IMEX=1 的设置 字符串的扩展属性决定了ImportMixedTypes 价值得到尊重。 IMEX 指的是“导入导出模式”。有三种 可能的值。 IMEX=0IMEX=2 导致 ImportMixedTypes 是 忽略并使用“多数类型”的默认值。 IMEX=1 是 确保ImportMixedTypes=Text 受到尊重的唯一方法。所结果的 连接字符串可能如下所示:

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

最后,虽然在MSDN文章中提到MAXSCANROWS 可以在连接字符串的扩展属性中使用 覆盖 TypeGuessRows 注册表项,这似乎是一个谬论。 以这种方式使用MAXSCANROWS=0 永远不会在任何 情况。换句话说,is 和 put 的效果一样 ONEDAYWHEN=0 在扩展属性中,没有(甚至不是 错误!)同样适用于ImportMixedTypes,即不能用于 覆盖注册表设置的连接字符串。

综上所述,使用TypeGuessRows让Jet检测是否有'混合 类型的情况存在或使用它来“欺骗”Jet 检测到 某些数据类型是多数类型。如果发生 检测到“混合类型”情况,使用ImportMixedTypes 告知 Jet 要么使用多数类型,要么将所有值强制为Text (最多 255 个字符)。

【讨论】:

    【解决方案2】:

    尝试将 SQL 语句的日期部分更改为:

    "[...] originalAlarmTime BETWEEN '" & Format$(StartDate, "yyyy-mm-dd") & "' AND '" & Format$(EndDate, "yyyy-mm-dd") & "' [...]"
    

    您也可以尝试使用parameterized query

    【讨论】:

    • 不用担心。如果您对答案感到满意,请接受!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-03
    • 1970-01-01
    相关资源
    最近更新 更多