TSQL-使用函数调用动态查询时出错

时间:2018-08-13 18:27:39

标签: sql-server tsql

我有一个可以运行的查询-

SELECT connected_clients, (ServerName + CacheType) AS metric, CreateDate AS time
FROM dbo.DiagnosticLog dl 
WHERE ServerName IN ('001        ', '002        ', '003        ')
  AND CacheType IN ('p.1   ', 'q.1   ', 'm.1     ', 'a-p.1   ', 'a-q.1   ', 'sentinel  ')   

connected_clients是列名,所以我需要进行动态查询,并且还需要调用一个函数,该函数将逗号分隔单词,如ServerName和CacheType。这是我的包含动态查询的存储过程:

    @StartDate DATETIME,
    @EndDate DATETIME,
    @Message VARCHAR(MAX),
    @ServerName CHAR(150),
    @CacheType CHAR(150)
)   
AS
BEGIN
    DECLARE @sql NVARCHAR(MAX)
    SET @sql = 
    ('SELECT '+ @Message +', (ServerName + CacheType )as metric, CreateDate  as time
    FROM DiagnosticLog 
    WHERE ServerName in ('+(SELECT * FROM dbo.SplitString(@ServerName,','))+') AND 
        CacheType in ('+(SELECT * FROM dbo.SplitString(@CacheType,','))+')   ')
    EXECUTE (@sql)
END
GO

这就是我调用存储过程的方式

DECLARE
    @StartDate DATETIME,
    @EndDate DATETIME,
    @Message CHAR(20)

SET @StartDate =  DATEADD(HH,-24, GETDATE()) 
SET @EndDate = GETDATE()

EXECUTE storedProcedureName @StartDate, @EndDate ,  'connected_clients', '001        ,002        ,003        ' , 'p.1   ,q.1   ,m.1     ,a-p.1   ,a-q.1   ,sentinel  '

我得到的错误是:

  

子查询返回了多个值。当子查询遵循=,!=,<,<=,>,> =或将子查询用作表达式时,不允许这样做

编辑:我将sql字符串更改为

@sql = 
    'SELECT '+ @Message +', (ServerName + CacheType )as metric, CreateDate  as time
    FROM DiagnosticLog dl 
    WHERE ServerName in (SELECT * FROM dbo.SplitString(' +@ServerName + ','','')) AND 
        CacheType in (SELECT * FROM dbo.SplitString(' +@CacheType+ ','',''))   '
execute (@sql)

我得到

的错误
  

'。1'附近的语法不正确

2 个答案:

答案 0 :(得分:0)

您在此行上缺少pvk2pfx.exe -pvk <pvk file location>.pvk -pi <pvk password> -spc <pvk file location>.cer -pfx <new pfx file location>.pfx -po <pfx password> 关键字:

IN

声明时,也不要将sql字符串放在括号中。

答案 1 :(得分:0)

您从... ServerName in ('+(SELECT * FROM dbo.SplitString(@ServerName,','))+') ...中的查询中获得了多个值,但是SQL Server不会为您神奇地将这些值连接成一个逗号分隔的字符串。

由于in处理以逗号分隔的列表,因此如果用引号引起来,则可以使用... ServerName in (' + @ServerName + ') ...。 (请注意,您已从在工作查询中使用'001 ','002 ','003 '(使用每个元素都被引号更改为'001 ,002 ,003 ')作为参数值并使用了整个字符串。)

或者,让in使用子查询:... ServerName in ( select * from dbo.SplitString( ''' + @ServerName + ''',',') ) ...

请注意,这两者都为SQL Injection提供了充足的机会。

使用带有execute的参数化查询来传递变量值将消除SQL注入的可能性。

以上所有内容同样适用于CacheType in表达式。