Программирование SQL Server – обновление всех дат на заданное количество дней
-
21-08-2019 - |
Вопрос
У меня есть демонстрационная база данных с парой сотен таблиц.Каждая таблица обычно имеет по крайней мере одно поле с именем tstamp, которое представляет собой тип данных smalldatetime.В некоторых таблицах есть и другие поля дат.Многие таблицы также имеют один или несколько триггеров.
Я написал сценарий (сложный способ — см. ниже), который увеличивает поля даты в каждой таблице на заданное количество дней.Идея состоит в том, чтобы сделать данные более «актуальными», обновляя все даты на одинаковое количество дней.
Я уверен, что есть более простой способ сделать это, пройдя по системной таблице, чтобы идентифицировать каждую пользовательскую таблицу в базе данных, отключить все триггеры на ней, изменить каждое поле smalldatetime, добавив к нему количество дней, повторно включив триггеры. и переходим к следующему столу.Я просто понятия не имею, как писать такой T-SQL.
Есть желающие?
Спасибо.Джо
Пример сценария:
DECLARE @numDaysToAdd int
SET @numDaysToAdd = 100
ALTER TABLE someTableDISABLE TRIGGER someTrigger
UPDATE someTable
SET tstamp = DATEADD(day, @numDaysToAdd, tstamp)
-- update any other smalldatetime field in the table too.
ALTER TABLE someTable ENABLE TRIGGER someTrigger
-- same pattern for 200 more tables!
============================================================================= ================================================================== работает:
ОБЪЯВИТЬ @numDaysToAdd int
УСТАНОВИТЬ @numDaysToAdd = 1
ЕСЛИ @numDaysToAdd > 0
НАЧИНАТЬ
ОБЪЯВИТЬ @tablename varchar(100)
ОБЪЯВИТЬ @currtable varchar(100)
ОБЪЯВИТЬ @currcolumn varchar(100)
ОБЪЯВИТЬ @columnname varchar(100)
ОБЪЯВИТЬ @strSQL nvarchar(4000)
ОБЪЯВИТЬ tnames_cursor КУРСОР
ДЛЯ
ВЫБЕРИТЕ t.TABLE_NAME, c.COLUMN_NAME
FROM INFORMATION_SCHEMA.COLUMNS c присоединиться к INFORMATION_SCHEMA.TABLES t ON t.TABLE_NAME = c.TABLE_NAME
ГДЕ (c.DATA_TYPE = 'smalldatetime' ИЛИ c.DATA_TYPE = 'datetime') И t.TABLE_TYPE<>'VIEW'
ORDER BY t.TABLE_NAME, c.COLUMN_NAME DESC
ОТКРЫТЬ tnames_cursor
ПОЛУЧИТЬ СЛЕДУЮЩИЙ ИЗ tnames_cursor В @tablename, @columnname
SET @currcolumn = @columnname
SET @currtable = @имя_таблицы
SET @strSQL = N'UPDATE ' + @tablename + CHAR(13)+CHAR(10) + 'SET ' + @columnname + ' = DATEADD(day, ' + CONVERT(varchar(10),@numDaysToAdd) + ', ' + @имя_столбца + ')'
ПОКА (@@FETCH_STATUS = 0)
НАЧИНАТЬ
ЕСЛИ (@currtable = @tablename)
BEGIN
IF @currcolumn <> @columnname
SET @strSQL = @strSQL + N',' + CHAR(13)+CHAR(10) + @columnname + ' = DATEADD(day, ' + CONVERT(varchar(10),@numDaysToAdd) + ', ' + @columnname + ')'
END
ЕЩЕ
BEGIN
SET @currtable = @tablename
SET @currcolumn = @columnname
EXEC sp_executesql @strSQL
SET @strSQL = N'UPDATE ' + @tablename + CHAR(13)+CHAR(10) + 'SET ' + @columnname + ' = DATEADD(day, ' + CONVERT(varchar(10),@numDaysToAdd) + ', ' + @columnname + ')'
END
ПОЛУЧИТЬ СЛЕДУЮЩИЙ ИЗ tnames_cursor В @tablename, @columnname
КОНЕЦ
-Запустите окончательный оператор exec sp_executeql @strsql
ЗАКРЫТЬ tnames_cursor
DEALLOCATE tnames_cursor
КОНЕЦ
Решение
Ваше понимание правильное.Похоже, вам не хватает следующих частей:
- Как найти метаданные (какие таблицы у вас есть, и какие столбцы)
- Как построить SQL, чтобы пройти через столы.
Для № 1 см. представления системы. INFORMATION_SCHEMA.TABLES
и INFORMATION_SCHEMA.COLUMNS
:
-- add your own additional criteria
select t.TABLE_NAME, c.COLUMN_NAME from INFORMATION_SCHEMA.COLUMNS c
join INFORMATION_SCHEMA.TABLES t ON t.TABLE_NAME = c.TABLE_NAME
WHERE c.DATA_TYPE = 'datetime'
Для № 2 вы можете создать оператор SQL в виде строки, проходя по интересующим вас таблицам, а затем выполнить его с помощью sp_executesql
.
Другие советы
Я согласен.Другой вариант — использовать системные таблицы для генерации SQL для всех 200 таблиц.Затем вы можете использовать sp_execsql для выполнения.Выполнение не изменится, но избавит вас от необходимости печатать, что всегда важно :)
Следующий запрос предоставит вам список пользовательских таблиц и их столбцов типа smallDateTime.
SELECT sys.columns.name as tableName, sys.tables.name as columnName from sys.columns,sys.tables
where sys.columns.object_id=sys.tables.object_id and sys.columns.system_type_id=58 order by tableName
здесь 58 — это system_type_id для типа данных — smallDateTime.Вы можете проверить это из таблицы sys.types.
Используя курсор, вы можете перебирать набор результатов, чтобы получить каждую таблицу, а затем отключить триггеры для этой таблицы.Проверьте это для отключения/включения триггера http://msdn.microsoft.com/en-us/library/ms189748.aspx
Затем обновите каждый столбец в наборе результатов, относящийся к каждой таблице, а затем включите триггеры.
ваше здоровье