Выполнение оператора динамического обновления для каждой строки в наборе результатов - PullRequest
0 голосов
/ 02 февраля 2012

Я пытаюсь написать скрипт ролика данных, который найдет все столбцы даты и времени в базе данных demo и свернет их на x дней.Я пытаюсь сохранить это как можно более динамичным из-за того, что наша схема базы данных не установлена ​​(все еще в разработке).За исключением нескольких столбцов (которые я исключу позже), этот оператор идентифицирует оператор обновления, который переместит столбец datetime вперед:

SELECT 

    'UPDATE ' + [isc].[TABLE_NAME] + ' SET ' +
    [isc].[COLUMN_NAME] + 
    '= ' + [isc].[COLUMN_NAME] + '+ ' + 
    CAST(@DaysToRollForward AS NVARCHAR(5))  AS DySQL

FROM [INFORMATION_SCHEMA].COLUMNS AS isc
INNER JOIN [INFORMATION_SCHEMA].tables AS ist
    ON [ist].[TABLE_NAME] = [isc].[TABLE_NAME]
        WHERE [isc].[DATA_TYPE] = 'datetime'
            AND [ist].[TABLE_TYPE] = 'base table' 

Я не против использования курсора, поскольку это толькодемо-сервер, и никогда не будет видеть большую нагрузку.Мы просто делаем это, чтобы поддерживать актуальность наших записей, чтобы у нас всегда были данные, видимые в приложении.Я попробовал приведенный ниже курсор, и он не выполняет инструкции UPDATE.Есть идеи?У меня есть правильная идея?Я видел несколько постов помощи здесь, но большинство выполняет хранимую процедуру в блоке BEGIN - END.Кроме того, если есть подход, основанный на множестве, я был бы заинтересован в этом, хотя, если бы у моего курсора было легко исправить это было бы тоже хорошо.Как я уже говорил, это только демо / qa сервер.

USE [sCRMDB1_demo]

GO

DECLARE @OrganizationId BIGINT
DECLARE @dySQL NVARCHAR(256)
DECLARE @DaysToRollForward INT


SET @DaysToRollForward = 7

DECLARE db_cursor_rollbackdates CURSOR FOR

SELECT 
    'UPDATE ' + [isc].[TABLE_NAME] + ' SET ' +
    [isc].[COLUMN_NAME] + 
    '= ' + [isc].[COLUMN_NAME] + '+ ' + 
    CAST(@DaysToRollForward AS NVARCHAR(5))  AS DySQL

FROM [INFORMATION_SCHEMA].COLUMNS AS isc
INNER JOIN [INFORMATION_SCHEMA].tables AS ist
    ON [ist].[TABLE_NAME] = [isc].[TABLE_NAME]
        WHERE [isc].[DATA_TYPE] = 'datetime'
            AND [ist].[TABLE_TYPE] = 'base table' 


OPEN db_cursor_rollbackdates
FETCH NEXT FROM db_cursor_rollbackdates INTO @dySQL

WHILE @@FETCH_STATUS = 0

BEGIN
    --PRINT CAST(@dySQL AS NVARCHAR(200))
    EXEC (@dySQL)
    FETCH NEXT FROM db_cursor_rollbackdates
END

CLOSE db_cursor_rollbackdates
DEALLOCATE db_cursor_rollbackdates

1 Ответ

0 голосов
/ 02 февраля 2012

Вы ударите себя ...

В цикле у вас есть

FETCH NEXT FROM db_cursor_rollbackdates

Это, по сути, просто оператор выбора и оставляет @dySQL без изменений, поэтому ваша строка EXEC (@dySQL) делает одно и то же обновление снова и снова, поэтому вы не видите дней, обновленных в базе данных.Вам нужно изменить это на:

FETCH NEXT FROM db_cursor_rollbackdates INTO @dySQL

Это невозможно сделать в решении на основе множеств, так как вы обновляете несколько столбцов в нескольких таблицах.С точки зрения альтернативных решений найдите «Cursors vs Temp tables» и решите, как повлиять на производительность.Лично я предпочитаю подход с временными таблицами, но некоторые, возможно, будут линчевать, если я предположу, что это «правильный» путь!Кроме того, если у вас много таблиц с несколькими столбцами datetime и большими объемами данных, вы можете немного повысить производительность, используя временные таблицы и используя вложенные циклы, т. Е. Цикл по всем таблицам с хотя бы одним столбцом datetime, а затем внутри каждого цикла цикла.через все столбцы даты и времени, создавая sql динамически для каждой таблицы, так что для каждой таблицы выполняется только одно обновление, независимо от того, сколько у них столбцов даты и времени.Поскольку это сервер разработки, и на рабочем сервере такой же процедуры не потребуется, я бы не стал беспокоиться о его производительности на вашем месте, если он работает и концентрируется на других областях разработки!

Наконец, имейте в виду другие форматы даты (Smalldatetime, Date, Datetime2), ваш курсор в настоящее время не будет их поднимать.

...