问题描述
我有两个数据表。第一个是书,第二个是作者。 book表的字段:
预订
图书 ID(PK)
作者ID
书名
...
作者
作者 ID (PK)
作者姓名
1-Book Name,Author name 将写入 Windows 窗体应用程序的文本框中,并单击保存按钮。作者姓名将首先保存在'author'表中,并创建id作为自动pk密钥。
2-文本框上写的'author name'和author表中对应的id会被取用。
3- 最后,书名和作者 id 将记录在“书”表中。
举个例子:
Windows 窗体应用程序中的文本框:
书名:IT
作者姓名:斯蒂芬·金
点击保存按钮。
作者表
AuthorID:97(自动分配)
作者姓名:斯蒂芬·金
书桌
图书编号:11
作者 ID:97
书名:IT
简而言之,只需单击一下,即可同时拥有作者和图书记录以及数据库。
string sqlcom1 = "INSERT INTO author (authorName) VALUES(@Pauthor)";
commandobject = new sqlCommand(sqlcom1,connectionObject );
commandobject.Parameters.AddWithValue("@Pauthor",textBoxauthorName.Text);
string sqlcom2 = "SELECT authorID FROM author WHERE authorName='" + textBoxauthorName.Text + "'");
commandobject = new sqlCommand(sqlcom2,connectionObject );
string sqlcom3 = "INSERT INTO book (bookName,authorID) VALUES(@PbookName,@PauthorID)";
commandobject = new sqlCommand(sqlcom3,connectionObject);
commandobject.Parameters.AddWithValue("@PbookName",textBoxbookName.Text);
commandobject.Parameters.AddWithValue("@PauthorID",sqlcom2);
connectionObject.open();
commandobject.ExecuteNonQuery();
connectionObject.Close();
错误: '将 nvarchar 值 'SELECT authorID FROM author WHERE authorName='author30'' 转换为数据类型 int 时转换失败。'
author30 --> 我在文本框中输入的作者姓名值。
注意:我可以看到,通过注册到作者表,名称会自动分配 id。正在向作者表注册。
作者 ID 与书表中的作者 ID 相关联。
解决方法
解决方案
connectionObject.Open();
string sqlcom1 = "INSERT INTO author (authorName) VALUES(@Pauthor); SELECT SCOPE_IDENTITY()";
commandObject= new SqlCommand(sqlcom1,connectionObject);
commandObject.Parameters.AddWithValue("@Pauthor",textBoxauthorName.Text);
string SolutionVariable = commandObject.ExecuteScalar().ToString();
string sqlcom3 = "INSERT INTO book (bookName,authorID) VALUES(@PbookName,@PauthorID)";
commandObject = new SqlCommand(sqlcom3,connectionObject);
commandObject.Parameters.AddWithValue("@PbookName",textBoxbookName.Text);
commandObject.Parameters.AddWithValue("@PauthorID",SolutionVariable);
commandObject.ExecuteNonQuery();
connectionObject.Close();
,
SQLServer 支持一个名为 OUTPUT 的子句,用于(除其他外)INSERT 语句,它允许您为所有插入的值检索一组行。这比选择 SCOPE_IDENTITY 更有用,因为它允许您检索多个值;你可以插入 N 行,每插入一行检索 O 列,例如
INSERT INTO T(CreateDate,A,B,C) --imagine that T has a PK int autonumber
OUTPUT inserted.PK,inserted.CreateDate
VALUES (GetUtcDate(),'A','BB','CCC'),(GetUtcDate(),'A2','BB2','CCC2')
ExecuteReader()
执行此操作(而不是 NonQuery)将使用插入值的 2x2 结果集进行响应 - PK 和由 DB 计算的日期。您当然也可以在 1x1 模式下使用它(并执行标量它),但通常对于 SQL,我们的目标应该是处理数据集
您需要使用 SCOPE_IDENTITY()
获取插入的 ID,并将其传递给另一个表。在单个命令中执行此操作。
您的代码还有许多其他问题:
- SQL 注入风险
- 您没有正确处理连接
- 您应该为
varchar
参数使用正确的长度
我将演示如何正确执行此操作
const string query = @"
INSERT INTO author (authorName)
VALUES(@Pauthor);
INSERT INTO book (bookName,authorID)
VALUES(@PbookName,SCOPE_IDENTITY());
";
using(var connectionObject = new SqlConnection(connString))
using(var commandObject = new SqlCommand(query,connectionObject))
{
commandObject.Parameters.Add("@Pauthor",SqlDbType.VarChar,100).Value = textBoxauthorName.Text;
commandObject.Parameters.Add("@PbookName",100).Value = textBoxbookName.Text;
connectionObject.Open();
commandObject.ExecuteNonQuery();
}
如果您有多行,则需要使用 OUTPUT
子句。同样,您可以在单个批处理命令中执行此操作,只需先将其发送到表变量即可。