如何声明和设置一个等于值列表的变量?

时间:2014-08-07 13:59:23

标签: sql sql-server sql-server-2008 tsql

大家早上好!我正在尝试编写一个Query,它接受一个邮政编码列表作为变量,然后查询该集合中的值。除了我将列表值放入的变量外,一切似乎都运行良好。

我从未尝试使用varchar值来表示值列表,因此如果不可能或者有更好的方法,请告诉我。

这是迄今为止的代码:

DECLARE @trade_firm VARCHAR(20)
DECLARE @zip_list VARCHAR(255)
---------------------------------
SET @trade_firm = '0016986'
SET @zip_list = '44654,15219,15219,15219' --this is my list of zip codes
---------------------------------

SELECT oad.POSTAL_CODE_1,
      o.CHANNEL
FROM dbo.OFFICE AS o
    INNER JOIN dbo.OFFICE_ALIAS AS oa
    ON o.OFFICE_ID = oa.OFFICE_ID
    INNER JOIN dbo.OFFICE_ADDRESS AS oad
    ON o.ADDRESS_1_ID = oad.OFFICE_ADDRESS_ID
WHERE oa.TRADE_FIRM = @trade_firm
AND o.CHANNEL != (  SELECT f.channel
                FROM dbo.FIRM AS f
                    INNER JOIN dbo.FIRM_ALIAS AS fa
                    ON f.FIRM_ID = fa.FIRM_ID
                WHERE fa.trade_firm = @trade_firm)--will return the channel of the main firm
AND oad.POSTAL_CODE_1 NOT IN @zip_list --this is the variable as I currently have it, broken

3 个答案:

答案 0 :(得分:0)

这是不可能的,您需要将字符串变量转换为表变量才能与IN关键字一起使用。

一种解决方案是从应用程序逻辑传递一个表值参数。该参数可以是像对象一样的数组。请参阅Using Table-Valued Parameters Arrays and Lists in SQL Server 2008

如果以上不可能,我使用的技术之一也在上面的文章中描述,即将逗号分隔的值列表拆分为表变量。

declare @trade_firm varchar(20)
declare @zip_list varchar(255)
---------------------------------
set @trade_firm = '0016986'
set @zip_list = '44654,15219,15219,15219' --this is my list of zip codes

--DECLARE TABLE VARIABLE
DECLARE @ziplist_table table(
  zipcode varchar(10)
)

--TAKSE COMA SEPERATED LIST OF CODES AN INSERTS TO TABLE VARIABLE FOR LATER USE
DECLARE @pos int, @nextpos int, @valuelen int
SELECT @pos = 0, @nextpos = 1
WHILE @nextpos > 0
   BEGIN
      SELECT @nextpos = charindex(',', @zip_list, @pos + 1)
            SELECT @valuelen = CASE WHEN @nextpos > 0
                              THEN @nextpos
                              ELSE len(@zip_list) + 1
                         END - @pos - 1
      INSERT @ziplist_table (zipcode)
         VALUES (substring(@zip_list, @pos + 1, @valuelen))
      SELECT @pos = @nextpos
   END

现在您可以使用WHERE子句中的表变量,如此

WHERE oad.POSTAL_CODE_1 not in (SELECT zipcode FROM @zip_list)

答案 1 :(得分:0)

这应该有效。希望它有所帮助。

DECLARE @trade_firm VARCHAR(20)
DECLARE @zip_list VARCHAR(255)
DECLARE @tbl_zip_list TABLE (zip_list VARCHAR(10))
---------------------------------
SET @trade_firm = '0016986'
SET @zip_list = '44654,15219,15219,15219' --this is my list of zip codes
---------------------------------

SET @zip_list = @zip_list + ','  --Add trailing ',' for closing the loop
WHILE CHARINDEX(',', @zip_list) > 0
    BEGIN
       INSERT INTO @tbl_zip_list
       SELECT SUBSTRING(@zip_list, 1, CHARINDEX(',', @zip_list) - 1)

       SET @zip_list = SUBSTRING(@zip_list, CHARINDEX(',', @zip_list) + 1, LEN(@zip_list))
    END
SELECT *
FROM @tbl_zip_list

SELECT oad.POSTAL_CODE_1,
      o.CHANNEL
FROM dbo.OFFICE AS o
    INNER JOIN dbo.OFFICE_ALIAS AS oa
    ON o.OFFICE_ID = oa.OFFICE_ID
    INNER JOIN dbo.OFFICE_ADDRESS AS oad
    ON o.ADDRESS_1_ID = oad.OFFICE_ADDRESS_ID
WHERE oa.TRADE_FIRM = @trade_firm
  AND o.CHANNEL != (    SELECT f.channel
                    FROM dbo.FIRM AS f
                        INNER JOIN dbo.FIRM_ALIAS AS fa
                        ON f.FIRM_ID = fa.FIRM_ID
                    WHERE fa.trade_firm = @trade_firm)--will return the channel of the main firm
  AND NOT EXISTS (SELECT 1
               FROM @tbl_zip_list AS ni
               WHERE n1.zip_list = oad.POSTAL_CODE_1) --this is the variable as I currently have it, broken

答案 2 :(得分:0)

我更喜欢使用here找到的技术之一来分割逗号字符串...我最喜欢的是Numbers表(或使用CTE,找到的代码here - 但是CTE上的性能可以是正如Sean Lange在评论中所指出的那样可怜。

将这些内容插入到您的特定代码中,并使用CTE代替实际的Numbers表,我想出了类似的内容:

declare @trade_firm varchar(20)
declare @zip_list varchar(255)
---------------------------------
set @trade_firm = '0016986'
set @zip_list = '44654,15219,15219,15219' --this is my list of zip codes
---------------------------------

--define start and end limits

Declare @start int, @end int
Select @start=1, @end=255 -- @end should equal the maximum number of characters possibe in @zip_list

;With NumberSequence( Number ) as
(
    Select @start as Number
        union all
    Select Number + 1
        from NumberSequence
        where Number < @end
)

select oad.POSTAL_CODE_1, o.CHANNEL
from dbo.OFFICE o
inner join dbo.OFFICE_ALIAS oa on o.OFFICE_ID = oa.OFFICE_ID
inner join dbo.OFFICE_ADDRESS oad on o.ADDRESS_1_ID = oad.OFFICE_ADDRESS_ID
where oa.TRADE_FIRM = @trade_firm
and o.CHANNEL != 
(
select f.channel 
from dbo.FIRM f INNER JOIN dbo.FIRM_ALIAS fa on f.FIRM_ID = fa.FIRM_ID
where fa.trade_firm = @trade_firm
)--will return the channel of the main firm
and oad.POSTAL_CODE_1 not in
  (
    SELECT Item = SUBSTRING(@zip_list, Number, 
        CHARINDEX(',', @zip_list + ',', Number) - Number)
    FROM NumberSequence
    WHERE Number <= CONVERT(INT, LEN(@zip_list))
        AND SUBSTRING(',' + @zip_list, Number, 1) = ','

  ) 
Option (MaxRecursion 255)-- should equal the maximum number of characters possibe in @zip_list