从 VB.NET 中的标识列输出执行 INSERT

Executing INSERT from Identity column Output in VB.NET

使用 VB.NET 和 SQL 服务器:我有一个 table [Item_List]。当我从 Windows 表单添加新项目时,我想将记录插入 Item_List table,得到 ItemID 这是一个 IDENTITY,并使用它在财务跟踪中插入相应的记录 [Inventory_Transactions] table.

我直接在 T-SQL 查询 window 中成功测试了以下查询:

DECLARE @OutputTbl TABLE (ItemID INT);

INSERT INTO [Item_List] (Item_Name, Vendor, Quantity, Price, Category, Active, Notes, Created) 
OUTPUT INSERTED.ItemID INTO @OutputTbl(ItemID) 
VALUES ('Test Item', 'Walmart', 42, 4.22, 'Stuff', 1, '', CURRENT_TIMESTAMP);

INSERT INTO Inventory_Transactions (TransDate, Category, Transactee, Amount, Item, Quantity, Description) 
    SELECT 
        CURRENT_TIMESTAMP, 'Stuff', 'Walmart', -4.22, ItemID, 42, '';

但是,当我尝试使用 ExecuteNonQuery() 运行 时,出现错误

Invalid column name 'ItemID'

我使用了上面和下面的确切脚本以及参数 - 同样的错误。

Dim sql As String = "DECLARE @OutputTbl TABLE (ItemID INT); " &
                    "INSERT INTO [Item_List] (Item_Name, Vendor, Quantity, Price, Category, Active, Notes, Created) " &
                    "OUTPUT INSERTED.ItemID  INTO @OutputTbl(ItemID) " &
                    "VALUES (@ItemName, @Vendor, @Quantity, @Price, @Category, @Active, @Notes, CURRENT_TIMESTAMP); " &
                    "INSERT INTO Inventory_Transactions (TransDate, Category, Transactee, Amount, Item, Quantity, Description) " &
                    "SELECT CURRENT_TIMESTAMP, @Category, @Vendor, '-' + @Price, ItemID, @Quantity, @Notes;"

Using conn As New SqlConnection(My.Settings.dbConnectionString)
        Dim cmd As New SqlCommand(sql, conn)

        If Not IsNothing(params) Then
            For Each param In params
                cmd.Parameters.Add(param)
            Next
        End If

        If cmd.Connection.State <> ConnectionState.Open Then 
           cmd.Connection.Open()

        Dim rows As Integer = cmd.ExecuteNonQuery()
End Using

如何在 VB 中实现它?

我认为:

"SELECT CURRENT_TIMESTAMP, @Category, @Vendor, '-' + @Price, ItemID, @Quantity, @Notes;"

应该是:

"SELECT CURRENT_TIMESTAMP, @Category, @Vendor, '-' + @Price, ItemID, @Quantity, @Notes from @OutputTbl;"

我刚刚测试了这段代码,它完全符合预期:

Dim sql = "INSERT INTO Parent (ParentName) VALUES (@ParentName);
           INSERT INTO Child (ChildName, ParentId) VALUES (@ChildName, SCOPE_IDENTITY())"

command.CommandText = sql
command.Parameters.Add("@ParentName", SqlDbType.NVarChar, 50).Value = "Parent1"
command.Parameters.Add("@ChildName", SqlDbType.NVarChar, 50).Value = "Child1"

command.ExecuteNonQuery()

SCOPE_IDENTITY 函数获取在当前作用域中生成的最后一个标识值。

如果您需要多次使用标识值,那么您可以将其分配给一个参数并使用它,例如

Dim sql = "INSERT INTO Parent (ParentName) VALUES (@ParentName);
           SELECT @ParentId = SCOPE_IDENTITY();
           INSERT INTO Child (ChildName, ParentId) VALUES (@ChildName, @ParentId)"

command.CommandText = sql
command.Parameters.Add("@ParentName", SqlDbType.NVarChar, 50).Value = "Parent1"
command.Parameters.Add("@ParentId", SqlDbType.Int).Direction = ParameterDirection.Output
command.Parameters.Add("@ChildName", SqlDbType.NVarChar, 50).Value = "Child1"

command.ExecuteNonQuery()

如果您需要在 VB 代码中使用身份值,那么也可以使用这样的参数:

Dim parentSql = "INSERT INTO Parent (ParentName) VALUES (@ParentName);
                 SELECT @ParentId = SCOPE_IDENTITY();"

parentCommand.CommandText = parentSql
parentCommand.Parameters.Add("@ParentName", SqlDbType.NVarChar, 50).Value = "Parent1"
parentCommand.Parameters.Add("@ParentId", SqlDbType.Int).Direction = ParameterDirection.Output

parentCommand.ExecuteNonQuery()

Dim childSql = "INSERT INTO Child (ChildName, ParentId) VALUES (@ChildName, @ParentId)"

childCommand.CommandText = childSql
childCommand.Parameters.Add("@ChildName", SqlDbType.NVarChar, 50).Value = "Child1"
childCommand.Parameters.Add("@ParentId", SqlDbType.Int).Value = parentCommand.Parameters("@ParentId").Value

childCommand.ExecuteNonQuery()