#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'' '