3

我有一个用 VB.NET 编写的 ASP.NET 页面,它GridView通过使用SELECT语句将项目放入 a 中,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

@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
4

2 回答 2

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);

现在您只需调用一个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

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

于 2013-04-18T13:03:23.883 回答
0
ItemId = AddNewItemSQL.ExecuteScalar()

        AddNewItemSQL.ExecuteNonQuery()

相邻的这两行将执行该命令两次。您应该删除第二个 - ExecuteNonQuery。这会将您的数据插入两次Items- 两个相同的行但具有不同的 ID。

由于您只从第一行检索 ItemID,因此应该将那个插入到 中project_items,但最后插入到 items 中的另一个将没有匹配的行。

此外 - 从按钮单击方法开始的完整部分之前Dim AddNewItemComm As String- 打开和关闭 DataReader 并且不对其执行任何操作似乎完全没有必要。

于 2013-04-18T12:55:56.437 回答