【问题标题】:SQL Server - Construct a dynamic where clause based on the records inside a tableSQL Server - 根据表内的记录构造动态 where 子句
【发布时间】:2019-08-25 19:55:39
【问题描述】:

我有一个名为dbo.ItemTagTransactions 的表,如下所示:

PK_ID | ItemTag
1     | Filename.xlsx
2     | ABC7798
3     | {empty string}
4     | Completed

如何根据上表中ItemTag 列中的值构造动态WHERE 子句?此表可能有一条或多条记录。

我将使用的查询如下所示:

SELECT FK_QueueItem_ItemTagTransaction 
FROM dbo.ItemTagTransactions 
WHERE TagValue = {insert dynamic where clause here}

WHERE 子句中的字段总是引用 TagValue,它可以是 1 或更多。它基于一个由分号分隔的字符串,就像这样。 "文件名.xlsx;ABC7798;;已完成"

想要的结果是这样的:

SELECT FK_QueueItem_ItemTagTransaction 
FROM dbo.ItemTagTransactions 
WHERE TagValue = 'Filename.xlsx' 
   OR TagValue = 'ABC7798' 
   OR TagValue = '' 
   OR TagValue = 'Completed'

附:我将在存储过程中使用它

【问题讨论】:

  • 你在说什么?由于您使用的是存储过程,只需将 @Variable 传递给您的 proc 和 WHERE TagValue = @Variable
  • 样本数据最好使用DDL + DML。请edit您的问题包括它,您当前的尝试和您想要的结果。更多详情,read this.
  • 好吧,您只需要一个 where 子句,例如 where TagValue in ([split my ; delimited string])。因此,如果您在 SQL 中使用 Google 拆分分隔字符串。
  • 表格非常适合与in 子句一起使用。 where tagValue in (select Value from SplitStringTable)
  • @thecodeexplorer - 你真好 :) 但 MarcinJ 也给出了答案,所以给他吧。

标签: sql sql-server tsql select where


【解决方案1】:

如果您的输入是用分号分隔的,您可以简单地将这些分号替换为 ', ' 并用 ' 将其包裹起来以形成有效的值列表:

DECLARE @sampleInput NVARCHAR(MAX) = 'Filename.xlsx;ABC7798;;Completed'

DECLARE @Query NVARCHAR(MAX)

SET @Query = 'SELECT FK_QueueItem_ItemTagTransaction FROM dbo.ItemTagTransactions WHERE TagValue IN (' 
           + CONCAT('N''', REPLACE(@sampleInput, ';', ''',N'''), '''')
           + ')'

PRINT @Query

它会输出:

SELECT FK_QueueItem_ItemTagTransaction FROM dbo.ItemTagTransactions WHERE TagValue IN (N'Filename.xlsx',N'ABC7798',N'',N'Completed')

如果要执行查询并存储结果以供进一步处理,请创建临时表:

CREATE TABLE #results
(
    FK_QueueItem_ItemTagTransaction INT -- adjust the
);

INSERT INTO #results
EXEC sp_executesql @Query

如果你有一个返回表格的字符串拆分函数,那就更简单了,你只需使用

SELECT FK_QueueItem_ItemTagTransaction 
  INTO #results -- for further processing
  FROM dbo.ItemTagTransactions 
 WHERE TagValue IN (SELECT Value 
                      FROM dbo.mySplitStringFunction(@sampleInput))

【讨论】:

    【解决方案2】:

    我希望这对你有用。

    SELECT FK_QueueItem_ItemTagTransaction 
    FROM dbo.ItemTagTransactions 
    WHERE TagValue IN (SELECT ItemTag FROM dbo.ItemTagTransactions)
    

    试试这个...

    【讨论】:

      【解决方案3】:

      尝试使用动态 Sql。多个标签值必须用逗号分隔,如下所示的 InputString。

        declare @dynamicsql nvarchar(max),@inputstring nvarchar(max)='''ABC101170'',''dfg101264'''
          select @dynamicsql='select * from table 
          where tagvalue in('+@inputstring+')'
      print @dynamicsql
      exec sp_executesql @dynamicsql
      

      【讨论】:

        【解决方案4】:

        您可以使用 table-valued parameter 作为

        CREATE TYPE MyType AS TABLE (AValues VARCHAR(50));
        
        CREATE PROCEDURE MyProc
          @AVariable MyType READONLY
        AS
          SELECT *
          FROM T
          WHERE ItemTag IN (SELECT AValues FROM @AVariable);
        
        CREATE TABLE T(
          PK_ID INT,
          ItemTag VARCHAR(50)
        );
        
        INSERT INTO T VALUES
        (1, 'Filename.xlsx'),
        (2, 'ABC7798'),
        (3, '{empty string}'),
        (4, 'Completed');
        
        DECLARE @Var MyType;
        
        INSERT INTO @Var VALUES
        ('Filename.xlsx'), ('Completed');
        
        EXEC dbo.MyProc @Var;
        

        返回:

        +-------+---------------+
        | PK_ID |    ItemTag    |
        +-------+---------------+
        |     1 | Filename.xlsx |
        |     4 | Completed     |
        +-------+---------------+
        

        看看它在这个Live Demo

        上是如何工作的

        你可以传递一个字符串,然后

        CREATE PROCEDURE MyProc
          @AVariable VARCHAR(300)
        AS
          SELECT *
          FROM T CROSS APPLY 
               (SELECT Value FROM STRING_SPLIT(@AVariable, ',')) TT --You can use semi-colon ; instead of ,
          WHERE T.ItemTag = TT.Value;
        

        Second Demo

        但使用表值参数更安全,因为字符串可能包含,

        【讨论】:

          猜你喜欢
          • 2010-09-13
          • 1970-01-01
          • 2014-03-30
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-03-03
          • 1970-01-01
          • 2016-12-06
          相关资源
          最近更新 更多