C# 中的 SQL 参数化,使用 SQL 声明的变量
Posted
技术标签:
【中文标题】C# 中的 SQL 参数化,使用 SQL 声明的变量【英文标题】:SQL paramaterisation in C#, using SQL declared variables 【发布时间】:2021-07-21 15:48:04 【问题描述】:我有以下从 C# 程序发送的 SQL 查询:
DECLARE @id as int
SELECT @id = max(fault_catagory_ident) FROM fault_catagory_list
INSERT INTO fault_catagory_list (fault_catagory_ident, fault_catagory)
VALUES (@id + 1, 'TEST')
SELECT @id + 1
'fault_catagory' 值来自我的程序,但 ident 值需要是数据库中现有表中的下一个数字(主键)。我的 C# 代码正在参数化安全值。
我有两个问题:
-
如何将@id + 1 值返回给我的程序(executeNonQuery 不返回任何内容)?
如何获取 @id 作为插入命令的参数化值?
我想知道我的主键是否可以以某种方式自动化?
我想在一个查询中完成所有这些操作,因为会有多个登录运行同一查询的风险。如果有任何碰巧同时运行,@id 值可能会重复,并且会失败。
抱歉,如果这里没有足够的信息,我正在学习中!
任何建议将不胜感激。提前致谢。
【问题讨论】:
您正在寻找IDENTITY()
功能
永远不要使用这样的代码。它保证重复值。这也是完全没有必要的。您可以创建一个带有IDENTITY
约束的列,让数据库生成唯一值
您可以轻松编写单个INSERT
并使用OUTPUT
子句返回任何生成的值。将IDENTITY
约束添加到fault_catagory_ident
并使用INSERT INTO fault_catagory_list (fault_catagory) OUTPUT inserted.fault_catagory_ident VALUES ('TEST')
检索生成的值
【参考方案1】:
我认为你会在 MSDN 提供的这个例子中找到你需要的一切: https://docs.microsoft.com/en-us/dotnet/api/system.data.sqlclient.sqlcommand.executescalar?view=dotnet-plat-ext-5.0
简而言之:
-
要从查询中返回单个参数,请使用 ExecuteScalar()
通过 System.Data.SqlClient 中提供的 SqlCommand 类将参数添加到查询中。
干杯!
【讨论】:
谢谢,这肯定有助于返回我想要的值。【参考方案2】:感谢您的建议,我想我已经找到了解决方案... 首先,我需要使用 IDENTITY 约束重新创建具有主键列的表(现在使用它很有意义,我知道它存在!)。在这里找到了一个指南(尽管这将意味着一些主/外键链接的重建)https://www.datameer.com/blog/how-to-add-an-identity-to-an-existing-column-in-sql/
然后在C#程序中,使用SqlCommand.executeScalar返回标识值
Int identReturn = 0;
identReturn = (Int32)cmd.ExecuteScalar();
再次感谢您的回复。
【讨论】:
【参考方案3】:虽然我不同意您为插入的行选择标识行值的逻辑,但您当然可以在 SQL 表定义中使用 IDENTITY()
列属性来实现这一点。
如果您的 SQL 命令中有多个 SELECT, 每次您在 sql 命令中有一个 SELECT 时,都会将一个新表添加到传入的数据集到数据适配器中。
string sql = "
DECLARE @id as int
SELECT @id = max(fault_catagory_ident) FROM fault_catagory_list
INSERT INTO fault_catagory_list (fault_catagory_ident, fault_catagory)
VALUES (@id + 1, 'TEST')
SELECT @id + 1";
SqlCommand cmd = new SqlCommand(sql, conn); // assuming you already set connection
SqlDataAdapter da = new SqlDataAdapter(cmd);
DataSet ds = new DataSet();
da.Fill(ds);
Console.WriteLine( ds.Tables[0].Rows[0][0]); // this will print @id
Console.WriteLine( ds.Tables[1].Rows[0][0]); // this will print @id + 1
【讨论】:
这不是一个查询,但只有一个结果集。SELECT @id
-...` 设置变量,它不返回任何东西。 cmd.ExecuteScalar
将返回递增的 ID。一个更大的问题是这段代码会产生重复的值以上是关于C# 中的 SQL 参数化,使用 SQL 声明的变量的主要内容,如果未能解决你的问题,请参考以下文章
SQL Server参数化SQL语句中的like和in查询的语法(C#)
SQL Server参数化SQL语句中的like和in查询的语法(C#)