SQL Server выбирает нулические символы unicode в строках nvarchar

94
8

У меня есть контент, который был импортирован в нашу базу данных SQL Server 2008 (с использованием сопоставления SQL_Latin1_General_CP1_CI_AS), который загрязнен UNICODE NULLS в столбцах nvarchar(128).

Воздействие на то, что оно взрывает наши java-библиотеки, когда они пытаются экспортировать контент в PDF-отчеты и другие подобные манипуляции.

Я пытаюсь найти и изменить значения в различных таблицах и столбцах. Некоторые сотрудники говорят, что оскорбительные ценности выглядят как 'usernam e' вместо 'username'.

При попытке найти эти оскорбительные UNICODE NULLS, я запустил следующий SQL:

SELECT name 
FROM users
WHERE name LIKE '%[^ -~]%' COLLATE Latin1_General_BIN

Возвращен следующий набор:

M
M
M
N
S
S
S
S
ÿþA

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

Есть ли способ использовать CONVERT и шестнадцатеричное значение - 0x00 для поиска UNICODE NULLS в строках nvarchar?

EDIT # 1:

select name, CAST(RIGHT(name,1) AS varbinary(128)) AS RIGHTER_1,
from users
where id=1

returns:

B 0x4200

Итак, эта буква "В" немного смешная. Здесь действительно UNICODE NULLS, и библиотеки не предназначены для обработки UNICODE. Они прочны с марками LATIN UTF8.

спросил(а) 2013-01-15T02:01:00+04:00 7 лет, 5 месяцев назад
1
Решение
78

Дайте этому оригинальному сообщению больше 9 месяцев, это, я уверен, слишком поздно для плаката. Но, согласно документации, nchar данных nchar и nvarchar являются Unicode. Они определяются как:

| Строковые типы данных, которые являются либо фиксированной длиной, nchar, либо переменной длиной, nvarchar, Unicode данными и используют набор символов UNICODE UCS-2.

UCS-2 означает, что каждый символ в столбце занимает 2 байта. Если данные являются одиночными байтовыми символами, старший байт будет 0x00, естественно, и каждый другой октет будет 0x00.

Первоначальная проблема заключалась в том, что потребитель почти наверняка ожидал данные ASCII или UTF-8, а не UCS-2/UTF-16. Скорее всего, столбцы должны были быть объявлены как char/varchar а не nchar/nvarchar. Правильным решением было бы сделать одно из следующего:

    Измените таблицу, чтобы столбцы были правильным типом данных. Измените запрос на преобразование столбцов с помощью функции convert(), таким образом: convert(varchar(4000),my_nvarchar_column) изменить потребителя, чтобы правильно использовать двухбайтовые символы.

ответил(а) 2013-10-21T22:55:00+04:00 6 лет, 8 месяцев назад
39

Попытка поиска нулевых последовательностей символов Юникода, использующих преобразования varbinary, может привести к ложным срабатываниям, например, следующий юникод в UTF16 LE:

20 00 00 A0

Строка представляет собой пробел, за которым следует символ Unicode A0. Оба значения являются допустимыми непустыми символами. Однако, если вы это сделали:

where charindex (0x0000, cast(UnicodeText as varbinary (max))) > 0

Вы получите ложное положительное значение между концом пробела и началом следующего символа.

Вот функция, которую я написал. Заметьте, он не очень хорошо работает с большим текстом, что-то, над чем я работаю над улучшением. Возможно, CLR-процесс будет работать лучше. Попробуй это:

    create function dbo.FindNullUnicode
(
@Input nvarchar(max)
,@StartPosition bigint = 1
)
returns bigint
as
begin
if @StartPosition < 1
set @StartPosition = 1;

declare @pos bigint = @StartPosition;
declare @len bigint = len(@Input);
declare @singlechar nchar(1);

while (@pos <= @len)
begin
if unicode(SUBSTRING(@input,@pos,1)) = 0
return @pos;

set @pos +=1;
end;
return 0;
end

ответил(а) 2013-10-21T22:40:00+04:00 6 лет, 8 месяцев назад
40

Вы можете использовать CAST(name AS varbinary(128)) чтобы увидеть значение как hex и изучить его.

Вы можете найти "нулевые символы", используя name LIKE '%'+CHAR(0)+'%' условия name LIKE '%'+CHAR(0)+'%', однако допустимая строка юникода может содержать нули, поэтому это, вероятно, не то, что вам нужно сделать.


Вы уверены, что проблема не в ваших библиотеках или в PDF-генераторе? Похоже, что вы имеете строки unicode в базе данных, но приложение интерпретирует их как строки ASCII.

ответил(а) 2013-01-15T12:00:00+04:00 7 лет, 5 месяцев назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема