SQL: необходимо запросить более 5900 таблиц для определенного значения, но возникла ошибка выделения памяти - PullRequest
2 голосов
/ 03 ноября 2011

В Microsoft SQL Server 2008 я пытаюсь вернуть список имен таблиц, которые содержат определенное значение в определенном поле.Из-за количества таблиц, к которым он обращается, я получаю ошибку выделения памяти, и она дает сбой.
Я хочу иметь возможность возвращать имя таблицы ТОЛЬКО для тех таблиц, где значение существует, и, надеюсь, избежать проблемы выделения памяти, а такжеизбегайте чтения 5900 строк в журнале, ища результаты ...

Я рассмотрю пример моего кода ниже, ища поле с именем PAINTCOLOUR, которое содержит "СИНИЙ".

SET NOCOUNT ON
go

DECLARE @tablename nvarchar(256)
DECLARE @sqlStatement nvarchar(300)

Получить все таблицы из БД, где существует поле с именем "PAINTCOLOUR"

DECLARE tnames_cursor CURSOR FOR SELECT A.name
FROM [dbName.dbo.sysobjects] A
    WHERE A.name in (SELECT B.RECNAME FROM TBLRECFIELD B WHERE B.FIELDNAME     = 'PAINTCOLOUR' AND B.RECNAME = A.name) 
    ORDER BY A.name

Перебрать tnames_cursor, передавая каждое имя таблицы в оператор Select ниже

OPEN tnames_cursor

FETCH NEXT FROM tnames_cursor INTO @tablename

WHILE (@@fetch_status <> -1)
BEGIN
    IF (@@fetch_status <> -2)

Выберите вместо переданного @tablename, чтобы увидеть, существует ли значение «СИНИЙ» в поле PAINTCOLOUR, и если да, то сколько раз.
МОЙ ВОПРОС ЗДЕСЬ: Могу ли я как-нибудь написать этот запрос лучшеизбежать проблемы выделения памяти и избежать просмотра всех строк в журнале, где не было найдено результатов для данной таблицы?

SET @sqlStatement = 'select '''+@tablename+''' AS ''RECORD NAME'', COUNT(*) AS ''COUNT OF RECORDS'' from '+@tablename+' where PAINTCOLOUR = ''BLUE'' HAVING COUNT (*) > 0 '


EXEC (@sqlStatement)

    FETCH NEXT FROM tnames_cursor INTO @tablename
END
go
DEALLOCATE tnames_cursor
go

Ответы [ 2 ]

1 голос
/ 03 ноября 2011

Итак, я вижу, что вы уже поняли это, но я был заинтригован.Вот мой ответ, который избегает использования счетчиков, поэтому я думаю, что это будет намного быстрее.Он использует INFORMATION_SCHEMA для ограничения количества таблиц на основе имен столбцов и запроса EXISTS, а не GROUP BY для поиска значений.Если вы действительно заинтересованы в подсчете записей с СИНИМ, это не сработает.

SET NOCOUNT ON

DECLARE @tableschema nvarchar(256);
DECLARE @tablename nvarchar(256);
DECLARE @sqlStatement nvarchar(300);

DECLARE @tblOutput TABLE (TableName nvarchar(256));

Declare tnames_cursor Cursor FOR
    Select t.table_schema, t.table_name
        from information_schema.tables t
            Inner Join information_schema.columns c
            on t.table_schema = c.table_schema and t.table_name=c.table_name
    Where c.column_name='PAINTCOLOUR' and Table_type='BASE TABLE'

OPEN tnames_cursor
FETCH NEXT FROM tnames_cursor INTO @tableschema, @tablename
WHILE @@fetch_status = 0
    BEGIN
        DECLARE @rows int;
        Set @sqlStatement = 'Select @rows=1 Where Exists (select 1 from ' 
            + @tableschema + '.' + @tablename 
            + ' where PAINTCOLOUR = ''BLUE'')'

        exec sp_executesql @sqlStatement, @params=N'@rows INT OUTPUT', @rows=@rows OUTPUT

        If @rows > 0 
            INSERT INTO @tblOutput Values (@tablename)

        FETCH NEXT FROM tnames_cursor INTO @tableschema, @tablename
    END

CLOSE tnames_cursor
DEALLOCATE tnames_cursor

SET NOCOUNT OFF

Select * from @tblOutput
0 голосов
/ 04 ноября 2011

Мое решение: я создал временную таблицу и записал свои результаты в нее, где число было больше 0. Затем я просто запрашиваю таблицу tmp.Примечание. Я удаляю таблицу tmp и заново создаю ее каждый раз, когда мы работаем в нестабильных средах, которые часто обновляются.

- Цель SQL - вернуть список имен таблиц, в которых есть значение«Синий» в поле PAINTCOLOUR.

SET NOCOUNT ON
go

DECLARE @tablename nvarchar(256)
DECLARE @sqlStatement nvarchar(300)

- Сначала получите все таблицы из БД, где существует поле с именем «PAINTCOLOUR», и сохраните их в tnames_cursor

DECLARE tnames_cursor CURSOR FOR SELECT A.name
FROM [dbPath] A
    WHERE A.name in (SELECT B.RECNAME FROM TBLRECFIELD B WHERE  B.FIELDNAME  = 'PAINTCOLOUR' AND B.RECNAME = A.name) 
    ORDER BY A.name

-NEW: если MY_TMP_TBL существует, отбросить его

IF object_id('dbo.MY_TMP_TBL') is not null
DROP TABLE dbo.MY_TMP_TBL

- NEW: создать временную таблицу MY_TMP_TBL

CREATE TABLE MY_TMP_TBL
(
TABLENAME varchar(255),
COUNTOFRECORDS varchar(255)
)

- перебрать tnames_cursor, передавая каждое имя таблицы в оператор Select ниже

OPEN tnames_cursor

FETCH NEXT FROM tnames_cursor INTO @tablename

WHILE (@@fetch_status <> -1)
BEGIN
    IF (@@fetch_status <> -2)

- ОБНОВЛЕНО: Выберите для каждого @tablename имя, чтобы увидеть, существует ли значение «СИНИЙ» в поле PAINTCOLOUR, и если да, то сколько раз.Записать результаты во временную таблицу --MY_TMP_TBL, где счетчик больше 0.

SET @sqlStatement = 'INSERT INTO MY_TMP_TBL (TABLENAME, COUNTOFRECORDS)    SELECT '''+@tablename+''', COUNT(*) from PS_'+RTRIM(UPPER(@tablename))+' where PAINTCOLOUR = ''BLUE'' HAVING COUNT (*) > 0 '


EXEC (@sqlStatement)

    FETCH NEXT FROM tnames_cursor INTO @tablename
END
go
DEALLOCATE tnames_cursor
go

- NEW: теперь вы можете запросить результаты MY_TMP_TBL.

SELECT * FROM MY_TMP_TBL;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...