在将记录添加到数据库之前检查记录是不是存在

Posted

技术标签:

【中文标题】在将记录添加到数据库之前检查记录是不是存在【英文标题】:Check if record exists before adding it to the database在将记录添加到数据库之前检查记录是否存在 【发布时间】:2017-09-08 08:49:04 【问题描述】:

VBA 中有没有一种方法可以在添加记录之前检查数据库中是否存在记录?

我试图在变量中捕获选择查询:

sSQL = "select count(*) from OptionRestriction where Feature_ID_1 = 1021 AND OptionValue_1 = 3 AND value = 0 AND Feature_ID_2 = 403 AND OptionValue_2 = 5 and visible = 1"

我在if语句中使用了变量来检查计数是否不是1。如果语句为真,则应添加记录:

            If sSQL <> "1" Then
                conn.Execute "INSERT INTO OptionRestriction (Feature_ID_1, OptionValue_1, value, Feature_ID_2, OptionValue_2, visible) SELECT TOP(1) CF.FeatureID As Feature_ID_1, CF.OptionValue  As OptionValue_1, 0, OV.FeatureID As Feature_ID_2, OV.OptionValue  AS OptionValue_2, 1 From Value as CF Cross Join Value as OV INNER JOIN Feature f on CF.FeatureID = f.ID INNER JOIN Feature f_2 on OV.FeatureID = f_2.ID Where CF.Name = '" & Replace(s_OptionValue_1_s, "'", "''") & "' AND OV.Name = '" & Replace(s_OptionValue_2_s, "'", "''") & "'"
            End If

但是,这在 VBA 中不起作用。有什么想法可以让我完成这项工作吗?

更新

基于Vityata的cmets,我做了如下改动:

我添加了一个函数:

Public Function RestrictionCount() As Long
     RestrictionCount = DCount("Feature_ID_1", "OptionRestriction", "Feature_ID_1 = 1023 AND OptionValue_1 AND value = 0  AND Feature_ID_2 = 403 AND optionValue_2 = 5 AND visible = 1")
End Function

并在我的 if 所在的代码中使用了函数:

Private Sub CommandButton1_Click()

   Dim conn              As New ADODB.Connection
   conn.Open             "<string to connect to DB. Not displayed here due to confidentiality reasons>"


            If RestrictionCount() <> 1 Then
                conn.Execute "INSERT INTO OptionRestriction (Feature_ID_1, OptionValue_1, value, Feature_ID_2, OptionValue_2, visible) SELECT TOP(1) CF.FeatureID As Feature_ID_1, CF.OptionValue  As OptionValue_1, 0, OV.FeatureID As Feature_ID_2, OV.OptionValue  AS OptionValue_2, 1 From Value as CF Cross Join Value as OV INNER JOIN Feature f on CF.FeatureID = f.ID INNER JOIN Feature f_2 on OV.FeatureID = f_2.ID Where CF.Name = '" & Replace(s_OptionValue_1_s, "'", "''") & "' AND OV.Name = '" & Replace(s_OptionValue_2_s, "'", "''") & "'"
            End If

End Sub

现在我收到一个编译错误,指出子或函数未定义,而 DCount 位于另一个函数中。有没有办法解决这个问题?抱歉我的问题(我是 VBA 新手)。

更新

感谢 Vityata 的最后评论,现在可以执行检查。现在的代码如下,包括我用来将数据添加到数据库的循环:

    rs.ActiveConnection = conn
    rs.Open "select * from OptionRestriction where Feature_ID_1 = 1021 AND OptionValue_1 = 3 AND value = 0 AND Feature_ID_2 = 403 AND OptionValue_2 = 5 and visible = 1"

    i = 2
    Do Until IsEmpty(Cells(i, 1))
        s_OptionValue_1_s = ActiveSheet.Cells(i, 1)
        value_s = ActiveSheet.Cells(i, 2)
        s_OptionValue_2_s = ActiveSheet.Cells(i, 3)

        If value_s <> "" Then

            If rs.RecordCount <> 1 Then
                conn.Execute "INSERT INTO OptionRestriction (Feature_ID_1, OptionValue_1, value, Feature_ID_2, OptionValue_2, visible) SELECT TOP(1) CF.FeatureID As Feature_ID_1, CF.OptionValue  As OptionValue_1, 0, OV.FeatureID As Feature_ID_2, OV.OptionValue  AS OptionValue_2, 1 From Value as CF Cross Join Value as OV INNER JOIN Feature f on CF.FeatureID = f.ID INNER JOIN Feature f_2 on OV.FeatureID = f_2.ID Where CF.Name = '" & Replace(s_OptionValue_1_s, "'", "''") & "' AND OV.Name = '" & Replace(s_OptionValue_2_s, "'", "''") & "'"
            End If

            conn.Execute "INSERT INTO OptionRestriction (Feature_ID_1, OptionValue_1, value, Feature_ID_2, OptionValue_2, visible) SELECT TOP(1) CF.FeatureID As Feature_ID_1, CF.OptionValue  As OptionValue_1, '" & Replace(value_s, "'", "''") & "', OV.FeatureID As Feature_ID_2, OV.OptionValue  AS OptionValue_2, 0 From Value as CF Cross Join Value as OV INNER JOIN Feature f on CF.FeatureID = f.ID INNER JOIN Feature f_2 on OV.FeatureID = f_2.ID Where CF.Name = '" & Replace(s_OptionValue_1_s, "'", "''") & "' AND OV.Name = '" & Replace(s_OptionValue_2_s, "'", "''") & "'"
        Else
            conn.Execute "INSERT INTO OptionRestriction (Feature_ID_1, OptionValue_1, value, Feature_ID_2, OptionValue_2, visible) SELECT TOP(1) CF.FeatureID As Feature_ID_1, CF.OptionValue  As OptionValue_1, 1, OV.FeatureID As Feature_ID_2, OV.OptionValue  AS OptionValue_2, 0 From Value as CF Cross Join Value as OV INNER JOIN Feature f on CF.FeatureID = f.ID INNER JOIN Feature f_2 on OV.FeatureID = f_2.ID Where CF.Name = '" & Replace(s_OptionValue_1_s, "'", "''") & "' AND OV.Name = '" & Replace(s_OptionValue_2_s, "'", "''") & "'"
            conn.Execute "INSERT INTO OptionRestriction (Feature_ID_1, OptionValue_1, value, Feature_ID_2, OptionValue_2, visible) SELECT TOP(1) CF.FeatureID As Feature_ID_1, CF.OptionValue  As OptionValue_1, 0, OV.FeatureID As Feature_ID_2, OV.OptionValue  AS OptionValue_2, 1 From Value as CF Cross Join Value as OV INNER JOIN Feature f on CF.FeatureID = f.ID INNER JOIN Feature f_2 on OV.FeatureID = f_2.ID Where CF.Name = '" & Replace(s_OptionValue_1_s, "'", "''") & "' AND OV.Name = '" & Replace(s_OptionValue_2_s, "'", "''") & "'"
        End If

    i = i + 1
    Loop

现在数据库中的结果是:

然而,被选中的行不应该在那里。所以它只需要添加 1021 - 3 - 0 - 403 - 5 - 1 一次。为了实现这一点,我需要在循环中进行哪些更改?

将数据插入数据库的 excel 文件如下所示:

【问题讨论】:

你在用什么rdbms? 我正在使用 SQL 服务器 您应该看看 TRANSACT SQL 中的 MERGE 语句,如果记录存在或不存在,它会为您提供许多选项。 ***.com/questions/11017036/… 【参考方案1】:

如果您使用 MS Excel,以下是您可以使用的示例:

Public Sub CheckDataInSQLServer()

    Dim cnLogs              As Object
    Dim rsData              As Object

    On Error GoTo CheckDataInSQLServer_Error

    Set cnLogs = CreateObject("ADODB.Connection")
    Set rsData = CreateObject("ADODB.Recordset")

    cnLogs.Open ConnectionString 'this is a string function

    rsData.ActiveConnection = cnLogs
    rsData.Open "SELECT * FROM A WHERE B = C;"

    If rsData.EOF Then
        debug.print "no values"
    Else    
        debug.print "has values"
    End If    

End Sub

在 VBA 中,如果您使用 MS Access,您需要的函数称为 DCount

您可以使用 DCount 函数来确定指定记录集(域)中的记录数。使用 Visual Basic 中的 DCount 函数、宏、查询表达式或计算控件。例如,您可以在模块中使用 DCount 函数来返回 Orders 表中与特定日期下达的订单相对应的记录数。 MSDN

查看更多如何使用 DCount - DCount with 2 criteria

这是一个如何在函数中构建DCount 并使用它的示例:

Public Function OrdersCount(ByVal strCountry As String, ByVal dteShipDate As Date) As Long
    OrdersCount = DCount("[ShippedDate]", "Orders", _
                  "[ShipCountry] = '" & strCountry & _
                  "' AND [ShippedDate] > #" & dteShipDate & "#")
End Function

If OrdersCount("Bulgaria", Now()) = 0 then
    'Execute the SQL query.
End if

【讨论】:

亲爱的 Vityata。我在主要问题中发布了更新。你能帮我看看如何让它工作吗? @user2237168 - 首先尝试使用较少的条件。 Feature_ID_1 = 1023 AND OptionValue_1 AND value = 0 应该是 Feature_ID_1 = 1023 AND OptionValue_1 = 5 AND value = 0。然后确保它有效并编写更多条件。 嗯,是的,但我仍然收到错误:尝试编译时未定义子或函数。我做错了什么? @user2237168 - 您是在 Excel 中还是在 Access 中使用 VBA?在 Access 中,您应该没有问题。 不再需要帮助了。它通过在 SQL 中使用 NOT EXISTS 来解决:)。不过谢谢你的帮助!!

以上是关于在将记录添加到数据库之前检查记录是不是存在的主要内容,如果未能解决你的问题,请参考以下文章

检查FMDB中某条记录之后或某条记录之前是不是存在行

laravel 在插入之前检查记录是不是存在,这是一种有效的方法

Laravel:检查记录ID是不是存在

在创建新记录之前如何检查记录是不是已经存在?

实体框架:在插入新记录之前检查记录是不是存在

如何使用 .forEach() 插入多个集合并检查它是不是存在