VBA & SQL - удалить диапазон дат из базы данных - PullRequest
0 голосов
/ 05 июня 2018

Я пытаюсь создать опцию в моей базе данных Access, которая удаляет все записи между 2 датами.

I код, который я имею ниже, кажется, не работает последовательно.Например, если в моей базе данных есть даты с 01.01.18 по 30.01.18, а указанный диапазон точно равен 01.01.18-30.01-18, то она работает и удаляет все данные.

Но если я укажу любой другой диапазон дат (например, 01/01 - 01/15), он потерпит неудачу, и никакие записи не будут удалены.

[Дата сделки] в коротком текстовом формате вместо даты, но все записи представлены в ММ / ДД / ГГ.Предпочел бы сохранить это таким образом, если это не проблема, и нет других альтернатив.

Пожалуйста, дайте мне знать, что я делаю неправильно или могу сделать лучше.Заранее спасибо.

Dim trFrmDat As String
Dim trToDat As String
Dim dbsDelete As DAO.Database
Dim qdfToDelete As DAO.QueryDef
Dim countString As String
Dim count As Long

Set dbsDelete = CurrentDb
trFrmDat = InputBox("Trade Date To Be Deleted From [MM/DD/YY]:")
trToDat = InputBox("Trade Date To Be Deleted To [MM/DD/YY]:")
If Len(trFrmDat) <> 8 Or Len(trToDat) <> 8 Then
    MsgBox ("The correct date or answer has not been entered. Process Aborted.")
    Exit Sub
Else
    countString = "SELECT COUNT(PK_ID) FROM AR_Consolidated WHERE [Trade Date] BETWEEN " & trFrmDat & " AND " & trToDat & ""
    count = dbsDelete.OpenRecordset(countString).Fields(0).Value
    Set qdfToDelete = dbsDelete.CreateQueryDef("", "DELETE FROM AR_Consolidated WHERE [Trade Date] BETWEEN " & trFrmDat & " AND " & trToDat & "")
    qdfToDelete.Execute dbFailOnError
    MsgBox ("" & count & " records have been deleted from AR_Consolidated")
End If

РЕДАКТИРОВАТЬ:

В итоге я воспользовался одним из предложенных ниже советов, но все еще имел проблемы с форматированием даты, поэтому я признал, что не могу сохранить фактическое поле в виде короткого текста.Я только что ввел alter line и все работает отлично.

    DoCmd.RunSQL "ALTER TABLE AR_Consolidated ALTER COLUMN [Trade Date] Datetime"

Ответы [ 3 ]

0 голосов
/ 05 июня 2018

Я бы использовал другой подход и использовал бы параметры вместо конкатенации строк.

SQL-запрос был бы примерно таким:

PARAMETERS [prmDateFrom] DateTime, [prmDateTo] DateTime;
DELETE *
FROM AR_Consolidated
WHERE [Trade Date] Between [prmDateFrom] And [prmDateTo];

Затем для вызова моего запроса в VBA:

Sub Something()

    Dim trFrmDat As String
    Dim trToDat As String

    trFrmDat = InputBox("Trade Date To Be Deleted From [MM/DD/YY]:")
    trToDat = InputBox("Trade Date To Be Deleted To [MM/DD/YY]:")

    If Len(trFrmDat) <> 8 Or Len(trToDat) <> 8 Then
        MsgBox ("The correct date or answer has not been entered. Process Aborted.")
        Exit Sub
    End If

    Dim qdf As DAO.QueryDef
    Dim count As Long

    Set qdf = CurrentDb().QueryDefs("QueryName")
    With qdf
        .Parameters("[prmDateFrom]").Value = CDate(trFrmDat)
        .Parameters("[prmDateTo]").Value = CDate(trToDat)
        .Execute dbFailOnError
        count = .RecordsAffected
    End With

    MsgBox " " & count & " records have been deleted from AR_Consolidated"

End Sub

Однако вам нужно улучшить проверку ввода как обычную строку с 8 символами, которые нельзя преобразовать в дату, что приведет к ошибке времени выполнения.

0 голосов
/ 05 июня 2018

Вы можете проверить ввод и затем отформатировать значения:

trFrmDat = InputBox("Trade Date To Be Deleted From [MM/DD/YY]:")
trToDat = InputBox("Trade Date To Be Deleted To [MM/DD/YY]:")

If IsDate(trFrmDat) And  IsDate(trToDat) Then
    trFrmDat = Format(CDate(trFrmDat), "yyyy\/mm\/dd")
    trToDat = Format(CDate(trToDat), "yyyy\/mm\/dd")
    countString = "SELECT COUNT(PK_ID) FROM AR_Consolidated WHERE [Trade Date] BETWEEN #" & trFrmDat & "# AND #" & trToDat & "#"
End If

и аналогичные для удаления SQL.

0 голосов
/ 05 июня 2018

Чтобы представить значение даты в Jet SQL, вам необходимо заключить его в #, чтобы ваш SQL заканчивался примерно так:

DELETE FROM AR_Consolidated WHERE [Trade Date] BETWEEN #01/01/18# AND #01/30/18#

Обратите внимание, что в целомобъединять строки с пользовательским вводом для создания операторов SQL - плохая идея.Помимо проблем, схожих с вашими - правильное представление даты или других литералов в операторах SQL - вы также подвержены внедрению SQL, когда злонамеренный пользователь вставляет дополнительные операторы или предложения SQL, которые приводят к сбою вашего кода или выполнению чего-либо нежелательного.Например, пользователь может передать в качестве второго параметра следующую строку:

01/01/18 OR 1 = 1

и результирующий оператор SQL:

DELETE FROM AR_Consolidated WHERE [Trade Date] BETWEEN 01/01/18 AND 01/01/18 OR 1 = 1

удалит все записи в AR_Consolidated.

Правильный способ избежать проблем обоих классов - использовать параметризованные запросы.

Dim sql As String
sql = _
    "PARAMETERS FromDate DATETIME, TillDate DATETIME; " & _
    "DELETE FROM AR_Consolidated " & _
    "WHERE [Trade Date] BETWEEN FromDate AND TillDate"

Dim qdfToDelete As DAO.QueryDef
Set qdfToDelete = dbsToDelete.CreateQueryDef("", sql)

qdfToDelete.Parameters("FromDate") = trFromDate 
qdfToDelete.Parameters("TillDate") = trToDate 
'You may have to convert the string values to dates first

qdfToDelete.Execute dbFailOnError
...