Вы можете отложить EXEC до завершения цикла курсора. Затем просто отследите имя таблицы внутри цикла и, если оно совпадает, добавьте ИЛИ, в противном случае завершите свой SELECT и начните новый.
DECLARE @lasttable varchar(255);
SET @lasttable='';
FETCH NEXT FROM abc INTO @tableName, @columnName;
WHILE (@@FETCH_STATUS = 0)
BEGIN
IF(@lasttable=@tablename) BEGIN
SET @szQuery = @szQuery + ' OR [' + @columnName + ']=''' + CAST(@searchValue AS varchar(50)) + '''';
END ELSE BEGIN
SET @lasttable = @tablename;
SET @szQuery = @szQuery +
'SELECT '''+@tableName+''' AS TheTable, '''+@columnName+''' AS TheColumn '+
'FROM '+@tableName+' '+
'WHERE '+@columnName+' = '''+CAST(@searchValue AS varchar(50))+''''
END
FETCH NEXT FROM abc INTO @tableName, @columnName;
END
PRINT @szQuery;
EXEC (@szQuery);
Вы также можете создать хранимую процедуру для построения VIEW, который выполняет UNION ALL из всех таблиц и полей uniqueidentifier. Что-то с такой схемой:
CREATE VIEW all_uuids AS (
SELECT 'prices' AS tablename, 'BookGUID' as fieldname, ID as primarykey, BookGUID AS guid FROM prices
UNION ALL SELECT 'prices', 'AuthorGUID', ID, AuthorGUID FROM prices
UNION ALL SELECT 'othertable', 'otherfield', ID, otherfield FROM othertable
)
Тогда вам просто нужно выполнить один оператор SELECT для этого повторно используемого VIEW, чтобы получить все совпадающие GUID. Для поиска в одной таблице используйте коррелированный подзапрос, например ::
SELECT * FROM prices WHERE EXISTS (SELECT null FROM all_uuids u WHERE u.primarykey=prices.id AND u.guid=@searchfor AND u.tablename='prices')
Это будет искать во всех полях GUID в таблице цен. SQL Server достаточно умен, чтобы не просматривать другие таблицы, и использует индексы существующих таблиц.
Повторно используя одиночное представление, вы должны проходить циклически по information_schema, когда вы изменяете свою схему, а не с каждым запросом, и результаты представления можно объединить с большей готовностью, чем результаты хранимой процедуры.
Ответ
Оригинальные постеры, окончательное решение, на основе этого ответа:
CREATE PROCEDURE dbo.FindGUID @searchValue uniqueidentifier AS
/*
Search all tables in the database for a guid
Revision History
6/9/2009: Initally created
6/10/2009: Build or clause of multiple columns on one table
*/
--DECLARE @searchValue uniqueidentifier
--SET @searchValue = '{2A6814B9-8261-452D-A144-13264433864E}'
DECLARE abc CURSOR FOR
SELECT
c.TABLE_SCHEMA, c.TABLE_NAME, c.COLUMN_NAME
FROM INFORMATION_SCHEMA.Columns c
INNER JOIN INFORMATION_SCHEMA.Tables t
ON c.TABLE_NAME = t.TABLE_NAME
AND t.TABLE_TYPE = 'BASE TABLE'
WHERE DATA_TYPE = 'uniqueidentifier'
DECLARE @tableSchema varchar(200)
DECLARE @tableName varchar(200)
DECLARE @columnName varchar(200)
DECLARE @szQuery varchar(8000)
SET @szQuery = ''
DECLARE @lasttable varchar(255);
SET @lasttable='';
OPEN ABC
FETCH NEXT FROM abc INTO @tableSchema, @tableName, @columnName;
WHILE (@@FETCH_STATUS = 0)
BEGIN
IF(@lasttable=@tablename)
BEGIN
SET @szQuery = @szQuery + ' OR [' + @columnName + ']=''' + CAST(@searchValue AS varchar(50)) + '''';
END
ELSE
BEGIN
SET @lasttable = @tablename;
IF @szQuery <> ''
BEGIN
PRINT @szQuery
EXEC ('IF EXISTS (' + @szQuery + ') BEGIN ' + @szQuery + ' END');
END
SET @szQuery =
'SELECT '''+@tableSchema+'.'+@tableName+''' AS TheTable, '''+@columnName+''' AS TheColumn '+
'FROM '+@tableName+' '+
'WHERE '+@columnName+' = '''+CAST(@searchValue AS varchar(50))+''''
END
FETCH NEXT FROM abc INTO @tableSchema, @tableName, @columnName;
END
CLOSE abc
DEALLOCATE abc
IF @szQuery <> ''
BEGIN
PRINT @szQuery
EXEC ('IF EXISTS (' + @szQuery + ') BEGIN ' + @szQuery + ' END');
END
GO