【问题标题】:TSQL Dynamic QueryTSQL 动态查询
【发布时间】:2014-08-22 09:41:57
【问题描述】:

我有一个动态 TSQL 查询,大部分时间都在工作,但是我现在尝试向它添加一个 IN 子句,因为我正在传递多个员工 ID 并想要获取他们的数据。

这就是我要添加的部分的陈述:

IF @awardEmployees IS NOT NULL
        SET @Where = @Where + ' AND A.[employee] IN 'SELECT ParamValues.x2.value('empID[1]', 'VARCHAR(60)') FROM  @awardEmployees.nodes('/employees/employee') AS ParamValues(x2);

这样的动态查询中是否可以包含 IN 子句?我一直在尝试我能做的,但似乎没有任何效果。它目前所做的只是返回我正在搜索的empID,甚至没有正确运行查询。

更新:

当我这样做时,它适用于单个员工:

IF @awardEmployees IS NOT NULL
        SET @Where = @Where + ' AND A.[employee] IN (''' +(SELECT ParamValues.x2.value('empID[1]', 'VARCHAR(60)') FROM @awardEmployees.nodes('/employees/employee') AS ParamValues(x2)) + ''')';

但是,当我的 XML 包含 2 名或更多员工时,它会引发此错误:

Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.

【问题讨论】:

  • 您的子查询必须返回一个字符串,或者可以隐式转换为字符串的内容,例如单列单行行集。在多个值的情况下,它们必须连接在一起并用逗号分隔才能成为单个字符串!当您的子查询返回诸如 1,2,15,27 之类的结果时,您就可以将其添加到动态 SQL 字符串中了。
  • 谢谢 - 我不太确定如何将 XML 输入转换为字符串。我一直都是这样做的,但在这个动态查询的情况下它似乎不起作用

标签: sql sql-server tsql stored-procedures


【解决方案1】:

您需要将 nodes() 方法返回的表转换为逗号分隔的值列表。

        IF @awardEmployees IS NOT NULL
             SET @Where = @Where + ' AND A.[employee] IN (' + stuff(
          (
            select ','+QUOTENAME(ParamValues.x2.value('@empID[1]', 'VARCHAR(60)'), '''')
            FROM @awardEmployees.nodes('/employees/employee') AS ParamValues(x2)
            for xml path(''),type
          ).value('.','varchar(max)'),1,1,'') + ')'

下面的SQL Fiddle 演示了这个想法。顺便说一句,当您这样做时,您将不需要 sp_executesql 调用中 @_awardEmployees = @awardEmployees 的参数

【讨论】:

  • 这很好用;多谢。我遇到的一个问题是当我没有要查找的员工时尝试将值设置为 null。 SET @awardEmployees = NULLIF(@awardEmployees, '') 这不起作用,因为我收到错误 The data types xml and varchar are incompatible in the equal to operator. 当传递的值为空时,有没有办法将其设置为 null?
  • 删除这一行。您的 if 语句正在检查 null
  • 是的,但是脚本无论如何都会传递一些东西,它要么是 XML 字符串,要么是空值。所以它总是不是 null 这就是为什么我有其他行说 if '' then it's null
【解决方案2】:

in 和子查询周围需要括号:

IF @awardEmployees IS NOT NULL
    SET @Where = @Where + ' AND A.[employee] IN (''' +
                 (SELECT ParamValues.x2.value('empID[1]', 'VARCHAR(60)') FROM @awardEmployees.nodes('/employees/employee') AS ParamValues(x2)
                 ) + ''');

这假定查询的结果是单行和单列,其中包含逗号分隔的列表。

编辑:

您可以尝试将它们连接在一起:

IF @awardEmployees IS NOT NULL
    SET @Where = @Where + ' AND A.[employee] IN (' +
                 stuff((SELECT ', ''' + ParamValues.x2.value('empID[1]', 'VARCHAR(60)') + ''''
                        FROM @awardEmployees.nodes('/employees/employee') AS ParamValues(x2)
                        FOR XML PATH ('')
                       ), 1, 2, '') + ');

【讨论】:

  • 我尝试过类似的操作,运行时出错SQL Server]Invalid column name 'ABC123'
  • @SBB 。 . .在这种情况下,您需要更多的单引号,正如我刚刚添加的那样。
  • 您应该编辑您的问题并显示变量替换后@where 变量的内容。
  • @GordonLinoff:我认为您需要从SELECT ParamValues.x2.value 构建一个逗号分隔的列表。我认为您将需要使用 FOR XML PATH 或其他方法
  • 这就是我整个 SP 的样子。我想弄清楚如何在执行之前显示 where 子句:pastebin.com/JWd8aLkZ
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-01-07
  • 2016-08-23
  • 1970-01-01
  • 1970-01-01
  • 2013-05-23
  • 2023-04-07
  • 2016-05-15
相关资源
最近更新 更多