首页 > 解决方案 > where 条件为 varchar 使用变量

问题描述

我在 varchar 中有一个 SQL 查询,如下所示:

declare @dataSourceId varchar(500) = ''
declare @SQL varchar(500) = 'select * from DataSources
                             where Data is not null 
                               and DataSourceId not in ('+@dataSourceId+')
                                or Data is not null 
                               and DataSourceId is not null'

如果@dataSourceId是空字符串'',那么我想执行条件Data is not null and DataSourceId is not null,但如果@dataSourceId不是'',则执行第一个条件。如何实施此解决方案?

标签: sqlsql-servertsqlwhere-clausedynamic-sql

解决方案


您在这里真正应该做的不是将值注入您的语句;该路径导致 SQL 注入。正确参数化你的陈述。

如果必须传递分隔列表,请使用字符串拆分器。我假设您使用的是最新版本的 SQL Server(如果没有,您将需要使用用户定义的字符串拆分器,例如用于 的 XML 拆分器delimitedsplit8k_LEAD)。

SELECT *
FROM dbo.DataSources
WHERE (Data IS NOT NULL 
  AND DataSourceId not in (SELECT value FROM STRING_SPLIT(@dataSourceId,',')))
   OR (NULLIF(@dataSourceId,'') IS NULL
  AND  Data IS NOT NULL
  AND  DataSourceId IS NOT NULL)
OPTION (RECOMPILE);

当然,这可能表现得不太好,由于OR化妆,所以你可以使用适当的参数化动态语句来代替:

DECLARE @SQL nvarchar(MAX),
        @CRLF nchar(2) = NCHAR(13) + NCHAR(10);

SET @SQL = N'SELECT *' + @CRLF +    
           N'FROM dbo.DataSources' + @CRLF + 
           N'WHERE Data IS NOT NULL' + @CRLF +
           CASE WHEN NULLIF(@dataSourceId,'') IS NULL THEN N'  AND DataSourceId IS NOT NULL'
                                                      ELSE N'  AND DataSourceId NOT IN(SELECT value FROM STRING_SPLIT(@dataSourceId,'','')'
           END + N';'
EXEC sys.sp_executesql @SQL, N'@dataSourceId varchar(500)', @dataSourceId;

推荐阅读