Итерация SQL по всем таблицам

Я запускаю следующий код, чтобы извлечь все соответствующие строки из всех таблиц, которые имеют определенный столбец. Внешний IF должен проверить, существует ли столбец в таблице для этой итерации. Если нет, он должен завершить эту итерацию и перейти к следующей таблице. Если таблица имеет GCRecord столбец, он должен проверить, будет ли эта таблица возвращать какие-либо записи. Если нет записей для возврата, следует завершить эту итерацию и перейти к следующей таблице. Если есть записи, они должны отображаться в SSMS.

USE WS_Live

EXECUTE sp_MSforeachtable 
'
    USE WS_Live

    IF EXISTS(  SELECT * 
                FROM sys.columns
                WHERE columns.Object_ID = Object_ID(''?'')
                AND Name = ''GCRecord''
             ) 
    BEGIN
        IF EXISTS (SELECT * FROM ? WHERE GCRecord IS NOT NULL)

        BEGIN
            SELECT * FROM ? WHERE GCRecord IS NOT NULL
        END
    END
'

Кажется, это работает, потому что SSMS возвращает только сетки с действительными записями. Что я не понимаю: почему я все еще получаю эти ошибки?

Msg 207, Level 16, State 1, Line 10
Invalid column name 'GCRecord'.
Msg 207, Level 16, State 1, Line 13
Invalid column name 'GCRecord'.

РЕДАКТИРОВАТЬ

После использования предложений, у меня есть это:

USE WS_Live

EXECUTE sp_MSforeachtable 
'
    USE WS_Live

    IF EXISTS(SELECT * FROM sys.columns WHERE columns.Object_ID = Object_ID(''?'')AND Name = ''GCRecord'') 

    BEGIN
    IF EXISTS (SELECT * FROM ? WHERE GCRecord IS NOT NULL)

            BEGIN
               EXEC('' SELECT * FROM ? WHERE GCRecord IS NOT NULL'')
            END
    END
'

Который возвращает эту ошибку:

Msg 207, Level 16, State 1, Line 7
Invalid column name 'GCRecord'.

Который относится к этой строке

IF EXISTS(SELECT * FROM sys.columns WHERE columns.Object_ID = Object_ID(''?'')AND Name = ''GCRecord'') 

ОБНОВИТЬ

Я пробовал вложение EXEC утверждения, которые не сработали, но, используя выбранный ответ, я получил результаты, которые искал, без ошибок.

4 ответа

Решение

Используйте динамический запрос внутри begin, чтобы избежать внутренней предварительной компиляции кода, поскольку таблицы не содержат column 'GCRecord'

USE WS_Live
GO

EXECUTE sp_MSforeachtable 
'
    IF EXISTS(  SELECT * 
                FROM sys.columns
                WHERE columns.Object_ID = Object_ID(''?'')
                AND Name = ''GCRecord''
             ) 
    BEGIN

          EXEC(''          
                  IF EXISTS (SELECT * FROM ? WHERE GCRecord IS NOT NULL)
                 BEGIN
                         SELECT * FROM ? WHERE GCRecord IS NOT NULL
                 END
              '')
    END
'

Вы очень близки Используйте "EXEC"

USE WS_Live 

EXECUTE sp_MSforeachtable  
' 
    USE WS_Live 

    IF EXISTS(  SELECT *  
                FROM sys.columns 
                WHERE columns.Object_ID = Object_ID(''?'') 
                AND Name = ''GCRecord''
             ) 
    BEGIN
        EXEC(''SELECT * FROM ? WHERE GCRecord IS NOT NULL'')
    END
'

Используйте @whereand, чтобы упростить:

exec sp_MSforeachtable 
@command1='select * from ? where GCRecord is not null', 
@whereand='and exists(select 1 from sys.columns c where c.object_id = o.id 
                      and c.name = ''GCRecord'')' 

Пожалуйста, попробуйте этот динамический sql. удалить комментарий из exec когда ты будешь готов бежать

declare @t varchar(max) = ''

SELECT @t =  @t + 'SELECT * FROM ' + a.name + ' WHERE GCRecord IS NOT NULL;' + char(13)
                FROM sys.columns b join sys.objects a  on
                 b.Object_ID = a.Object_ID
                WHERE b.Name ='CreateDt'

Print  @t
--exec (@t)
Другие вопросы по тегам