mssql выбрать все nvarchar с неправильной кодировкой - PullRequest
0 голосов
/ 29 апреля 2019

Я работаю со старой базой данных, где кто-то неправильно кодировал данные, прежде чем вставить их в базу данных.который приводит к тексту, как

«Неправильный текст» (в моем случае «�» является ø).

Я ищу способ найти все строки, где содержится столбецданные, как это, так что я могу исправить это.

До сих пор я пытался использовать регулярные выражения, как

SELECT * FROM table WHERE ([colm] not like '[a-zA-Z\s]%') 

, но независимо от того, что я делаю, я не могу найти способ выбрать толькоте, которые содержат '�'

поиск, подобный

    SELECT * FROM table WHERE ([colm] like '%�%') 

, также ничего не вернут.(попробовал, на всякий случай).

Я искал это в Google и здесь, в Stackoverflow, но либо у кого-то нет этой проблемы, либо я ищу не ту вещь.

Так что, если кто-то будет так любезен, чтобы помочь мне с этим, я был бы очень счастлив.

Спасибо за ваше время.

Ответы [ 4 ]

1 голос
/ 30 апреля 2019

Предполагая, что символ в строке действительно равен U+FFFD REPLACEMENT CHARACTER (�), и он не отображается в качестве символа замены, потому что на самом деле есть другие байты, которые не могут быть правильно декодированы, вы можете найти его с помощью

SELECT * FROM table WHERE [colm] LIKE N'%�%' COLLATE Latin1_General_BIN2

Или (во избежание дальнейших проблем с кодированием искажающих символов)

SELECT * FROM table WHERE [colm] LIKE N'%' + NCHAR(0xfffd) + N'%' COLLATE Latin1_General_BIN2

Требуется Unicode, поскольку � не существует ни в одном однобайтовом сопоставлении, а двоичное сопоставление требуется, посколькурегулярные сопоставления обрабатывают � так, как будто это вообще не встречается в строках.

1 голос
/ 29 апреля 2019

Как упоминал Джерун, использование binary, похоже, является подходящим вариантом.Лично я бы предложил использовать NGrams4k здесь, но вместо этого я построил таблицу быстрого подсчета, которая выполняет эту работу:

WITH N AS(
    SELECT N
    FROM (VALUES(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL)) N(N)),
Tally AS(
    SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS I
    FROM N N1, N N2, N N3, N N4)
SELECT V.Colm
FROM (VALUES(N'Wrong t�xt" (in my case the ''�'' is a ø)'),
            (N'This string is ok'))V(colm)
     JOIN Tally T ON LEN(V.Colm) >= T.I
     CROSS APPLY (VALUES(SUBSTRING(V.Colm,T.I,1))) SS(C) 
GROUP BY V.colm
HAVING COUNT(CASE CONVERT(binary(2),SS.C) WHEN 0xFDFF THEN 1 END) > 0;
1 голос
/ 29 апреля 2019

Попробуйте:

WHERE [colm] not like N'%[a-zA-Z]%'

Конечно, это должно возвращать значения с числами, пробелами и пунктуацией.

0 голосов
/ 29 апреля 2019

Вы можете заменить вхождения U+FFFD REPLACEMENT CHARACTER ( ) и сравнить его с исходным значением:

SELECT *
, CASE WHEN CONVERT(VARBINARY(MAX), t.colm) = CAST(REPLACE(CONVERT(VARBINARY(MAX), t.colm), 0xFDFF, 0x) AS VARBINARY(MAX)) THEN 1 ELSE 0 END AS EncodingCorrect
FROM (
    SELECT N'Wrong t�xt" (in my case the ''�'' is a ø)' AS colm
    UNION ALL
    SELECT 'Correct text'
    UNION ALL
    SELECT 'Wrong t?xt" (in my case the ''?'' is a ø)'
) t

@ Jeroen Mostert * Предложение 1006 * WHERE colm LIKE N'%�%' COLLATE Latin1_General_BIN2 кажется лучшим и более читабельным решением.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...