【问题标题】:How to create a stored procedure with dynamically created IN set如何使用动态创建的 IN 集创建存储过程
【发布时间】:2017-06-16 20:41:18
【问题描述】:

我有一些 SQL 正在通过盲目需求/请求转换为存储过程。我正在查看的应用程序中有一些 SQL 使用动态 IN(set)语句构建 where 子句。我已经搜索了动态存储过程,但没有找到接近我正在寻找的东西。这是 WHERE 子句的示例:

WHERE Var.A = @Param AND Var.Id IN

从这里开始,使用字符串构建器手动构建 SQL,然后执行。不知道如何将其转换为存储过程,因为我对它们还很陌生。

我们正在使用 C# 和 SQL Server

【问题讨论】:

  • 如何将用户定义的表类型从 C# 发送到 proc?
  • 听起来不错。但我不知道那是什么意思。我会研究这个角度。谢谢大声笑
  • @Matt1776:根据各种因素,IN 子句可以是从良性到病态的不良重新性能。由于 IN 子句的要点是过滤返回的行,这也是 INNER JOIN 子句(除了引入额外的列之外),执行 INNER JOIN 而不是 IN 总是足够而且通常更好。 (回想一下:INNER JOIN 只返回 BOTH 表中具有匹配连接字段的行。)
  • @PieterGeerkens 我喜欢你的想法——但是由于 SQL 不是我的主要专长——我将如何使用内部连接来指定值列表?查询正在查找 ID 等于动态 ID 列表的位置。没有其他方法可以指定所需的结果 afaik

标签: c# sql sql-server stored-procedures sql-server-2012


【解决方案1】:

您可以使用用户定义的数据类型。

在 C# 端它看起来像这样:

//Setup a DataTable with the same structure as the SQL Type
var data = new DataTable();
data.Columns.Add("value", typeof(string));

//Populate the table
data.Rows.Add("oneID");
data.Rows.Add("anotherID");

//You create your sql command
cmd.Parameters.Add("@listArgument", data);
//Command execution

在 SQL 方面,你可以有这样的类型

CREATE TYPE [dbo].[NVarCharTable] AS TABLE (
    [value] NVARCHAR(MAX) NOT NULL);

然后是存储过程:

CREATE PROCEDURE [dbo].[MyProc] 
    @listArgument NVarCharTable READONLY
AS
BEGIN

    SELECT *
    FROM FOO
    WHERE Var.Id IN (Select [value] FROM @listArgument)

END

参考:https://docs.microsoft.com/en-us/dotnet/framework/data/adonet/sql/table-valued-parameters

【讨论】:

  • 那……很美。这似乎类似于创建一个临时视图,但这被称为用户定义的表类型?我会看看这是否有效!
  • 我添加了一个参考链接来阅读,我使用 DataTables 但有很多方法可以从 C# 中使用它
  • 老实说,我花了很长时间才能让它发挥作用 - 这绝对是由于我缺乏这种方法的经验。当我在 SQL Server 中执行存储过程时,如何设置 [NVarCharTable] 的值?它只给了我一个无法编写 SQL 的窗口界面
  • @Matt1776 不用担心。我已经改进了这个例子。基本上你需要一个与 SQL 表类型结构相同的 DataTable,你像一个普通的 DataTable 一样填充它(它是一个普通的 DataTable),然后你将它添加到 SQL 参数中
  • 原来一切都很好,我只是将错误的 SQL 复制到存储过程创建语句中。这工作得很好!谢谢!知道我的运气的客户会回来说我不能使用用户定义的表类型,但是当我到达那里时我会越过那座桥。
【解决方案2】:

如果您使用的是 SQl SERVER 2016 或更高版本,您可以使用 string_split 函数将 csv 参数转换为表格,然后在您的 IN 列表中使用它

例如

SELECT * FROM TBL WHERE Var.A = @Param AND Var.Id IN (SELECT value FROM STRING_SPLIT(@inlist, ','))

希望对你有帮助

【讨论】:

  • 唉,我们被锁定到 SQLServer 2012,但这看起来像是一个有效的、更简单的选项,因为拆分返回一个表。试一试就好了。
  • 有很多函数可以获取值列表并拆分为表格。只需谷歌它 - sql server central 至少有 3 个版本。所以这种方法在其他版本中也是可行的,只增加了1个函数。
  • @Jesse 经过一些粗略的研究后,我只找到了一种方法,您可以创建一个调用 dll 的函数 - 您有什么特别的想法吗?仔细阅读 SQLServer 文档后,我没有看到任何我可以使用的不会太繁重的东西。
  • 我将其添加为答案。第二个链接可能比第一个链接慢,但添加到数据库所需的精力更少。另一个使用数字表,但似乎没有创建它。顺便说一句,我使用的搜索是拆分字符串 t-sql 函数。
【解决方案3】:

要背负@lostmylogin,您可以传入一个带分隔符的参数并使用这些SQL 函数之一将其解析为一个表:

http://sqlservercentral.com/scripts/SUBSTRING/124330 或者 http://sqlservercentral.com/scripts/Miscellaneous/31913

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-07-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-19
    • 1970-01-01
    • 2012-05-01
    • 1970-01-01
    相关资源
    最近更新 更多