sql >> Databáze >  >> RDS >> Sqlserver

Převod Unicode na Non-Unicode

Zde je několik věcí, které je třeba poznamenat:

  1. Pokud chcete přesně vidět, který znak tam je, můžete hodnotu převést na VARBINARY což vám dá hexadecimální / binární hodnotu všech znaků v řetězci a neexistuje žádný koncept "skrytých" znaků v hex:

    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];
    

    Vrátí:

    NVarCharValue   VarCharValue   RTrimmedVarCharValue   VarBinaryValue
    053000          053000?        053000?                0x3000350033003000300030000820
    

    NVARCHAR data jsou uložena jako UTF-16, které funguje ve 2bajtových sadách. Když se podíváme na poslední 4 hexadecimální číslice, abychom viděli, co je skrytá 2bajtová sada, vidíme „0820“. Protože Windows a SQL Server jsou UTF-16 Little Endian (tj. UTF-16LE), jsou bajty v obráceném pořadí. Otočení posledních 2 bajtů -- 08 a 20 -- dostaneme "2008", což je "mezera pro interpunkci", kterou jsme přidali pomocí NCHAR(0x2008) .

    Vezměte prosím na vědomí, že RTRIM zde vůbec nepomohlo.

  2. Zjednodušeně můžete otazníky nahradit ničím:

    SELECT REPLACE(CONVERT(VARCHAR(20), [PostalCode]), '?', '');
    
  3. Ještě důležitější je, že byste měli převést [PostalCode] pole na VARCHAR aby tyto znaky neukládal. Žádná země nepoužívá písmena, která nejsou zastoupena ve znakové sadě ASCII a která nejsou platná pro datový typ VARCHAR, alespoň pokud jsem o tom kdy četl (odkazy viz spodní část). Ve skutečnosti je povolena poměrně malá podmnožina ASCII, což znamená, že můžete snadno filtrovat na cestě dovnitř (nebo prostě udělat to samé REPLACE jak je uvedeno výše při vkládání nebo aktualizaci):

    ALTER TABLE [table] ALTER COLUMN [PostalCode] VARCHAR(20) [NOT]? NULL;
    

    Nezapomeňte zkontrolovat aktuální hodnotu NULL / NOT NULL nastavení pro sloupec a udělejte jej stejné v příkazu ALTER výše, jinak by se mohlo změnit, protože výchozí je NULL pokud není uvedeno.

  4. Pokud nemůžete změnit schéma tabulky a potřebujete provádět pravidelné „čištění“ od špatných dat, můžete spustit následující:

    ;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]), '?', '');
    

    Mějte prosím na paměti, že výše uvedený dotaz nemá fungovat efektivně, pokud má tabulka miliony řádků. V tom okamžiku by to muselo být zpracováno v menších sadách pomocí smyčky.

Zde je článek na wikipedii pro PSČ , který v současnosti uvádí, že jediné kdy byly použity znaky:

A pokud jde o maximální velikost pole, zde je Wikipedia seznam poštovních směrovacích čísel



  1. Migrace databáze členství ASP.NET do SQL Azure

  2. výpočet škálování funkcí mysql

  3. Převod z typu [java.lang.Object[]] na typ se nezdařil

  4. Zobrazit definici uložené procedury/funkce v MySQL