具有多个值列表的局部变量

时间:2017-09-04 22:38:45

标签: sql sql-server local-variables

我使用Excel连接连接到SQL Server以查询从SQL服务器到Excel的数据。

我在Excel连接中有几次WHERE子句。我需要不时替换WHERE多值列表。要简单地替换,我想使用本地参数@Trans。使用local参数,我只能更改它,所有SQL都将使用它来查询。

WHERE Type in ('R','D','C')

如果是单一选项,则代码可以正常工作。

DECLARE @TRans CHAR(200)= 'R';
SELECT .....
WHERE Type in (@Trans)

如果是多个选项,则以下代码无效

DECLARE @TRans CHAR(200)= 'R,D,C';
SELECT .....
WHERE Type in (@Trans)

DECLARE @TRans CHAR(200)= '''R'''+','+'''D'''+','+'''C''';
SELECT .....
WHERE Type in (@Trans)

如何为多个值列表声明@Trans,例如(' R',' D',' C')?谢谢。

5 个答案:

答案 0 :(得分:2)

您可以使用动态sql

DECLARE @TRans VARCHAR(200)= '''R'',''D'',''C''';
DECLARE @sql VARCHAR(MAX) = '';

SET @sql = 'SELECT * FROM table WHERE Type in (' + @Trans + ');'

EXEC @sql

记下@TRans中这些字符值后的值的引号。

如果要检查@sql的值,您将看到构造的sql语句,请用PRINT @sql替换EXEC @sql。

@sql的结果

SELECT * FROM table WHERE Type in ('R','D','C');

答案 1 :(得分:1)

正如您现在所看到的,SQL Server不支持宏替代。这留下了几个选择。一种是拆分字符串。

如果不是2016年,这里是一种快速的在线方法,不需要表格值函数

示例

Declare @Trans varchar(max)='R,D,C'  -- Notice no single quotes

Select ...
 Where Type in (
                Select RetVal = LTrim(RTrim(B.i.value('(./text())[1]', 'varchar(max)')))
                From  (Select x = Cast('<x>' + replace(@Trans,',','</x><x>')+'</x>' as xml).query('.')) as A 
                Cross Apply x.nodes('x') AS B(i)
               )

答案 2 :(得分:0)

您可以创建一个名为LocalParameter的表,并在那里保留局部变量。您只能通过更新LocalParameter表而不更改queries来获取数据。

CREATE TABLE LocalParameter (Trans VARCHAR(MAX))

INSERT INTO LocalParameter
VALUES
(
    ',R,'
)

使用LIKE,您可以像这样使用它:

SELECT .....
WHERE (SELECT TOP 1 A.Trans FROM LocalParameter A) LIKE ',' + Type + ','

要更改WHERE子句:

UPDATE LocalParameter
SET Trans = ',R,D,C,'

查询:

SELECT .....
WHERE (SELECT TOP 1 A.Trans FROM LocalParameter A) LIKE ',' + Type + ','

将局部变量添加到逗号的开头和结尾。

答案 3 :(得分:0)

您可以使用拆分方法拆分csv值,如下所示

DECLARE @delimiter      VARCHAR(10)=','
DECLARE @input_string   VARCHAR(200)='R,D,C'

;WITH CTE AS
(
    SELECT 
        SUBSTRING(@input_string,0,CHARINDEX(@delimiter,@input_string)) AS ExtractedString, 
        SUBSTRING(@input_string,CHARINDEX(@delimiter,@input_string) + 1,LEN(@input_string)) AS PartString
    WHERE CHARINDEX(@delimiter,@input_string)>0
    UNION ALL
    SELECT 
        SUBSTRING(PartString,0,CHARINDEX(@delimiter,PartString)) AS ExtractedString, 
        SUBSTRING(PartString,CHARINDEX(@delimiter,PartString)+1,LEN(PartString)) AS PartString 
    FROM CTE WHERE CHARINDEX(@delimiter,PartString)>0
)
SELECT ExtractedString FROM CTE 
UNION ALL
SELECT 
    CASE WHEN CHARINDEX(@delimiter,REVERSE(@input_string))>0 
        THEN REVERSE(SUBSTRING(REVERSE(@input_string),0,CHARINDEX(@delimiter,REVERSE(@input_string)))) 
        ELSE @input_string END
OPTION (MAXRECURSION 0)

这种拆分方法没有任何循环,所以它会很快。然后将其与您的查询集成,如下所述

DECLARE @delimiter      VARCHAR(10)=','
DECLARE @input_string   VARCHAR(200)='R,D,C'

;WITH CTE AS
(
    SELECT 
        SUBSTRING(@input_string,0,CHARINDEX(@delimiter,@input_string)) AS ExtractedString, 
        SUBSTRING(@input_string,CHARINDEX(@delimiter,@input_string) + 1,LEN(@input_string)) AS PartString
    WHERE CHARINDEX(@delimiter,@input_string)>0
    UNION ALL
    SELECT 
        SUBSTRING(PartString,0,CHARINDEX(@delimiter,PartString)) AS ExtractedString, 
        SUBSTRING(PartString,CHARINDEX(@delimiter,PartString)+1,LEN(PartString)) AS PartString 
    FROM CTE WHERE CHARINDEX(@delimiter,PartString)>0
)
SELECT * FROM [YourTableName] WHERE Type IN
(SELECT ExtractedString FROM CTE 
UNION ALL
SELECT 
    CASE WHEN CHARINDEX(@delimiter,REVERSE(@input_string))>0 
        THEN REVERSE(SUBSTRING(REVERSE(@input_string),0,CHARINDEX(@delimiter,REVERSE(@input_string)))) 
        ELSE @input_string END
)OPTION (MAXRECURSION 0)

答案 4 :(得分:0)

如果可能的话,添加一个新表,然后在所有查询中加入它:

CREATE TABLE SelectedType
(
   [Type] CHAR(1) PRIMARY KEY
)

INSERT INTO SelectedType
VALUES ('R','D','C')

然后您的查询变为:

SELECT *
FROM MyTable MT
INNER JOIN SelectedType [ST]
   ON ST.[Type] = MT.[Type]

如果您需要添加,更新或删除类型,请更新SelectedType表中的行。

这样可以使用基于SET的查询,易于理解,易于添加,更新或删除所需类型。