连接到 SQL 服务器数据库
Connection to SQL Server database
一个 .NET 应用程序,从中建立连接并按如下方式执行查询(包装在 try-catch 块中):
using (SqlConnection conn = new SqlConnection(Configuration.connectionString))
{
SqlCommand cmd = new SqlCommand(createTransactionQuery,conn);
conn.Open();
return cmd.ExecuteNonQuery();
}
查询字符串是:
createTransactionQuery = "BEGIN " +
"BEGIN Transaction" +
" BEGIN TRY " +
" --variables" +
" DECLARE @varStaffID int;" +
" DECLARE @varProductID int;" +
" SET @varStaffID = " + transaction.getStaff().getID() + ";" +
" SET @varProductID = " + transaction.getProduct().getProductID() + ";" +
" " +
" --New record in Transactions table " +
" INSERT INTO Transactions (Timestamp_, CustomerID, StaffID, ProductID) " +
" VALUES (SYSDATETIME(),NULL,@varStaffID,@varProductID; " +
" " +
" --Update inventory (Products table)" +
" --First retrieve the current quantity of this product" +
" DECLARE @varCurrQuantity int; " +
" SET @varCurrQuantity = (SELECT Quantity FROM Products WHERE ProductID=@varProductID); " +
" --and update it" +
" UPDATE Products " +
" SET Quantity = @varQuantity-1 " +
" WHERE ProductID = @varProductID; " +
" END TRY " +
" BEGIN CATCH " +
" ROLLBACK Transaction " +
" END CATCH " +
"COMMIT Transaction" +
"END";
此代码抛出异常:
System.Exception: Incorrect syntax near 'BEGIN'.
我知道可以用更好的方式创建查询字符串。但是,我想知道问题的原因是什么,因为这个确切的查询在 SQL Server Management Studio 本身内执行时有效。
我已经确定连接字符串是正确的,因为它在应用程序的不同部分完全正常工作。
您可以试试这个进行交易。从您的代码中删除第一个开始和最后一个结束并按照以下说明操作:
BEGIN TRANSACTION trans
BEGIN TRY
--Do some insert or update
COMMIT TRANSACTION trans
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION trans
END CATCH
你好像少了一个右括号:
VALUES (SYSDATETIME(),NULL,@varStaffID,@varProductID; "
然而,这种字符串连接对 SQL 注入攻击是开放的。您应该始终使用 parameterized queries to avoid SQL Injection 并消除此类错误。
要了解如何使用参数化查询,请参阅下面的示例:
您在 "COMMIT Transaction" + "END";
之间错过了一个 space
使用这个 "COMMIT Transaction" + " END";
此外,您还没有声明 varQuantity
并且在后面错过了一个右括号
" VALUES (SYSDATETIME(),NULL,@varStaffID,@varProductID; "
一个 .NET 应用程序,从中建立连接并按如下方式执行查询(包装在 try-catch 块中):
using (SqlConnection conn = new SqlConnection(Configuration.connectionString))
{
SqlCommand cmd = new SqlCommand(createTransactionQuery,conn);
conn.Open();
return cmd.ExecuteNonQuery();
}
查询字符串是:
createTransactionQuery = "BEGIN " +
"BEGIN Transaction" +
" BEGIN TRY " +
" --variables" +
" DECLARE @varStaffID int;" +
" DECLARE @varProductID int;" +
" SET @varStaffID = " + transaction.getStaff().getID() + ";" +
" SET @varProductID = " + transaction.getProduct().getProductID() + ";" +
" " +
" --New record in Transactions table " +
" INSERT INTO Transactions (Timestamp_, CustomerID, StaffID, ProductID) " +
" VALUES (SYSDATETIME(),NULL,@varStaffID,@varProductID; " +
" " +
" --Update inventory (Products table)" +
" --First retrieve the current quantity of this product" +
" DECLARE @varCurrQuantity int; " +
" SET @varCurrQuantity = (SELECT Quantity FROM Products WHERE ProductID=@varProductID); " +
" --and update it" +
" UPDATE Products " +
" SET Quantity = @varQuantity-1 " +
" WHERE ProductID = @varProductID; " +
" END TRY " +
" BEGIN CATCH " +
" ROLLBACK Transaction " +
" END CATCH " +
"COMMIT Transaction" +
"END";
此代码抛出异常:
System.Exception: Incorrect syntax near 'BEGIN'.
我知道可以用更好的方式创建查询字符串。但是,我想知道问题的原因是什么,因为这个确切的查询在 SQL Server Management Studio 本身内执行时有效。
我已经确定连接字符串是正确的,因为它在应用程序的不同部分完全正常工作。
您可以试试这个进行交易。从您的代码中删除第一个开始和最后一个结束并按照以下说明操作:
BEGIN TRANSACTION trans
BEGIN TRY
--Do some insert or update
COMMIT TRANSACTION trans
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION trans
END CATCH
你好像少了一个右括号:
VALUES (SYSDATETIME(),NULL,@varStaffID,@varProductID; "
然而,这种字符串连接对 SQL 注入攻击是开放的。您应该始终使用 parameterized queries to avoid SQL Injection 并消除此类错误。
要了解如何使用参数化查询,请参阅下面的示例:
您在 "COMMIT Transaction" + "END";
之间错过了一个 space
使用这个 "COMMIT Transaction" + " END";
此外,您还没有声明 varQuantity
并且在后面错过了一个右括号
" VALUES (SYSDATETIME(),NULL,@varStaffID,@varProductID; "