Sqlserver
 sql >> Baza danych >  >> RDS >> Sqlserver

Konwersja Unicode do Non-Unicode

Należy tutaj zwrócić uwagę na kilka rzeczy:

  1. Jeśli chcesz zobaczyć dokładnie, który znak się tam znajduje, możesz przekonwertować wartość na VARBINARY co da ci wartość szesnastkową / binarną wszystkich znaków w ciągu i nie ma pojęcia "ukrytych" znaków w szesnastkowym:

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

    Zwroty:

    NVarCharValue   VarCharValue   RTrimmedVarCharValue   VarBinaryValue
    053000          053000?        053000?                0x3000350033003000300030000820
    

    NVARCHAR dane są przechowywane jako UTF-16, który działa w zestawach 2-bajtowych. Patrząc na ostatnie 4 cyfry szesnastkowe, aby zobaczyć, jaki jest ukryty zestaw 2 bajtów, widzimy „0820”. Ponieważ Windows i SQL Server są UTF-16 Little Endian (tj. UTF-16LE), bajty są w odwrotnej kolejności. Odwracanie ostatnich 2 bajtów -- 08 i 20 -- otrzymujemy "2008", czyli "spację interpunkcyjną" dodaną przez NCHAR(0x2008) .

    Pamiętaj też, że RTRIM tu w ogóle nie pomogło.

  2. Upraszczając, możesz po prostu zastąpić znaki zapytania niczym:

    SELECT REPLACE(CONVERT(VARCHAR(20), [PostalCode]), '?', '');
    
  3. Co ważniejsze, powinieneś przekonwertować [PostalCode] pole do VARCHAR aby nie przechowywać tych znaków. Żaden kraj nie używa liter, które nie są reprezentowane w zestawie znaków ASCII i które nie są poprawne dla typu danych VARCHAR, przynajmniej o ile kiedykolwiek czytałem (patrz dolna sekcja dla odniesień). W rzeczywistości dozwolony jest raczej mały podzbiór ASCII, co oznacza, że ​​możesz łatwo filtrować po drodze (lub po prostu zrobić to samo REPLACE jak pokazano powyżej podczas wstawiania lub aktualizacji):

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

    Pamiętaj, aby sprawdzić aktualny NULL / NOT NULL ustawienie dla kolumny i zrób to samo w powyższej instrukcji ALTER, w przeciwnym razie może zostać zmienione, ponieważ wartość domyślna to NULL jeśli nie określono.

  4. Jeśli nie możesz zmienić schematu tabeli i musisz przeprowadzać okresowe „czyszczenie” złych danych, możesz uruchomić następujące polecenie:

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

    Należy pamiętać, że powyższe zapytanie nie działa wydajnie, jeśli tabela ma miliony wierszy. W tym momencie musiałaby być obsługiwana w mniejszych zestawach za pomocą pętli.

Dla porównania, oto artykuł w Wikipedii dotyczący Kod pocztowy , który obecnie stwierdza, że ​​jedynymi używanymi znakami są:

A jeśli chodzi o maksymalny rozmiar pola, oto Wikipedia Lista kodów pocztowych



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Jak użyć wyzwalacza aktualizacji do aktualizacji innej tabeli?

  2. Wartości NULL wewnątrz klauzuli NOT IN

  3. Problem z uprawnieniami programu SQL Server 2008 OPENROWSET

  4. Sprawdź, czy zainstalowany jest serwer SQL (dowolna wersja)?

  5. Jak aktualizować i zamawiać za pomocą ms sql