SQL-使用Scope_Identity()插入-获取记录ID

Bri*_*ian 2 sql t-sql vb.net asp.net sql-server-2012

我有一个用VB.NET编写的ASP.NET页面,该页面GridView通过使用SELECT语句将项目放入,INNER JOIN并且还允许您将项目添加到发票中。

INNER JOINitems和获取数据project_items

SELECT Items.item_id, Items.item_name, Items.item_cost, project_items.item_quantity
FROM Items 
INNER JOIN project_items
ON items.item_id = project_items.item_id 
WHERE project_items.project_id = @parameter
Run Code Online (Sandbox Code Playgroud)

@parameter is Session("ProjectID")

(有一个外键project_items.item_id -> items.item_id。)

我试图在VB.NET中使用SQL语句尝试同时将INSERT插入两个表中。我所尝试的是尝试获取item_id最后创建的记录的,并project_items使用该数据将其插入到另一个表()中。但是,数据仅输入到第一个表中。

知道我能做什么吗?

这是代码:

Protected Sub btnAddItem_Click(sender As Object, e As EventArgs) Handles btnAddItem.Click

        Dim conn As New SqlConnection("Data Source=BRIAN-PC\SQLEXPRESS;Initial Catalog=master_db;Integrated Security=True")
        Dim addItemComm As String = "SELECT item_id FROM project_items WHERE project_id=@ProjectID"
        Dim user_id_select As New Integer

        Dim addItemSQL As New SqlCommand

        conn.Open()

        addItemSQL = New SqlCommand(addItemComm, conn)
        addItemSQL.Parameters.AddWithValue("@ProjectID", Convert.ToInt32(Session("ProjectID")))


        Dim datareader As SqlDataReader = addItemSQL.ExecuteReader()


        datareader.Close()
        conn.Close()

        Dim AddNewItemComm As String = "INSERT INTO Items (item_name,  item_cost, item_code) VALUES (@ItemName, @ItemCost, @ItemCode); SELECT SCOPE_IDENTITY()"
        Dim AddNewItem2Comm As String = "INSERT INTO project_items (item_id, project_id, item_quantity) VALUES (@ItemID, @ProjectID, @ItemQuantity) "
        Dim AddNewItemSQL As New SqlCommand


        conn.Open()

        AddNewItemSQL = New SqlCommand(AddNewItemComm, conn)
        AddNewItemSQL.Parameters.AddWithValue("@ItemName", txtItemName.Text.Trim)
        AddNewItemSQL.Parameters.AddWithValue("@ItemCost", Convert.ToInt32(txtItemCost.Text))
        AddNewItemSQL.Parameters.AddWithValue("@ItemCode", txtItemCost.Text.ToString.ToUpper)

        Dim ItemId As Integer

        ItemId = AddNewItemSQL.ExecuteScalar()

        AddNewItemSQL.ExecuteNonQuery()

        conn.Close()

        conn.Open()

        AddNewItemSQL = New SqlCommand(AddNewItem2Comm, conn)

        AddNewItemSQL.Parameters.AddWithValue("@ItemID", ItemId)
        AddNewItemSQL.Parameters.AddWithValue("@ProjectID", Convert.ToInt32(Session("ProjectID")))
        AddNewItemSQL.Parameters.AddWithValue("@ItemQuantity", Convert.ToInt32(txtItemQuantity.Text))

        AddNewItemSQL.ExecuteNonQuery()

        conn.Close()



    End Sub
Run Code Online (Sandbox Code Playgroud)

Aar*_*and 5

为什么首先要在多个语句中执行此操作?为什么不:

INSERT dbo.Items (item_name,  item_cost, item_code) 
  OUTPUT inserted.ItemID, @ProjectID, @ItemQuantity 
  INTO dbo.project_items(item_id, project_id, item_quantity)
VALUES (@ItemName, @ItemCost, @ItemCode);
Run Code Online (Sandbox Code Playgroud)

现在,您只需要调用一个ExecuteNonQuery(),您的应用程序就不必关心所SCOPE_IDENTITY()产生的实际价值。(SCOPE_IDENTITY()当然,您仍然可以使用ExecuteScalar- 检索,但是正如Nenad正确指出的那样,选择一个而不是同时调用两者。)

由于我们现在知道这里有一个明确的外键,因此即使我们不能使用该OUTPUT子句,我们仍然可以将您的C#代码减少为一次调用。

DECLARE @i INT;

INSERT dbo.Items (item_name,  item_cost, item_code) 
  SELECT @ItemName, @ItemCost, @ItemCode;

SELECT @i = SCOPE_IDENTITY();

INSERT dbo.project_items(item_id, project_id, item_quantity)
  SELECT @i, @ProjectID, @ItemQuantity 

SELECT @i; -- if necessary
Run Code Online (Sandbox Code Playgroud)

将其放入存储过程中甚至会更加干净。