循环以在动态OR语句中添加值

时间:2019-03-13 13:47:53

标签: sql-server

我将此查询细分为最基本的查询。我需要动态添加一个OR语句,其中包括一个变量。我需要使用下划线获取任何ID及其对应的ID。因此,我要执行的最终@SQL将是:

create table #Test (OrganizationId varchar(100), OrigID varchar(50))
insert into #Test(OrganizationId,OrigID)
Values  ('5','31'),
        ('5','31_00000'),
        ('5','33'),
        ('5','33_00000'),
        ('5','25'),
        ('5','25_00000'),
        ('5','HD_00000'),
        ('5','HD')

-- 
DECLARE 
        @OrganizationId int = 5,
        @OriginId nvarchar(256) = N'31,25,33'




create table #inVars(id int NOT NULL IDENTITY PRIMARY KEY, origins varchar(256))
  insert into #inVars(origins)
  Values ('31'),
         ('33'),
         ('25')

 DECLARE  @SQL           NVARCHAR(MAX),
             @ParamDefinition NVARCHAR(MAX)


 SET @ParamDefinition = N'@OrganizationId int,
                        @OriginId nvarchar(256)'


SET @SQL= 'SELECT OrganizationId,OrigID
FROM #Test
WHERE OrganizationId=@OrganizationId'

IF ISNULL(@OriginId,'') <> ''
     SET @SQL = @SQL + ' AND OrigID in (''' + @OriginId + ''') '
     DECLARE @counter INT = 1, @max INT = 0, @Origin nvarchar(50), @SQL_2 nvarchar(max)
     SELECT @max = COUNT(id) FROM #inVars
     WHILE @counter <= @max
     BEGIN
        SET @Origin = '_%'
        SET @Origin = (select origins from #invars where id = CAST(@counter as varchar(10))) + @Origin
        SET @SQL_2 = N' OR OrigID LIKE ''' + @Origin + ''' '
        SET @SQL_2 = @SQL + @SQL_2
print(@SQL_2)
        SET @counter = @counter + 1

    END

EXEC sp_executesql @SQL_2,@ParamDefinition,@OrganizationId,@OriginId

drop table #inVars
drop table #Test

这是我的查询现在如何执行:

SELECT OrganizationId,OrigID
    FROM #Test
    WHERE OrganizationId=@OrganizationId AND OrigID in ('31,25,33')  OR OrigID LIKE '31_%' 
SELECT OrganizationId,OrigID
    FROM #Test
    WHERE OrganizationId=@OrganizationId AND OrigID in ('31,25,33')  OR OrigID LIKE '33_%' 
SELECT OrganizationId,OrigID
    FROM #Test
    WHERE OrganizationId=@OrganizationId AND OrigID in ('31,25,33')  OR OrigID LIKE '25_%' 

这是我想要的结果:

SELECT OrganizationId,OrigID
    FROM #Test
    WHERE OrganizationId=@OrganizationId AND OrigID in ('31,25,33')  OR OrigID LIKE '31_%' 
    OR OrigID LIKE '33_%' 
    OR OrigID LIKE '25_%' 

3 个答案:

答案 0 :(得分:0)

一些问题:您不能将NULL与字符串EVER连接起来;结果始终为NULL(请查看IF @Origin IS NOT NULL行)。在循环中,您应该更新@SQL,而不是@ SQL_2。最后,您应该将OR包裹在括号中,这样逻辑就始终是明确的。

SET NOCOUNT ON

create table #Test (OrganizationId varchar(100), OrigID varchar(50))
insert into #Test(OrganizationId,OrigID)
Values  ('5','31'),
        ('5','31_00000'),
        ('5','33'),
        ('5','33_00000'),
        ('5','25'),
        ('5','25_00000'),
        ('5','HD_00000'),
        ('5','HD')

DECLARE 
        @OrganizationId int = 5,
        @OriginId nvarchar(256) = N'31,25,33'

create table #inVars(id int NOT NULL IDENTITY PRIMARY KEY, origins varchar(256))
  insert into #inVars(origins)
  Values ('31'),
         ('33'),
         ('25')

 DECLARE  @SQL           NVARCHAR(MAX),
             @ParamDefinition NVARCHAR(MAX)

 SET @ParamDefinition = N'@OrganizationId int,
                        @OriginId nvarchar(256)'


SET @SQL= 'SELECT OrganizationId,OrigID
FROM #Test
WHERE OrganizationId=@OrganizationId'

IF ISNULL(@OriginId,'') <> ''
     SET @SQL = @SQL + ' AND (OrigID in (''' + @OriginId + ''') '
     DECLARE @counter INT = 1, @max INT = 0, @Origin nvarchar(50), @SQL_2 nvarchar(max)
     SELECT @max = COUNT(id) FROM #inVars
     WHILE @counter <= @max
     BEGIN
        SET @Origin = '_%'
        SET @Origin = (select origins from #invars where id = CAST(@counter as varchar(10))) + @Origin
        IF @Origin IS NOT NULL
        BEGIN
            SET @SQL_2 = N' OR OrigID LIKE ''' + @Origin + ''' '
            SET @SQL = @SQL + @SQL_2
        END
        SET @counter = @counter + 1
    END
    SET @SQL=@SQL+')'
print @SQL

drop table #inVars
drop table #Test

答案 1 :(得分:0)

目前尚不清楚您想要什么,但我认为您正在使自己变得比自己更难。无需使用IN,因为您还会发现所有以相同值开头的值。您已经将相同的值硬编码到临时表中。使用一个字符串分割器,可以减少大约一百万倍的复杂性。只需在逗号上分割@OriginID,然后在联接中使用L​​IKE。

我正在使用DelimitedSplit8k,您可以找到here

我很确定这可以为您提供所需的信息。我建议尽可能避免循环。

create table #Test (OrganizationId varchar(100), OrigID varchar(50))
insert into #Test(OrganizationId,OrigID)
Values  ('5','31'),
        ('5','31_00000'),
        ('5','33'),
        ('5','33_00000'),
        ('5','25'),
        ('5','25_00000'),
        ('5','HD_00000'),
        ('5','HD')

DECLARE 
        @OrganizationId int = 5,
        @OriginId nvarchar(256) = N'31,25,33'

select *
from #Test t
join DelimitedSplit8K(@OriginID, ',') x on t.OrigID like x.Item + '%'

drop table #Test

答案 2 :(得分:0)

我解决了这个问题。谢谢所有回答。

创建表#Test(OrganizationId varchar(100),OrigID varchar(50)) 插入#Test(OrganizationId,OrigID) 值(“ 5”,“ 31”),         ('5','31_00000'),         ('5','33'),         ('5','33_00000'),         (“ 5”,“ 25”),         ('5','25_00000'),         ('5','HD_00000'),         (“ 5”,“ HD”)

声明         @OrganizationId int = 5         @OriginId nvarchar(256)= N'31,25,33'

创建表#inVars(id int NOT NULL IDENTITY PRIMARY KEY,起源varchar(256))   插入#inVars(来源)   值('31'),          (“ 33”),          ('25')

DECLARE @SQL NVARCHAR(MAX),              @ParamDefinition NVARCHAR(MAX)

SET @ParamDefinition = N'@ OrganizationId int,                         @OriginId nvarchar(256)'

SET @SQL= 'SELECT OrganizationId,OrigID
FROM #Test
WHERE OrganizationId=@OrganizationId'

IF ISNULL(@OriginId,'') <> ''
BEGIN
     SET @SQL = @SQL +' AND (OrigID in (''' + @OriginId + ''')) '
END

IF ISNULL(@OriginId,'') <> ''

     DECLARE @counter INT = 1, @max INT = 0, @Origin nvarchar(50), @SQL_2 nvarchar(max)
     SELECT @max = COUNT(id) FROM #inVars
     WHILE @counter <= @max
     BEGIN

        SET @Origin = (select origins from #invars where id = CAST(@counter as varchar(10)))
        SET @Origin = @Origin+'_%'
        SET @SQL_2 =  N' OR (OrigID LIKE ''' + @Origin + ''') '
        SET @SQL = @SQL + @SQL_2

        SET @counter = @counter + 1

    END
    print(@SQL)

EXEC sp_executesql @SQL,@ParamDefinition,@OrganizationId,@OriginId

放置表格#inVars 删除表#Test