Использовать дату в ячейке Excel в предложении BETWEEN в запросе SQL - PullRequest
0 голосов
/ 11 марта 2020

(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-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, который использует дату в Cell B1 в выражении BETWEEN в предложении WHERE.
Когда я запускаю этот запрос вне VBA, он отлично работает:

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

Однажды я запускаю его в VBA, он не выдает ошибку, но также не дает мне любой результат.
Я предполагаю, что проблема вызвана моей комбинацией sql и VBA в strSQL.

Как мне изменить VBA, чтобы он работал?

Ответы [ 3 ]

2 голосов
/ 11 марта 2020

Вместо форматирования значений, таких как даты или строки, в команду SQL, гораздо лучше использовать ADODB.Parameter - в этом случае драйвер сделает всю работу за вас. Вам не нужно заботиться о кавычках вокруг строки, форматируя дату так, чтобы база данных понимала ее правильно (что сильно зависит от базы данных, региональных настроек и т. Д.). Плюс это защита от инъекций SQL. Кроме того, оптимизатор запросов может выполнять свою работу намного лучше, потому что он каждый раз получает одну и ту же команду SQL и запоминает план выполнения.

Недостаток: получение кода немного сложнее, потому что необходимо задействовать ADODB.command object.

В своем выражении 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 Было немного лениво для обработки даты, если вы располагаете данными точно в полночь, вы получите слишком много данных.

1 голос
/ 11 марта 2020

Я знаю, что вы приняли ответ, и он очень хороший. Я просто оставляю это здесь как альтернативный метод, который может оказаться полезным и в других случаях:

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 инъекции ..

1 голос
/ 11 марта 2020

вам не хватает пробела между датой и временем ...

Откройте ваш VBE и отладьте распечатайте формулу, чтобы увидеть результат (убедитесь, что у вас есть непосредственное окно [View menu / Immediate window) .

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"
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...