INSERT语句后为什么要从SQL表中删除记录?

时间:2016-08-27 13:44:51

标签: sql sql-server triggers

INSERT语句之后,为什么记录会从SQL表中消失的任何想法?我应该提到INSERT是成功的,因为我可以在执行INSERT语句后看到表中的记录,但是在短时间段(10-30分钟)之后,删除添加的记录。我可以确认由于DELETE触发器而删除了记录。谢谢!

修改

Using conn As New SqlConnection("XXXXXXXXXXXXXXX")
    conn.Open()
    Using comm As New SqlCommand()
        Dim query as String
        For i As Integer = 0 To dgvOrders.Rows.Count - 1
            query = String.Empty
            With comm
                query &= "IF NOT EXISTS(SELECT 1 FROM TestTemp.dbo.OpenTabs WHERE OrderNum = " & orderNum & " AND " & "ItemNum = " & dgvOrders.Rows(i).Cells(4).Value & ") "
                query &= "INSERT INTO TestTemp.dbo.OpenTabs (OrderNum, CustomerName, UserID, ItemNum, ItemID, Quantity, "
                query &= "                     ItemType, ItemDesc, TransDate, TransTime, ItemPrice, OrderTotal)  "
                query &= "VALUES (@OrderNum, @CustomerName, @UserID, @ItemNum, @ItemID, @Quantity, @ItemType, @ItemDesc, @TransDate, @TransTime, @ItemPrice, @OrderTotal);"
                query &= "UPDATE TestTemp.dbo.OpenTabs SET OrderTotal=" & GetTotal(dgvOrders) & " WHERE OrderNum = " & "@OrderNum "
                .Connection = conn
                .CommandType = CommandType.Text
                .CommandText = query
                .Parameters.AddWithValue("@OrderNum", orderNum)
                .Parameters.AddWithValue("@CustomerName", customerName)
                .Parameters.AddWithValue("@UserID", userNameTemp)
                .Parameters.AddWithValue("@ItemNum", dgvOrders.Rows(i).Cells(4).Value)
                .Parameters.AddWithValue("@ItemID", dgvOrders.Rows(i).Cells(2).Value)
                .Parameters.AddWithValue("@Quantity", dgvOrders.Rows(i).Cells(5).Value)
                .Parameters.AddWithValue("@ItemType", dgvOrders.Rows(i).Cells(3).Value)
                .Parameters.AddWithValue("@ItemDesc", dgvOrders.Rows(i).Cells(0).Value)
                .Parameters.AddWithValue("@TransDate", Today.Date)
                .Parameters.AddWithValue("@TransTime", Now)
                .Parameters.AddWithValue("@ItemPrice", dgvOrders.Rows(i).Cells(1).Value)
                .Parameters.AddWithValue("@OrderTotal", GetTotal(dgvOrders))
            End With
            comm.ExecuteNonQuery()
            comm.Parameters.Clear()
        Next i
    End Using
    conn.Close()
End Using

1 个答案:

答案 0 :(得分:0)

此代码中存在一些挥之不去的SQL注入漏洞(如果您不认为可以注入数字,请尝试使用系统的负数和货币的区域设置)。您可以在此处执行许多其他操作来改善此问题:

'Use a parameters instead of string concatenation and suddenly you can
'  move the query out of the loop. This could even be a CONSTANT if you wanted.
Dim query As String
query = "IF NOT EXISTS(SELECT 1 FROM TestTemp.dbo.OpenTabs WHERE OrderNum = @OrderNum AND ItemNum = @ItemNum ) " & vbCrLf
query &= "  INSERT INTO TestTemp.dbo.OpenTabs (OrderNum, CustomerName, UserID, ItemNum, ItemID, Quantity, "
query &=          " ItemType, ItemDesc, TransDate, TransTime, ItemPrice, OrderTotal)  "
query &= " VALUES (@OrderNum, @CustomerName, @UserID, @ItemNum, @ItemID, @Quantity, @ItemType, @ItemDesc, @TransDate, @TransTime, @ItemPrice, @OrderTotal);" & vbCrLf
query &= "UPDATE TestTemp.dbo.OpenTabs SET OrderTotal= @OrderTotal WHERE OrderNum = @OrderNum ;"

'Combine the using declarations to reduce code
Using conn As New SqlConnection("XXXXXXXXXXXXXXX"), _
      comm As New SqlCommand()

    'MUCH better to use explicit types for your parameters.
    ' I needed to guess at the actual column types/lengths here, but you
    ' can check your DB for the actual column definitions.
    'We can also re-use the same parameter objects for each iteration through the loop
    comm.Parameters.Add("@OrderNum", SqlDbType.Int)
    comm.Parameters.Add("@CustomerName", SqlDbType.NVarChar,50)
    comm.Parameters.Add("@UserID", SqlDbType.Int)
    comm.Parameters.Add("@ItemNum", SqlDbType.Char, 15)
    comm.Parameters.Add("@ItemID", SqlDbType.Int)
    comm.Parameters.Add("@Quantity", SqlDbType.Int)
    comm.Parameters.Add("@ItemType", SqlDbType.VarChar, 15)
    comm.Parameters.Add("@ItemDesc", SqlDbType.NVarChar, 200)
    'You should REALLY combine these two columns!
    comm.Parameters.Add("@TransDate", SqlDbType.DateTime)
    comm.Parameters.Add("@TransTime", SqlDbType.DateTime)
    comm.Parameters.Add("@ItemPrice", SqlDbType.Decimal)
    comm.Parameters.Add("@OrderTotal", SqlDbType.Decimal)

    Dim Total = GetTotal(dgvOrders)
    'Wait as long as possible to call conn.Open()
    conn.Open()

    'For Each loop instead of For loop means shorter code to use each row value
    For Each row As DataGridViewRow In dgvOrders.Rows
        comm.Parameters("@OrderNum").Value = orderNum
        comm.Parameters("@CustomerName").Value = customerName
        comm.Parameters("@UserID").Value = userNameTemp
        comm.Parameters("@ItemNum").Value = row.Cells(4).Value
        comm.Parameters("@ItemID").Value = row.Cells(2).Value
        comm.Parameters("@Quantity").Value = row.Cells(5).Value
        comm.Parameters("@ItemType").Value = row.Cells(3).Value
        comm.Parameters("@ItemDesc").Value = row.Cells(0).Value
        comm.Parameters("@TransDate").Value = Today.Date
        comm.Parameters("@TransTime").Value = Now
        comm.Parameters("@ItemPrice").Value = row.Cells(1).Value
        comm.Parameters("@OrderTotal").Value = Total

        comm.ExecuteNonQuery()
    Next row
End Using 'No need to call conn.Close(), the Using block **will** take care of this for you

要回答实际问题...默认情况下,会提交Sql Server的隐式查询批处理。您可以更改此默认值,但很少见到。最有可能的是,这里更高级别的一些代码是吞噬由错误的sql语法产生的异常。这是一种糟糕的编码习惯,所以你可能想要追踪到哪里。