Выполнение INSERT из вывода столбца идентификаторов в VB.NET - PullRequest
0 голосов
/ 19 июня 2020

Использование VB. NET и SQL Сервер: у меня есть таблица [Item_List]. Когда я добавляю новый элемент из формы Windows, я хочу вставить запись в таблицу Item_List, получить ItemID, который является IDENTITY, и использовать его для вставки соответствующей записи в финансовое отслеживание. [Inventory_Transactions] table.

Я успешно протестировал следующий запрос непосредственно в окне запроса T- SQL:

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(), я получаю ошибка

Недопустимое имя столбца '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?

Ответы [ 2 ]

2 голосов
/ 19 июня 2020

Я только что протестировал этот код, и он работал точно так, как ожидалось:

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()
1 голос
/ 19 июня 2020

Думаю, это:

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

должно быть:

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