在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
答案 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语法产生的异常。这是一种糟糕的编码习惯,所以你可能想要追踪到哪里。