SQL Server - script para colunas do banco de dados de atualização de varchar para nvarchar se não já nvarchar
-
05-07-2019 - |
Pergunta
Eu estou em uma situação onde eu preciso atualizar uma estrutura de banco de dados existente de varchar para nvarchar usando um script. Uma vez que este script é executado toda vez que um aplicativo de configuração é executado, eu preferiria determinar se uma coluna já foi alterado para nvarchar e não realizar um alter na mesa. As bases de dados que devo suportam são SQL Server 2000, 2005 e 2008.
Solução
A consulta a seguir deve obter o que você precisa:
IF EXISTS
(SELECT *
FROM sysobjects syo
JOIN syscolumns syc ON
syc.id = syo.id
JOIN systypes syt ON
syt.xtype = syc.xtype
WHERE
syt.name = 'nvarchar' AND
syo.name = 'MY TABLE NAME' AND
syc.name = 'MY COLUMN NAME')
BEGIN
ALTER ...
END
Outras dicas
Você pode executar o seguinte script que lhe dará um conjunto de comandos ALTER:
SELECT 'ALTER TABLE ' + isnull(schema_name(syo.id), 'dbo') + '.' + syo.name
+ ' ALTER COLUMN ' + syc.name + ' NVARCHAR(' + case syc.length when -1 then 'MAX'
ELSE convert(nvarchar(10),syc.length) end + ');'
FROM sysobjects syo
JOIN syscolumns syc ON
syc.id = syo.id
JOIN systypes syt ON
syt.xtype = syc.xtype
WHERE
syt.name = 'varchar'
and syo.xtype='U'
Há, no entanto, um par de rápida ressalvas para você.
- Isso só vai fazer tabelas. Você vai querer examinar todas as suas sprocs e funções para se certificar de que eles são alterados para
NVARCHAR
também. - Se você tem um
VARCHAR
> 4000 terá de modificá-lo para serNVARCHAR(MAX)
Mas aqueles deve ser facilmente factível com este modelo.
Se você quer isto para executar automagicamente você pode configurá-lo em uma cláusula WHILE
.
O problema com a resposta de Josef é que ele iria mudar campos NOT NULL
para NULL
depois de executar as consultas. As seguintes correções de manipulação de TI:
SELECT cmd = 'alter table [' + c.table_schema + '].[' + c.table_name
+ '] alter column [' + c.column_name + '] nvarchar('
+CASE WHEN CHARACTER_MAXIMUM_LENGTH<=4000
THEN CAST(CHARACTER_MAXIMUM_LENGTH as varchar(10)) ELSE 'max' END+')'
+ CASE WHEN IS_NULLABLE='NO' THEN ' NOT NULL' ELSE '' END,*
FROM information_schema.columns c
WHERE c.data_type='varchar'
ORDER BY CHARACTER_MAXIMUM_LENGTH desc
Créditos a resposta de Igor
Corrigido o problema de espaço e esquema adicionado
SELECT 'ALTER TABLE [' + isnull(schema_name(syo.object_id), sysc.name) + '].[' + syo.name
+ '] ALTER COLUMN ' + syc.name + ' NVARCHAR(' + case syc.max_length when -1 then 'MAX'
ELSE convert(nvarchar(10),syc.max_length) end + ');'
FROM sys.objects syo
JOIN sys.columns syc ON
syc.object_id= syo.object_id
JOIN sys.types syt ON
syt.system_type_id = syc.system_type_id
JOIN sys.schemas sysc ON
syo.schema_id=sysc.schema_id
WHERE
syt.name = 'varchar'
and syo.type='U'
Além disso atualizados para corrigir MAX sendo substituído com -1.
SELECT cmd = 'ALTER TABLE [' + c.table_schema + '].[' + c.table_name
+ '] ALTER COLUMN [' + c.column_name + '] NVARCHAR('
+CASE WHEN CHARACTER_MAXIMUM_LENGTH<=4000 THEN
CASE WHEN CHARACTER_MAXIMUM_LENGTH = -1 THEN
'MAX' ELSE CAST(CHARACTER_MAXIMUM_LENGTH AS VARCHAR(10)) END ELSE 'MAX' END+')'
+ CASE WHEN IS_NULLABLE='NO' THEN ' NOT NULL' ELSE '' END,*
FROM information_schema.columns c
WHERE c.data_type='VARCHAR'
ORDER BY CHARACTER_MAXIMUM_LENGTH DESC
Crédito para Resposta de Nezam
E outro para gerenciar valores padrão:
SELECT cmd =
CASE WHEN name IS NOT NULL THEN
'ALTER TABLE ' + c.table_name + ' DROP CONSTRAINT ' + d.name + '; ' +
'ALTER TABLE [' + c.table_schema + '].[' + c.table_name + '] ALTER COLUMN [' + c.column_name + '] ' +
'NVARCHAR(' +
CASE WHEN CHARACTER_MAXIMUM_LENGTH <= 4000 THEN
CASE WHEN CHARACTER_MAXIMUM_LENGTH = -1 THEN
'MAX'
ELSE
CAST(CHARACTER_MAXIMUM_LENGTH AS VARCHAR(10))
END
ELSE
'MAX'
END
+ ')' +
CASE WHEN IS_NULLABLE='NO' THEN ' NOT NULL' ELSE '' END + '; ' +
'ALTER TABLE '+ c.table_name + ' ADD CONSTRAINT ' + d.name +' DEFAULT '+ c.column_default + ' FOR ' + c.column_name + ';'
ELSE
'ALTER TABLE [' + c.table_schema + '].[' + c.table_name + '] ALTER COLUMN [' + c.column_name + '] ' +
'NVARCHAR(' +
CASE WHEN CHARACTER_MAXIMUM_LENGTH<=4000 THEN
CASE WHEN CHARACTER_MAXIMUM_LENGTH = -1 THEN
'MAX'
ELSE
CAST(CHARACTER_MAXIMUM_LENGTH AS VARCHAR(10))
END
ELSE
'MAX'
END
+ ')' +
CASE WHEN IS_NULLABLE='NO' THEN ' NOT NULL' ELSE '' END
END,d.name, c.*
FROM information_schema.columns c
LEFT OUTER JOIN sys.default_constraints d ON d.parent_object_id = object_id(c.table_name)
AND d.parent_column_id = columnproperty(object_id(c.table_name), c.column_name, 'ColumnId')
WHERE c.data_type='VARCHAR'
ORDER BY CHARACTER_MAXIMUM_LENGTH DESC