Sqlserver
 sql >> Base de Dados >  >> RDS >> Sqlserver

Conversão de Unicode para não Unicode


Há algumas coisas a serem observadas aqui:

  1. Se você quiser ver exatamente qual caractere está lá, você pode converter o valor para VARBINARY que lhe dará o valor hexadecimal / binário de todos os caracteres na string e não há conceito de caracteres "ocultos" em hexadecimal:
    DECLARE @PostalCode NVARCHAR(20);
    SET @PostalCode = N'053000'+ NCHAR(0x2008); -- 0x2008 = "Punctuation Space"
    SELECT @PostalCode AS [NVarCharValue],
           CONVERT(VARCHAR(20), @PostalCode) AS [VarCharValue],
           CONVERT(VARCHAR(20), RTRIM(@PostalCode)) AS [RTrimmedVarCharValue],
           CONVERT(VARBINARY(20), @PostalCode) AS [VarBinaryValue];
    

    Devoluções:
    NVarCharValue   VarCharValue   RTrimmedVarCharValue   VarBinaryValue
    053000          053000?        053000?                0x3000350033003000300030000820
    

    NVARCHAR os dados são armazenados como UTF-16 que funciona em conjuntos de 2 bytes. Olhando para os últimos 4 dígitos hexadecimais para ver qual é o conjunto oculto de 2 bytes, vemos "0820". Como o Windows e o SQL Server são UTF-16 Little Endian (ou seja, UTF-16LE), os bytes estão na ordem inversa. Invertendo os 2 bytes finais -- 08 e 20 -- obtemos "2008", que é o "Espaço de pontuação" que adicionamos via NCHAR(0x2008) .

    Além disso, observe que RTRIM não ajudou em nada aqui.

  2. De forma simplista, você pode simplesmente substituir os pontos de interrogação por nada:
    SELECT REPLACE(CONVERT(VARCHAR(20), [PostalCode]), '?', '');
    

  3. Mais importante, você deve converter o [PostalCode] campo para VARCHAR para que não armazene esses caracteres. Nenhum país usa letras que não são representadas no conjunto de caracteres ASCII e que não são válidas para o tipo de dados VARCHAR, pelo menos até onde eu já li (consulte a seção inferior para referências). Na verdade, o que é permitido é um subconjunto bastante pequeno de ASCII, o que significa que você pode filtrar facilmente no caminho (ou apenas fazer o mesmo REPLACE como mostrado acima ao inserir ou atualizar):
    ALTER TABLE [table] ALTER COLUMN [PostalCode] VARCHAR(20) [NOT]? NULL;
    

    Certifique-se de verificar o NULL atual / NOT NULL configuração para a coluna e torná-lo o mesmo na instrução ALTER acima, caso contrário, ele pode ser alterado, pois o padrão é NULL se não for especificado.

  4. Se você não puder alterar o esquema da tabela e precisar fazer uma "limpeza" periódica dos dados ruins, poderá executar o seguinte:
    ;WITH cte AS
    (
       SELECT *
       FROM   TableName
       WHERE  [PostalCode] <>
                      CONVERT(NVARCHAR(50), CONVERT(VARCHAR(50), [PostalCode]))
    )
    UPDATE cte
    SET    cte.[PostalCode] = REPLACE(CONVERT(VARCHAR(50), [PostalCode]), '?', '');
    

    Lembre-se de que a consulta acima não deve funcionar de forma eficiente se a tabela tiver milhões de linhas. Nesse ponto, precisaria ser tratado em conjuntos menores por meio de um loop.

Para referência, aqui está o artigo da wikipedia para Código postal , que atualmente afirma que os únicos caracteres já usados ​​são:

E em relação ao tamanho máximo do campo, aqui está a Lista de códigos postais da Wikipedia