如何在SQL中用于动态生成的字符串中的操作员



下面提到的是讨论中的示例代码:

DECLARE @FROMDATE AS DATETIME
DECLARE @TODATE AS DATETIME
DECLARE @DAYS AS VARCHAR(100)
SET @FROMDATE = CONVERT(DATETIME, '2017-09-03')
SET @TODATE = CONVERT(DATETIME, '2017-09-06')
SET @DAYS = '''SUNDAY'',''MONDAY'',''TUESDAY'',''WEDNESDAY'',''FRIDAY'',''SATURDAY'''
PRINT @DAYS 
--(O/P - 'SUNDAY','MONDAY','TUESDAY','WEDNESDAY','FRIDAY','SATURDAY')
SELECT 
    UPPER(DATENAME(dw, CONVERT(DATETIME, CONVERT(VARCHAR(10), APPDATE, 112)))), 
    * 
FROM 
    SQLTABLE
WHERE 
    UPPER(DATENAME(dw, CONVERT(DATETIME, CONVERT(VARCHAR(10), APPDATE, 112)))) IN (@DAYS)

如果我手动传递值如下,我将获得输出:

UPPER(DATENAME(dw, CONVERT(DATETIME, CONVERT(VARCHAR(10), APPDATE, 112)))) 
IN ('SUNDAY','MONDAY','TUESDAY','WEDNESDAY','FRIDAY','SATURDAY')

如果我使用具有与PRINT @DAYS O/P相同的变量传递值,则结果为空白:

UPPER(DATENAME(dw, CONVERT(DATETIME, CONVERT(VARCHAR(10), APPDATE, 112)))) 
IN (@DAYS)

假设在实际情况下,我正在动态地生成@DAYS变量下的值,或者将代码传递到以下查询/存储过程中:

在SQL中不允许它还是我错误地这样做?

您需要将其执行为Dynamic SQL:

Set @sql='SELECT ... from ...  WHERE ... NOT IN ('+@days+')'
exec sp_executesql @sql

如果不是,则整个param值将被视为一个值。

in运算符期望由逗号分隔的值列表,但是您提供的是一个单个值,其中包含一个逗号分隔列表。

您可以使用Dynamic SQL来解决它,如Sagi在答案中所建议的,或使用字符串拆分函数(在SQL Server 2016中它内置)将单个逗号分隔变量转换为表 -

SET @DAYS = 'SUNDAY,MONDAY,TUESDAY,WEDNESDAY,FRIDAY,SATURDAY'
SELECT UPPER(DATENAME(dw, CONVERT(DATETIME, CONVERT(VARCHAR(10), APPDATE, 112)))), * 
FROM SQLTABLE
WHERE UPPER(DATENAME(dw, CONVERT(DATETIME, CONVERT(VARCHAR(10), APPDATE, 112)))) IN (STRING_SPLIT(@DAYS, ','))

如果您使用的版本比2016年的版本较低,则需要自己创建字符串拆分用户定义的函数 - 或以正确的方式从Aaron Bertrand的拆分字符串中选择一个 - 或下一个最佳方式

但是,如果您的客户端支持它,我建议将一个有价值的参数发送到数据库,而不是完全处理逗号界限字符串。

如果您不喜欢动态查询,这是萨吉答案的另一种方法。您可以创建一个桌子并填充想要的日子:

CREATE TABLE #Days (NAME VARCHAR(20))
INSERT INTO #Days
VALUES ('SUNDAY'),('MONDAY'),('TUESDAY'),('WEDNESDAY'),('FRIDAY'),('SATURDAY')

,然后将其与您的桌子一起加入:

SELECT UPPER(DATENAME(dw, CONVERT(DATETIME, CONVERT(VARCHAR(10), APPDATE, 112)))),*
FROM SQLTABLE s
INNER JOIN #Days d ON d.NAME 
          = UPPER(DATENAME(dw, CONVERT(DATETIME, CONVERT(VARCHAR(10), s.APPDATE, 112))))

如果您使用的是SQL Server 2016 ,则有一个String_split函数,该函数返回具有value列的表。

SET @DAYS = 'SUNDAY,MONDAY,TUESDAY,WEDNESDAY,FRIDAY,SATURDAY'
SELECT UPPER(DATENAME(dw, CONVERT(DATETIME, CONVERT(VARCHAR(10), APPDATE, 112)))), *
FROM SQLTABLE s
INNER JOIN STRING_SPLIT(@DAYS, ',') d ON d.value 
        = UPPER(DATENAME(dw, CONVERT(DATETIME, CONVERT(VARCHAR(10), s.APPDATE, 112))))

(PS:Zohar peled的实现STRING_SPLIT如果您使用的是SQL Server 2016 )

最新更新