Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/87.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
VBA&;SQL-从数据库中删除日期范围_Sql_Vba_Date_Ms Access_Between - Fatal编程技术网

VBA&;SQL-从数据库中删除日期范围

VBA&;SQL-从数据库中删除日期范围,sql,vba,date,ms-access,between,Sql,Vba,Date,Ms Access,Between,我试图在Access数据库上创建一个选项,删除两个日期之间的所有记录 我在下面的代码似乎并不一致。例如,如果我的数据库具有日期01/01/18至01/30/18,并且我指定的范围正好是01/01/18至01/30/18,则它将工作并删除所有数据 但如果我指定任何其他日期范围(如01/01-01/15),它将失败,并且不会删除任何记录 [交易日期]为短文本格式,而不是日期,但所有条目均为MM/DD/YY。我宁愿保持这种方式,除非这是一个问题,没有其他选择 请让我知道我做错了什么或可以做得更好。先谢

我试图在Access数据库上创建一个选项,删除两个日期之间的所有记录

我在下面的代码似乎并不一致。例如,如果我的数据库具有日期01/01/18至01/30/18,并且我指定的范围正好是01/01/18至01/30/18,则它将工作并删除所有数据

但如果我指定任何其他日期范围(如01/01-01/15),它将失败,并且不会删除任何记录

[交易日期]为短文本格式,而不是日期,但所有条目均为MM/DD/YY。我宁愿保持这种方式,除非这是一个问题,没有其他选择

请让我知道我做错了什么或可以做得更好。先谢谢你

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

为了在Jet SQL中表示日期值,您需要用
#
将其包围起来,这样您的SQL就可以这样结束:

DELETE FROM AR_Consolidated WHERE [Trade Date] BETWEEN #01/01/18# AND #01/30/18#
PARAMETERS [prmDateFrom] DateTime, [prmDateTo] DateTime;
DELETE *
FROM AR_Consolidated
WHERE [Trade Date] Between [prmDateFrom] And [prmDateTo];

请注意,一般来说,将字符串与用户输入结合起来生成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\u 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

有关如何在针对Jet/ACE编程时避免SQL注入的全面描述,请参阅bobby tables.com上的和页面。

我将采用不同的方法,使用参数而不是字符串连接

查询的SQL如下所示:

DELETE FROM AR_Consolidated WHERE [Trade Date] BETWEEN #01/01/18# AND #01/30/18#
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
Sub Something()
Dim trFrmDat As字符串
Dim trToDat作为字符串
trFrmDat=InputBox(“交易日期从[MM/DD/YY]删除:”)
trToDat=InputBox(“交易日期被删除到[MM/DD/YY]:”)
如果Len(trFrmDat)8或Len(trToDat)8,则
MsgBox(“尚未输入正确的日期或答案。进程已中止。”)
出口接头
如果结束
将qdf设置为DAO.QueryDef
不算长
设置qdf=CurrentDb().QueryDefs(“QueryName”)
使用qdf
.Parameters(“[PRMDATEFORM]”)。值=CDate(trFrmDat)
.Parameters(“[prmDateTo]”)。值=CDate(trToDat)
.执行dbFailOnError
计数=.RecordsAffected
以
MsgBox“”和计数记录已从AR_Consolidated中删除
端接头

但是,您需要增强输入验证,因为包含8个字符的普通字符串无法转换为日期会导致运行时错误

您可以验证输入,然后格式化值:

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。

谢谢。我会在心里做一些编辑,一旦我开始工作就会更新。我会用两个日期控件和一个按钮创建一个简单的表单。如果将控件的格式设置为日期,则不允许使用任何其他值。谢谢。从未考虑过SQL注入。将尝试这两个建议,如果有效,将进行更新。@Chris需要xkcd引用:。永远不要将日期存储为文本。此外,避免在字段名中使用空格。