Antes de fazer qualquer coisa, considere as perguntas feitas pelo @RDFozz em um comentário sobre a pergunta, a saber:
Há quaisquer outras fontes além de [Q].[G]
preencher esta tabela?
Se a resposta estiver fora de "Estou 100% certo de que esta é a única fonte de dados para esta tabela de destino", não faça alterações, independentemente de os dados atualmente na tabela poderem ser convertidos ou não sem perda de dados.
Existem quaisquer planos / discussões relacionadas com a adição de fontes adicionais para preencher esses dados no futuro próximo?
E eu acrescentaria uma pergunta relacionada: houve alguma discussão sobre o suporte a vários idiomas na tabela de origem atual (ie [Q].[G]
) convertendo -a para NVARCHAR
?
Você precisará perguntar ao redor para ter uma idéia dessas possibilidades. Presumo que você não tenha recebido nenhuma informação que apontaria nessa direção, caso contrário, você não faria essa pergunta, mas se essas perguntas forem consideradas "não", elas deverão ser feitas e solicitadas a um público amplo o suficiente para obter a resposta mais precisa / completa.
O principal problema aqui não é tanto ter pontos de código Unicode que não podem ser convertidos (nunca), mas ainda mais ter pontos de código que nem todos se encaixam em uma única página de código. Essa é a coisa legal do Unicode: ele pode conter caracteres de TODAS as páginas de código. Se você converter de NVARCHAR
- para onde não precisa se preocupar com páginas de código - para VARCHAR
, precisará garantir que o agrupamento da coluna de destino esteja usando a mesma página de código que a coluna de origem. Isso pressupõe ter uma fonte ou várias fontes usando a mesma página de código (embora não necessariamente o mesmo agrupamento). Mas se houver várias fontes com várias páginas de código, você poderá executar o seguinte problema:
DECLARE @Reporting TABLE
(
ID INT IDENTITY(1, 1) PRIMARY KEY,
SourceSlovak VARCHAR(50) COLLATE Slovak_CI_AS,
SourceHebrew VARCHAR(50) COLLATE Hebrew_CI_AS,
Destination NVARCHAR(50) COLLATE Latin1_General_CI_AS,
DestinationS VARCHAR(50) COLLATE Slovak_CI_AS,
DestinationH VARCHAR(50) COLLATE Hebrew_CI_AS
);
INSERT INTO @Reporting ([SourceSlovak]) VALUES (0xDE20FA);
INSERT INTO @Reporting ([SourceHebrew]) VALUES (0xE820FA);
UPDATE @Reporting
SET [Destination] = [SourceSlovak]
WHERE [SourceSlovak] IS NOT NULL;
UPDATE @Reporting
SET [Destination] = [SourceHebrew]
WHERE [SourceHebrew] IS NOT NULL;
SELECT * FROM @Reporting;
UPDATE @Reporting
SET [DestinationS] = [Destination],
[DestinationH] = [Destination]
SELECT * FROM @Reporting;
Retorna (segundo conjunto de resultados):
ID SourceSlovak SourceHebrew Destination DestinationS DestinationH
1 Ţ ú NULL Ţ ú Ţ ú ? ?
2 NULL ט ת ? ? ט ת ט ת
Como você pode ver, todos esses caracteres podem ser convertidos em VARCHAR
, mas não na mesma VARCHAR
coluna.
Use a seguinte consulta para determinar qual é a página de código para cada coluna da sua tabela de origem:
SELECT OBJECT_NAME(sc.[object_id]) AS [TableName],
COLLATIONPROPERTY(sc.[collation_name], 'CodePage') AS [CodePage],
sc.*
FROM sys.columns sc
WHERE OBJECT_NAME(sc.[object_id]) = N'source_table_name';
QUE ESTÁ DISSE ....
Você mencionou estar no SQL Server 2008 R2, MAS, não disse qual edição. Se você estiver no Enterprise Edition, esqueça todas essas conversões (já que provavelmente está fazendo isso apenas para economizar espaço) e ative a compactação de dados:
Implementação de compactação Unicode
Se você estiver usando o Standard Edition (e agora parece que você é 😞), há outra possibilidade de longo prazo: atualizar para o SQL Server 2016, já que o SP1 inclui a capacidade de todas as edições usarem a compactação de dados (lembre-se, eu disse "longo prazo "😉).
Obviamente, agora que acabou de ser esclarecido que há apenas uma fonte para os dados, você não precisa se preocupar, pois a fonte não pode conter caracteres somente Unicode ou caracteres fora do código específico. página. Nesse caso, a única coisa que você deve ter em mente é usar o mesmo agrupamento da coluna de origem ou pelo menos um que esteja usando a mesma página de código. Ou seja, se a coluna de origem estiver usando SQL_Latin1_General_CP1_CI_AS
, você poderá usar Latin1_General_100_CI_AS
no destino.
Depois de saber qual agrupamento usar, você pode:
ALTER TABLE ... ALTER COLUMN ...
para ser VARCHAR
(não se esqueça de especificar a corrente NULL
/ NOT NULL
configuração), que requer um pouco de tempo e um monte de espaço de log de transação para 87 milhões de linhas, ou
Crie novas colunas "ColumnName_tmp" para cada uma e preencha lentamente UPDATE
fazendo TOP (1000) ... WHERE new_column IS NULL
. Depois que todas as linhas forem preenchidas (e validadas, todas copiadas corretamente! Você pode precisar de um gatilho para manipular UPDATEs, se houver), em uma transação explícita, use sp_rename
para trocar os nomes das colunas "atuais" a serem " _Old "e, em seguida, as novas colunas" _tmp "para simplesmente remover o" _tmp "dos nomes. Em seguida, chame sp_reconfigure
a tabela para invalidar quaisquer planos em cache que façam referência à tabela e, se houver Visualizações que façam referência à tabela, você precisará chamar sp_refreshview
(ou algo assim). Depois de validar o aplicativo e o ETL estiver funcionando corretamente, você poderá soltar as colunas.
[G]
são ETLed para[P]
. Se[G]
forvarchar
, e o processo ETL é a única maneira pela qual os dados entram[P]
, a menos que o processo adicione caracteres Unicode verdadeiros, não deve haver nenhum. Se outros processos adicionam ou modificam dados[P]
, você precisa ter mais cuidado - apenas porque todos os dados atuais podem estarvarchar
, não significa que osnvarchar
dados não possam ser adicionados amanhã. Da mesma forma, é possível que o que estiver consumindo os dados[P]
precise denvarchar
dados.