Já deve ter acontecido contigo: precisar mandar um script de BD para algum cliente mas ninguém faz idéia da versão que o banco de dados do cliente está.
Enfim, já passei por isso diversas vezes e tinha que assumir que o banco de homologação interno da empresa seria o correto. Então eu fiz esse script para tentar simplificar (um pouco) a minha vida ao equalizar tabelas de clientes. Segue abaixo o código:
/******************************************************************************
Objective...: Gerar um script de equalização tomando como base um database.
Author......: Paulo E. Scatena
Date........: 2015-04-05
*******************************************************************************/
/*Prefixo de tabelas - para gerar script somente de um range específico de tabelas
(por nome de objeto)*/
DECLARE @PREFIXO VARCHAR(10) = ''
SET NOCOUNT ON
DECLARE @T_NAME VARCHAR(255),
@C_NAME VARCHAR(255),
@C_TYPE VARCHAR(255),
@C_ISNL VARCHAR(3),
@C_LENC INT,
@C_LENN INT,
@C_LENP INT,
@C_DEF VARCHAR(255),
@C_COLL VARCHAR(255),
@U_TBL VARCHAR(255) = '',
@C_1ST BIT = 1,
@LINE_SEM_DF VARCHAR(MAX),
@IDT BIT = 0
CREATE TABLE #T_T (L BIGINT IDENTITY(1,1), LINE VARCHAR(5000))
CREATE TABLE #T_C (L BIGINT IDENTITY(1,1), TBL VARCHAR(255), LINE VARCHAR(5000))
DECLARE CUR_COLUMNS CURSOR FAST_FORWARD FOR
SELECT ISNULL(T.TABLE_NAME, ''),
ISNULL(COLUMN_NAME, ''),
ISNULL(DATA_TYPE, ''),
ISNULL(IS_NULLABLE, ''),
ISNULL(CHARACTER_MAXIMUM_LENGTH, 0),
ISNULL(NUMERIC_PRECISION, 0),
ISNULL(NUMERIC_SCALE, 0),
ISNULL(COLUMN_DEFAULT, ''),
ISNULL(COLLATION_NAME, ''),
CASE WHEN EXISTS(SELECT 1 FROM sys.identity_columns WHERE name = C.COLUMN_NAME) then 1 else 0 end
FROM INFORMATION_SCHEMA.COLUMNS C INNER JOIN INFORMATION_SCHEMA.TABLES T ON
(C.TABLE_NAME = T.TABLE_NAME)
AND T.TABLE_TYPE = 'BASE TABLE'
AND (ISNULL(@PREFIXO, '') = '' OR T.TABLE_NAME LIKE '%' + @PREFIXO + '%')
AND T.TABLE_NAME NOT LIKE 'SYS%'
ORDER BY T.TABLE_NAME
OPEN CUR_COLUMNS
FETCH NEXT FROM CUR_COLUMNS INTO
@T_NAME,
@C_NAME,
@C_TYPE,
@C_ISNL,
@C_LENC,
@C_LENN,
@C_LENP,
@C_DEF,
@C_COLL,
@IDT
WHILE @@FETCH_STATUS = 0
BEGIN
/*Parte do Create Table*/
IF(@T_NAME <> @U_TBL)
BEGIN
IF(@U_TBL <> '')
INSERT INTO #T_T(LINE) VALUES (')')
SET @C_1ST = 1
INSERT INTO #T_T(LINE) VALUES('IF(NOT EXISTS(SELECT 1 FROM SYSOBJECTS WHERE ID = OBJECT_ID(''' + ISNULL(@T_NAME, '') + ''')))')
INSERT INTO #T_T(LINE) VALUES('CREATE TABLE DBO.' + ISNULL(@T_NAME, '') + '(')
END
DECLARE @LINE VARCHAR(5000)
DECLARE @NN VARCHAR(20) = ''
DECLARE @DF VARCHAR(100) = ''
DECLARE @SZ VARCHAR(30) = ''
DECLARE @CN VARCHAR(100) = ''
DECLARE @IDENT VARCHAR(100) = ''
IF(@C_TYPE NOT IN ('int', 'datetime', 'bit', 'bigint', 'tinyint', 'text', 'uniqueidentifier',
'money', 'smalldatetime', 'smallint', 'image', 'binary'))
BEGIN
SET @SZ = '(' + LTRIM(RTRIM(
CASE WHEN @C_LENN <> 0 THEN STR(@C_LENN)
WHEN @C_LENC <> 0 THEN
CASE WHEN @C_LENC <> -1 THEN STR(@C_LENC) ELSE 'MAX' END
END +
CASE WHEN ISNULL(@C_LENP, 0) <> 0 THEN ',' + LTRIM(RTRIM(STR(@C_LENP))) ELSE '' END)) +
')'
END
SET @NN = CASE WHEN @C_ISNL = 'NO' THEN 'NOT NULL' ELSE '' END
SET @DF = CASE WHEN @C_ISNL = 'YES' AND @C_DEF = '' THEN
' DEFAULT ' +
CASE
WHEN @C_TYPE IN ('varbinary', 'binary', 'int', 'numeric', 'money', 'smallint', 'bigint', 'decimal') THEN '0'
WHEN @C_TYPE IN ('datetime', 'smalldatetime') THEN '(getdate())'
ELSE ''' '''
END
ELSE
CASE WHEN @C_ISNL = 'YES' AND @C_DEF <> '' THEN
CASE WHEN @C_DEF NOT LIKE '%NULL%' THEN ' DEFAULT ' + @C_DEF ELSE 'DEFAULT '' ''' END
ELSE
' '
END
END
SET @CN = CASE WHEN @C_COLL <> '' THEN 'COLLATE ' + @C_COLL ELSE '' END
SET @LINE = @C_NAME + ' ' + @C_TYPE + ' ' +
CASE WHEN @SZ <> '' THEN @SZ ELSE '' END + ' ' +
CASE WHEN @CN <> '' THEN @CN ELSE '' END + ' ' +
CASE WHEN @DF <> '' THEN @DF ELSE '' END + ' ' +
CASE WHEN @NN <> '' THEN @NN ELSE '' END + ' '
SET @IDENT = CASE WHEN @IDT = 1 THEN ' IDENTITY(1,1)' ELSE '' END
-- No alter table, o comando vai sem NOT NULL e nem default pois é só para equalizar banco
SET @LINE_SEM_DF = @C_NAME + ' ' + @C_TYPE + ' ' +
CASE WHEN @SZ <> '' THEN @SZ ELSE '' END + ' ' +
@IDENT +
CASE WHEN @CN <> '' THEN @CN ELSE '' END + ' '
INSERT INTO #T_T(LINE) VALUES(
CASE WHEN @C_1ST = 0 THEN ',' ELSE '' END + @LINE)
INSERT INTO #T_C(TBL, LINE) VALUES (@T_NAME, 'IF(NOT EXISTS(SELECT 1 FROM SYSCOLUMNS WHERE ID = OBJECT_ID(''' + @T_NAME + ''') AND NAME = ''' + @C_NAME + '''))')
INSERT INTO #T_C(TBL, LINE) VALUES(@T_NAME, 'ALTER TABLE [' + @T_NAME + '] ADD ' + @LINE_SEM_DF)
INSERT INTO #T_C(TBL, LINE) VALUES(@T_NAME, 'GO')
SET @U_TBL = @T_NAME
SET @C_1ST = 0
FETCH NEXT FROM CUR_COLUMNS INTO
@T_NAME,
@C_NAME,
@C_TYPE,
@C_ISNL,
@C_LENC,
@C_LENN,
@C_LENP,
@C_DEF,
@C_COLL,
@IDT
END
CLOSE CUR_COLUMNS
DEALLOCATE CUR_COLUMNS
INSERT INTO #T_T(LINE) VALUES (')')
PRINT '/*Criação de tabelas - Table Creation*/'
SELECT LINE FROM #T_T
ORDER BY L
PRINT '/*Ajustes de tabelas - Column Adjustments*/'
SELECT LINE FROM #T_C
ORDER BY L
DROP TABLE #T_T
DROP TABLE #T_C
SET NOCOUNT OFF
Espero que ajude!
Grande abraço e até a próxima!
Nenhum comentário:
Postar um comentário