繁体   English   中英

在 SQL 查询的 BETWEEN 子句中使用 Excel 单元格中的日期

[英]Use date in Excel cell in BETWEEN clause in SQL query

(1) 表DB-Fiddle

CREATE TABLE logistics (
    id int primary key,
    Product VARCHAR(255),
    insert_timestamp Date
);

INSERT INTO logistics
(id, product, insert_timestamp
)
VALUES 
("1", "Product_A", "2020-02-24 18:15:48"),
("2", "Product_B", "2020-02-24 20:30:17"),
("3", "Product_C", "2020-02-24 23:54:58"),
("4", "Product_D", "2020-02-25 08:09:30"),
("5", "Product_E", "2020-02-25 10:17:15");

(2) VBA
Cell B1 = 2020-02-24Cell B1 = 2020-02-24

Sub Get_Data()

Dim conn As New ADODB.Connection
Dim rs As New ADODB.Recordset
Dim dateVar As Date

    Set conn = New ADODB.Connection
    conn.ConnectionString = "DRIVER={MySQL ODBC 5.1 Driver}; SERVER=localhost; DATABASE=bi; UID=username; PWD=password; OPTION=3"
    conn.Open

                strSQL = " SELECT " & _
                            " cID " & _
                            " FROM logistics " & _
                            " WHERE DATE(insert_timestamp) BETWEEN """ & Format(Sheet1.Range("B1").Value, "YYYY-MM-DD") & "00:00:00" & """ " & _
                            " AND """ & Format(Sheet1.Range("B1").Value, "YYYY-MM-DD") & "23:59:59" & """ " & _
                            " GROUP BY 1 "


    Set rs = New ADODB.Recordset
    rs.Open strSQL, conn, adOpenStatic

    Sheet1.Range("A1").CopyFromRecordset rs

    rs.Close
    conn.Close

End Sub

我想在VBA中运行一个查询,该查询在WHERE子句的BETWEEN语句中使用Cell B1的日期。
当我在VBA之外运行此查询时,它可以完美运行:

SELECT
Product
FROM logistics
WHERE DATE(insert_timestamp) BETWEEN "2020-02-24 00:00:00" AND "2020-02-24 23:59:59";

有一次,我在VBA运行它,它不会给我一个错误,但它也不会给我任何结果。
我认为这个问题是由我在strSQL中的sqlVBA组合引起的。

我必须如何更改VBA才能使其工作?

与其将日期或字符串等值格式化到 SQL 命令中,不如使用ADODB.Parameter - 在这种情况下,驱动程序将为您完成所有工作。 您不必关心字符串周围的引号、格式化日期以便数据库正确理解它(这在很大程度上取决于数据库、区域设置等)。 此外,它还可以防止 SQL 注入。 另外,查询优化器可以做得更好,因为它每次都获得相同的 SQL 命令并记住执行计划。

缺点:代码获取稍微复杂一些,因为您必须涉及ADODB.command对象。

在你的 SQL 语句中,你放了一个简单的? 在你想要参数的地方。 你只需要注意数字和位置? 和参数匹配。

Dim Conn As New ADODB.Connection, cmd As New ADODB.Command, param As ADODB.Parameter, rs As ADODB.Recordset
Conn.Open "<your connection string>"
Set cmd.ActiveConnection = Conn
cmd.CommandText = "SELECT cID FROM logistics WHERE DATE(insert_timestamp) BETWEEN ? AND ? GROUP BY 1"

Set param = cmd.CreateParameter(, adDate, adParamInput, , Date)
cmd.Parameters.Append param
Set param = cmd.CreateParameter(, adDate, adParamInput, , Date + 1)
cmd.Parameters.Append param

Set rs = cmd.Execute
Debug.Print rs.Fields(0).Name, rs(0).Value

PS 对日期处理有点懒惰,如果您恰好在午夜有数据,您会得到太多数据。

您在日期和时间之间缺少一个空格...

打开您的 VBE 并调试打印公式以查看结果(确保您有即时窗口 [查看菜单/即时窗口)。

Sub test()
   Debug.Print Format(Sheet1.Range("B1").Value, "YYYY-MM-DD") & "23:59:59"
End Sub

结果2020-03-1123:59:59

只需在 DD 后添加空格如下

Format(Sheet1.Range("B1").Value, "YYYY-MM-DD ") & "23:59:59"

我知道你已经接受了一个答案,这是一个非常好的答案。 我只是把它留在这里作为一种替代方法,你可能会发现它在其他情况下也很有用:

Dim date_to_use As String

date_to_use = Format(Sheet1.Range("B1").Value, "YYYY-MM-DD")

strSQl = " SELECT " & _
            " cID " & _
            " FROM logistics " & _
            " WHERE DATE(insert_timestamp) BETWEEN '[date to use] 00:00:00'" & _
            " AND '[date to use] 23:59:59'" & _
            " GROUP BY 1 "

strSQl = Replace(strSQl, "[date to use]", date_to_use)

在使用之前以这种方式存储B1的内容还允许您对其应用其他更改 - 以防万一您想进一步清理它或减少使用 SQL 注入的机会。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM