【问题标题】:loop to add value in dynamic OR statement循环以在动态 OR 语句中添加值
【发布时间】:2019-03-13 13:47:53
【问题描述】:

我将这个查询分解为最基本的。我需要动态添加一个 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_%' 

【问题讨论】:

  • 您好,欢迎来到 SO。只是说“它没有按预期工作”并不是很有帮助。我们不知道您正在尝试做什么或什么不起作用。我不明白你为什么在这里使用动态 sql。你能解释一下你想做什么吗?
  • 当然,抱歉,这是我在这里的第一篇文章。我正在尝试使用 OR 子句将变量插入到动态 sql 中。这个查询只是我原来的一小部分。我试图让它变小只是为了表明我的需要。我需要动态 sql,因为我有大约 7 个其他过滤器,这些过滤器是根据用户输入的值动态构建的。这个 origin id 过滤器只是其中之一。我需要能够在表格中搜索用户输入的任何 Id,在本例中为 31、33、25 及其匹配的原始 ID,并带有尾随下划线(即 31_、25_、33_)。
  • 将这些详细信息添加到您的问题中。评论很糟糕,因为它们会丢失并且格式不存在。
  • 对于这种捕获所有查询,您可以考虑使用表值参数。此外,like 使用下划线作为通配符。这是一个关于该主题的问题,已得到很好的解释。 stackoverflow.com/questions/19588455/…
  • 我需要将带有下划线的源 ID 从我的表中添加到 OR 语句中,因此我试图遍历我的 #invars 表并将它们放入 OR 语句中。现在,整个@Sql 正在执行多次:

标签: sql-server


【解决方案1】:

一些问题:不能将 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

【讨论】:

    【解决方案2】:

    这里不是很清楚你想要什么,但我认为你让自己变得比你需要的更难。无需使用 IN,因为您还会找到以相同值开头的所有值。而且您已将相同的值硬编码到临时表中。使用字符串拆分器,这大约要简单一百万倍。只需用逗号分隔您的 @OriginID 并在连接中使用 LIKE。

    我使用的是 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
    

    【讨论】:

      【解决方案3】:

      我解决了。谢谢所有回复的人。

      创建表#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, origins varchar(256)) 插入#inVars(origins) 值('31'), ('33'), ('25')

      声明@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

      【讨论】:

        猜你喜欢
        • 2017-05-22
        • 2019-12-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-07-10
        • 2020-09-09
        相关资源
        最近更新 更多