在外键的 id 列中插入值
Posted
技术标签:
【中文标题】在外键的 id 列中插入值【英文标题】:Insert values in id columns for foreign keys 【发布时间】:2021-12-31 13:43:08 【问题描述】:如图所示,我有三张桌子。我想加入这三个表,并将应用程序表单中的所有数据插入Produse
、Clienti
和Comenzi
表中。
除了Comenzi
表中的两列(IDClient
和IDProdus
)外,一切正常。它们都是int
类型和其他两个表的外键,我不能让它们Identity
自动增加ID。
所以当我按下应用表单中的提交按钮时程序崩溃了。
无法将值 NULL 插入到列“IDClient”、表“dbo.Tmp_Comenzi”中;列不允许空值。插入失败。
如果我允许空值,它不会引发错误,但该列将为空值。应用程序表单的这两列中没有任何值,所以我必须找到一种方法为它们提供值,还是有其他方法?
我无法手动填充它们。我不太擅长 SQL 连接和表关系,可能是我做错了什么。
如何才能成功插入数据?
好吧,我创建了 3 个存储过程
CREATE PROCEDURE [dbo].[InsertProducts]
@DenProd nvarchar(50),
@ProdQuant nvarchar(50),
@ProdSize nvarchar(50),
@ProdComm nvarchar(50)
作为
BEGIN
INSERT INTO Produse (Denumire, Cantitate, Dimensiuni, Comentarii) VALUES (@DenProd, @ProdQuant, @ProdSize, @ProdComm)
END
创建过程 [dbo].[InsertClients]
@NumeClient nvarchar(50)
作为
BEGIN
INSERT INTO Clienti (NumeClient) VALUES (@NumeClient)
END
创建过程 [dbo].[InsertOrders]
-- @ClientID int,
-- @ProductID int,
@StartDate date,
@FinishDate date,
@Billed nvarchar(50),
@Delivered nvarchar(50)
作为
BEGIN
INSERT INTO Comenzi (IDClient) SELECT IDClient FROM Clienti;
INSERT INTO Comenzi (IDProdus) SELECT IDProdus FROM Produse;
INSERT INTO Comenzi (DataInceput, DataSfarsit, Facturata, Livrata) VALUES (@StartDate, @FinishDate, @Billed, @Delivered)
END
前两个程序完美运行。三是问题。
插入代码:
private void InsertOrderButton_Click(object sender, EventArgs e)
SqlCommand cmd = new SqlCommand("InsertClients", con);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("@NumeClient", textBoxClientNou.Text);
con.Open();
cmd.ExecuteNonQuery();
con.Close();
textBoxClientNou.Text = "";
foreach (ListViewItem item in ListaProduse.Items)
SqlCommand cmd2 = new SqlCommand("InsertProducts", con);
cmd2.CommandType = CommandType.StoredProcedure;
cmd2.Parameters.AddWithValue("@DenProd", item.Text);
cmd2.Parameters.AddWithValue("@ProdQuant", item.SubItems[1].Text);
cmd2.Parameters.AddWithValue("@ProdSize", item.SubItems[1].Text);
cmd2.Parameters.AddWithValue("@ProdComm", item.SubItems[1].Text);
con.Open();
cmd2.ExecuteNonQuery();
con.Close();
SqlCommand cmd3 = new SqlCommand("InsertOrders", con);
cmd3.CommandType = CommandType.StoredProcedure;
cmd3.Parameters.AddWithValue("@StartDate", dateTimePicker1.Text);
cmd3.Parameters.AddWithValue("@FinishDate", dateTimePicker2.Text);
cmd3.Parameters.AddWithValue("@Billed", factstatus);
cmd3.Parameters.AddWithValue("@Delivered", livstatus);
con.Open();
cmd3.ExecuteNonQuery();
con.Close();
comboBoxClient.Text = "";
dateTimePicker1.Text = "";
dateTimePicker2.Text = "";
textBoxClientNou.Text = "";
ListaProduse.Items.Clear();
MessageBox.Show("Succesful insert");
现在我收到这些错误:
Cannot insert the value NULL into column 'IDProdus', table 'DatabaseName.dbo.Comenzi'; column does not allow nulls. INSERT fails.
Cannot insert the value NULL into column 'IDClient', table 'DatabaseName.dbo.Comenzi'; column does not allow nulls. INSERT fails.
在 InsertOrders 过程中,我尝试插入其他表中的值,但什么也没有。我尝试了各种查询。
现在我得到了这段代码:
SqlCommand cmd2 = new SqlCommand("InsertProducts", con);
cmd2.CommandType = CommandType.StoredProcedure;
foreach (ListViewItem item in ListaProduse.Items)
cmd2.Parameters.AddWithValue("@DenProd", item.Text);
cmd2.Parameters.AddWithValue("@ProdQuant", item.SubItems[1].Text);
cmd2.Parameters.AddWithValue("@ProdSize", item.SubItems[1].Text);
cmd2.Parameters.AddWithValue("@ProdComm", item.SubItems[1].Text);
var IDProductParameter = cmd2.Parameters.Add("@ProdID", SqlDbType.Int);
IDProductParameter.Direction = ParameterDirection.Output;
con.Open();
cmd2.ExecuteNonQuery();
var IDProdus = (int)IDProductParameter.Value;
con.Close();
它适用于具有四列的列表视图,用于在数据库中发送值。它适用于 1 种产品。如果我在列表中添加另一个产品并将其插入数据库,我会收到错误:
过程或函数 InsertProducts 指定的参数过多。
这是程序:
CREATE PROCEDURE [dbo].[InsertProducts]
@DenProd nvarchar(50),
@ProdQuant nvarchar(50),
@ProdSize nvarchar(50),
@ProdComm nvarchar(50),
@ProdID INT OUTPUT
AS
BEGIN
INSERT INTO Produse (Denumire, Cantitate, Dimensiuni, Comentarii) VALUES (@DenProd, @ProdQuant, @ProdSize, @ProdComm);
SELECT @ProdID = SCOPE_IDENTITY();
END
【问题讨论】:
“我不能让他们的身份自动增加id”,你为什么不能这样做? 数据应首先插入 Produse、Clienti 表中,然后应正确映射两个表中的标识列值以插入到 Comenzi 表中。您的映射中似乎存在问题,您从应用程序中传递了两个键的值。 只使用EF Core;它会为你做这一切 但是将关系的子端设置为自动增量是没有意义的,因为那样您将无法设置该值,并且您需要能够将该值设置为创建相关记录 当我在应用程序表单中按下提交按钮时程序崩溃。 那么您能否edit 分享一个minimal reproducible example 重现问题?来自How to Ask:如果您的问题与您编写的代码有关,您应该包含一些......包含足够的代码以允许其他人重现问题。我们只能猜测你做错了什么,所以如果我们不必猜测,你更有可能得到帮助——因为你已经告诉我们了。 【参考方案1】:首先您插入 Produse 和 Clienti 表并获取这些 ID 并在插入 Comenzi 表时发送这些值。您如何获得我正在共享的示例存储过程
CREATE PROCEDURE Usp_Insert_Produse
@col1 VARCHAR(50),
@new_identity INT OUTPUT
AS
BEGIN
SET NOCOUNT ON
INSERT INTO Produse(col1)
VALUES (@col1)
SELECT @new_identity = SCOPE_IDENTITY()
SELECT @new_identity AS id
RETURN
END
【讨论】:
【参考方案2】:您的前两个存储过程应该有输出参数来返回新的 IDClient 和 IDProdus。然后应用程序代码可以接收这些值并将它们作为参数提交给第三个存储过程。
这里以第一步为例。
CREATE PROCEDURE [dbo].[InsertClients]
@NumeClient nvarchar(50),
@IDClient INT OUTUT
AS
BEGIN
INSERT INTO Clienti (NumeClient) VALUES (@NumeClient);
SELECT @IDClient = SCOPE_IDENTITY();
END
应用
SqlCommand cmd = new SqlCommand("InsertClients", con);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("@NumeClient", textBoxClientNou.Text);
var IDClientParameter = cmd.Parameters.Add("@IDClient", SqlDbType.Int);
IDClientParameter.Direction = ParameterDirection.Output;
con.Open();
cmd.ExecuteNonQuery();
var IDClient = (int) IDClientParameter.Value;
con.Close();
【讨论】:
以上是关于在外键的 id 列中插入值的主要内容,如果未能解决你的问题,请参考以下文章
MySQL - 无法在列中插入 NULL 值,但我指定了默认值?