Plutôt que d'exporter, de modifier manuellement et de réexécuter, vous pouvez essayer de faire le travail directement dans la base de données avec quelque chose comme:
DECLARE C CURSOR FOR
SELECT sm.definition, so.type
FROM sys.objects so
JOIN sys.all_sql_modules sm ON sm.object_id = so.object_id
WHERE so.type IN ('P', 'V')
ORDER BY so.name
DECLARE @SQL NVARCHAR(MAX), @ojtype NVARCHAR(MAX)
OPEN C
FETCH NEXT FROM C INTO @SQL, @ojtype
WHILE @@FETCH_STATUS = 0 BEGIN
IF @objtype = 'P' SET @SQL = REPLACE(@SQL, 'CREATE PROCEDURE', 'ALTER PROCEDURE')
IF @objtype = 'V' SET @SQL = REPLACE(@SQL, 'CREATE VIEW' , 'ALTER VIEW' )
SET @SQL = REPLACE(@SQL, 'GETDATE()', '[dbo].[getlocaldate]()')
--PRINT @SQL
EXEC (@SQL)
FETCH NEXT FROM C INTO @SQL, @ojtype
END
CLOSE C
DEALLOCATE C
bien sûr, l'étendre pour gérer les fonctions, les déclencheurs, etc.
Il y a quelques mises en garde:
Vous devrez peut-être être un peu plus lumineux et gérer des espaces blancs différents / supplémentaires entre CREATE
et PROCEDURE
/ VIEW
/ <other>
. Plutôt que le REPLACE
pour cela, vous préféreriez peut-être laisser le CREATE
en place et en exécuter un DROP
premier, mais cela risque de laisser les sys.depends
amis hors de portée, ce qui ALTER
peut ne pas être le cas, également en cas d' ALTER
échec, vous avez au moins l'objet existant toujours en place où avec DROP
+ CREATE
vous pouvez ne pas.
Si votre code a des odeurs "intelligentes" comme la modification de son propre schéma avec TSQL ad hoc, vous devrez vous assurer que la recherche et le remplacement de CREATE
-> ALTER
n'interfèrent pas avec cela.
Vous souhaiterez tester la régression de la ou des applications entières après l'opération, que vous utilisiez le curseur ou les méthodes d'exportation + édition + exécution.
J'ai utilisé cette méthode pour effectuer des mises à jour similaires à l'échelle du schéma dans le passé. C'est un peu un hack et semble assez moche, mais parfois c'est le moyen le plus simple / le plus rapide.
Les valeurs par défaut et autres contraintes peuvent également être modifiées de la même manière, bien que celles-ci puissent uniquement être supprimées et recréées plutôt que modifiées. Quelque chose comme:
DECLARE C CURSOR FOR
SELECT AlterDefaultSQL = 'ALTER TABLE [' +st.name+ '] DROP CONSTRAINT [' + si.name + '];'
+ CHAR(10)
+ 'ALTER TABLE [' +st.name+ '] ADD CONSTRAINT [' + si.name + '] DEFAULT '+REPLACE(si.definition, 'GETDATE()', '[dbo].[getlocaldate]()')+' FOR '+sc.name+';'
FROM sys.tables st
JOIN sys.default_constraints si ON si.parent_object_id = st.object_id
JOIN sys.columns sc ON sc.default_object_id = si.object_id
DECLARE @SQL NVARCHAR(MAX)
OPEN C
FETCH NEXT FROM C INTO @SQL
WHILE @@FETCH_STATUS = 0 BEGIN
--PRINT @SQL
EXEC (@SQL)
FETCH NEXT FROM C INTO @SQL
END
CLOSE C
DEALLOCATE C
Un peu plus de plaisir auquel vous devrez peut-être faire face: si vous partitionnez en fonction du temps, ces parties peuvent également avoir besoin d'être modifiées. Bien que le partitionnement à l'heure de manière plus granulaire que le jour soit rare, vous pouvez avoir des problèmes où les DATETIME
s sont interprétés par la fonction de partitionnement comme étant le jour précédent ou suivant selon le fuseau horaire, laissant vos partitions non alignées avec vos requêtes habituelles.