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

SQL Server参数化SQL语句中的like和in查询的语法(C#)

如何在 C# 中创建动态参数化 SQL 查询字符串

sql参数化查询

如何避免从 C# 构建的 Sql Server 2005 参数化查询变慢