В SQL, как найти все строки, в которых ЛЮБОЙ столбец соответствует условию?

#sql #dynamic

#sql #динамический

Вопрос:

Я хочу найти строки в таблице, где ЛЮБОЙ столбец соответствует определенному условию.

Например, если у меня есть таблица RobTest :

 -- Example Table
create table #RobTest
    (A varchar(10), B varchar(10), C varchar(10))
insert into #RobTest
    select 'Blue', 'Green', 'Green' UNION ALL
    select 'Green', 'Blue', 'Green' UNION ALL
    select 'Green', 'Green', 'Green'
  

Если бы я хотел найти все строки, в которых В ЛЮБОМ столбце есть поле со значением 'Blue' , я мог бы написать:

 select * from #RobTest 
where A = 'Blue' or B = 'Blue' or C = 'Blue'
  

И получить строки 1 и 2. Но это решение может стать громоздким, если в таблице десятки имен столбцов или если вы не можете быть уверены, что имена столбцов могут измениться, и вы выполняете запрос, например, в качестве аудита. Итак, как сделать это динамически?

Комментарии:

1. Или вы считаете запись select * from #RobTest where 'Blue' in (A,B,C,D)

2. Краткий комментарий: Если вы можете проверить десятки разных столбцов на одно и то же значение, то у вас, вероятно, проблемы с нормализацией.

3. SQL server, Oracle, DB2, MySQL … синтаксис и information_Schema различаются. но общая концепция @MichaelCurrie разумна для обработки динамического характера этого запроса.

Ответ №1:

Мы можем использовать INFORMATION_SCHEMA.COLUMNS для поиска имен столбцов, затем использовать курсор для перебора по всем столбцам, используя динамический SQL для заполнения временной таблицы строками, удовлетворяющими условию.

Следуя приведенному выше коду, предполагая #RobTest определение, данное в вопросе:

 -- Find all columns of #RobTest
select COLUMN_NAME
INTO #ColumnNames
from tempdb.INFORMATION_SCHEMA.COLUMNS
where TABLE_NAME like '%RobTest%'

-- Create a place to hold our results
select * into #RobTemp from #RobTest
truncate table #RobTemp

-- Set up varaibles for our iteration process
DECLARE @sql nvarchar(1000)
DECLARE @columnCursor CURSOR
DECLARE @currentColumn NVARCHAR(100)
SET @columnCursor = CURSOR FOR
    SELECT COLUMN_NAME FROM #ColumnNames

-- Go through the columns one at a time and then run the query on that column.
OPEN @columnCursor
FETCH NEXT FROM @columnCursor INTO @currentColumn
WHILE @@FETCH_STATUS = 0
BEGIN
    set @sql = 'select * from #RobTest where '   @currentColumn   ' = ''Blue'''
    insert into #RobTemp
        exec sp_executesql @sql

    FETCH NEXT FROM @columnCursor INTO @currentColumn
END

-- Show the results
select * from #RobTemp
  

Комментарии:

1. # 1 вы можете select * into #RobTemp from #RobTest where 1 = 2 вместо его усечения. # 2 вы должны рассмотреть возможность создания всего динамического sql и выполнить его сразу, вот так : set @sql = case when isnull(@sql, '') = '' then 'select * from #RobTest where ' else @sql ' and ' end @currentColumn ' = ''Blue'' '