Em vez de exportar, editar manualmente e executar novamente, você pode tentar fazer o trabalho diretamente no banco de dados com algo como:
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
é claro estendendo-o para lidar com funções, gatilhos e assim por diante também.
Existem algumas ressalvas:
Você pode precisar ser um pouco mais inteligente e lidar com espaços em branco diferentes / extras entre CREATE
e PROCEDURE
/ VIEW
/ <other>
. Ao invés do REPLACE
para que você pode preferir deixar em vez disso o CREATE
no lugar e executar um DROP
primeiro, mas esta riscos deixando sys.depends
e amigos fora dos eixos, onde ALTER
não podem, também, se ALTER
falhar, você pelo menos tem o objeto existente ainda no lugar onde, com DROP
+ CREATE
você pode não.
Se você codificar algum cheiro "inteligente", como modificar seu próprio esquema com TSQL ad-hoc, será necessário garantir que a pesquisa e a substituição de CREATE
-> ALTER
não interfiram nisso.
Você desejará testar a regressão do (s) aplicativo (s) inteiro (s) após a operação, independentemente de usar o cursor ou exportar + editar + executar métodos.
Eu usei esse método para fazer atualizações semelhantes em todo o esquema no passado. É um pouco complicado, e parece muito feio, mas às vezes é a maneira mais fácil / rápida.
Padrões e outras restrições também podem ser modificados da mesma forma, embora apenas possam ser eliminados e recriados em vez de alterados. Algo como:
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
Um pouco mais divertido com o qual você pode precisar lidar: se você estiver particionando com o tempo, essas partes também precisarão ser alteradas. Embora o particionamento no horário mais granularmente do que o dia seja raro, você pode ter problemas em que DATETIME
s são interpretados pela função de particionamento como sendo o dia anterior ou o próximo, dependendo do fuso horário, deixando suas partições desalinhadas com as consultas habituais.