Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 Сравнение строк  [new]
Zberik
Member

Откуда:
Сообщений: 67
Уважаемый All, прошу разъяснить, почему при сравнении работает не так, как предполагалось.

Конкретнее ? Почему @str3 = 'CH', а не пустая строка или NULL ?

Пример кода:

SET TEXTSIZE 0
SET NOCOUNT ON
CREATE TABLE ASDF (LAND varchar(5))
INSERT INTO ASDF VALUES ('CH')
INSERT INTO ASDF VALUES ('CH')
INSERT INTO ASDF VALUES ('CH')
DECLARE @str1 VARCHAR(5), @str2 VARCHAR(5), @str3 VARCHAR(5)
SET @str1 = (SELECT TOP 1 LAND FROM ASDF WHERE (LAND > ''))
--Теперь @str1 = 'CH'
SET @str2 = @str1 + char(1)
--Теперь @str2 = 'CH☺'
SET @str3 = (SELECT TOP 1 LAND FROM ASDF WHERE (LAND > @str2))
--Проверяем результат
SELECT @str1 as STR1, @str2 as STR2, @str3 as STR3
select datalength(@str1) as str1length1, datalength (@str2) as str2length, datalength (@str3) as str3length, datalength (LAND) as landdatalength from ASDF
SET NOCOUNT OFF
DROP TABLE ASDF
GO

Результат:
STR1 STR2 STR3
----- ----- -----
CH CH CH

str1length1 str2length str3length landdatalength
----------- ----------- ----------- --------------
2 3 2 2
2 3 2 2
2 3 2 2

Условия работы:
База данных имеет collation Latin1_General_BIN
SELECT DATABASEPROPERTYEX('TEMIST2', 'IsAnsiPaddingEnabled')
Возвращает 0
15 дек 04, 16:39    [1183406]     Ответить | Цитировать Сообщить модератору
 Re: Сравнение строк  [new]
Алексей2003
Member

Откуда: Москва
Сообщений: 5645
select @@version
?

для спящего время бодрствования равносильно сну
15 дек 04, 17:19    [1183588]     Ответить | Цитировать Сообщить модератору
 Re: Сравнение строк  [new]
Taffy
Member

Откуда:
Сообщений: 20501
А мне вот тоже стало интересно.
Поэкспериментировала я тут и выяснила, что с CHAR(9) все идет нормально и только от1 до 8 такая странность.
Версия
Microsoft SQL Server 2000 - 8.00.760 (Intel X86)
Enterprise Edition on Windows NT 5.0 (Build 2195: Service Pack 4)
Показываю
SET NOCOUNT ON
DECLARE @str1 VARCHAR(5), @str2 VARCHAR(5), @str3 VARCHAR(5)

SET @str1 = char(1)
select @str1

SET @str2 = @str1 + char(1)
select @str2

select case when @str1 > @str2 
		then 'Не может этого быть'
		else 'Так верно'
		end
SET NOCOUNT OFF

--Результат
----- 


----- 


------------------- 
Не может этого быть

SET NOCOUNT ON

DECLARE @str1 VARCHAR(5), @str2 VARCHAR(5), @str3 VARCHAR(5)

SET @str1 = char(1)
select @str1

SET @str2 = @str1 + char(9)
select @str2

select case when @str1 > @str2 
		then 'Не может этого быть'
		else 'Так верно'
		end


SET NOCOUNT OFF

--Результат
----- 

      
----- 
	
                  
------------------- 
Так верно
Почему?
15 дек 04, 17:28    [1183627]     Ответить | Цитировать Сообщить модератору
 Re: Сравнение строк  [new]
Алексей2003
Member

Откуда: Москва
Сообщений: 5645
1. длина @str3 - null
2. и там и тут у меня выдает верно

для спящего время бодрствования равносильно сну
15 дек 04, 17:32    [1183650]     Ответить | Цитировать Сообщить модератору
 Re: Сравнение строк  [new]
Taffy
Member

Откуда:
Сообщений: 20501
2Алексей 2003 - это не ответ - "У меня верно". Значит дело в настройках сервера? Каких? Я же не спрашиваю - "А как у Вас?", Я спрашиваю "Почему у меня так же как и у Zberik получается такой результат?"
15 дек 04, 17:45    [1183689]     Ответить | Цитировать Сообщить модератору
 Re: Сравнение строк  [new]
Zberik
Member

Откуда:
Сообщений: 67
Microsoft SQL Server 2000 - 8.00.818 (Intel X86) May 31 2003 16:08:15 Copyright (c) 1988-2003 Microsoft Corporation Developer Edition on Windows NT 5.1 (Build 2600: Service Pack 2)

ПРОШУ УЧЕСТЬ!
В QueryAnalyzer-e ОБЯЗАТЕЛЬНО
Results in Text, а не Results in Grid
потому что Grid тупит, если работает со строками.
15 дек 04, 18:54    [1183921]     Ответить | Цитировать Сообщить модератору
 Re: Сравнение строк  [new]
Taffy
Member

Откуда:
Сообщений: 20501
Вопрос остался без ответа.
Мне-то оно не надо. Просто очень любопытно - в чем дело?
16 дек 04, 11:25    [1184897]     Ответить | Цитировать Сообщить модератору
 Re: Сравнение строк  [new]
GreenSunrise
Member

Откуда:
Сообщений: 12310
2Алексей2003: вы точно дочитали первый топик до конца? Там, где сказано про бинарный коллейшн базы? У меня, к примеру, такое странное поведение проявляется именно с бинарным коллейшном при всех прочих равных настройках.
16 дек 04, 11:28    [1184913]     Ответить | Цитировать Сообщить модератору
 Re: Сравнение строк  [new]
Alex Antonoff
Member

Откуда: Из лесу вестимо
Сообщений: 1251
У меня тоже был некий "глюк", была табличка с nvarchar(x), в которой в катакане лежали японские названия, мне нужно было разделить одну колонку на 3, по пробелам, дак вот если после пробела стояла одина из японских закорючек, то charindex упорно отказывался находить пробел ... Пришлось написать свой, который саьстрингом сравнивает символы ...
16 дек 04, 11:29    [1184917]     Ответить | Цитировать Сообщить модератору
 Re: Сравнение строк  [new]
Glory
Member

Откуда:
Сообщений: 104760
Taffy
Вопрос остался без ответа.
Мне-то оно не надо. Просто очень любопытно - в чем дело?

SET NOCOUNT ON
DECLARE @str1 VARCHAR(5), @str2 VARCHAR(5), @str3 VARCHAR(5)

SET @str1 = char(1)
select @str1

SET @str2 = @str1 + char(1)
select @str2

select case when @str1 > @str2 COLLATE Latin1_General_BIN
		then 'Impossible'
		else 'That''s right'
		end
select case when @str1 > @str2 COLLATE Latin1_General_CI_AS
		then 'Impossible'
		else 'That''s right'
		end

select case when @str1 > @str2 COLLATE Cyrillic_General_BIN
		then 'Impossible'
		else 'That''s right'
		end
select case when @str1 > @str2 COLLATE Cyrillic_General_CI_AS
		then 'Impossible'
		else 'That''s right'
		end
SET NOCOUNT OFF
Насколько я помню при сравнении строк разной длины наименьшая из них дополняется пробелами. Т.е. на самом деле в нашем случае сравниваются не char(1) c char(1)+char(1) а char(1)+char(32) с char(1)+char(1)
А так как в свою очередь collation с _BIN сравнивает строки переводя их в бинарное представление то получаем
что cast(@str1+char(32) as varbinary) > cast(@str2 as varbinary)
Что есть правильно.
16 дек 04, 11:39    [1184956]     Ответить | Цитировать Сообщить модератору
 Re: Сравнение строк  [new]
Zberik
Member

Откуда:
Сообщений: 67
2 Glory
Не нашел в BOL про то, что добивается пробелами меньшая строка при сравнении с более длинной. Если так, то конечно результат правильный.

Узость мышления на C\C++. Там при сравнении строк более длинная при прочих равных символах считается большей.
Предполагалось, что при
SELECT DATABASEPROPERTYEX('TEMIST2', 'IsAnsiPaddingEnabled')
Возвращает 0

никакого дополнения пробелами не будет. Это надо, цитирую "просто запомнить"

Спасибо за ответ.
16 дек 04, 12:24    [1185150]     Ответить | Цитировать Сообщить модератору
 Re: Сравнение строк  [new]
Glory
Member

Откуда:
Сообщений: 104760
Предполагалось, что при
SELECT DATABASEPROPERTYEX('TEMIST2', 'IsAnsiPaddingEnabled')
Возвращает 0
никакого дополнения пробелами не будет. Это надо, цитирую "просто запомнить"


AnsiPadding
1. Действует только на столбец таблицы при занесении в него значения.
2. Запоминается на момент создания этого столбца и меняется только пересозданием столбца
16 дек 04, 12:35    [1185209]     Ответить | Цитировать Сообщить модератору
 Re: Сравнение строк  [new]
Taffy
Member

Откуда:
Сообщений: 20501
Так. Кое-что стало понятно. Неясно только вот что. В моем примере правильное сравнение идет начиная с char(9).
Это значит дополнение идет char(9)?
У меня на сервере COLLATE SQL_Latin1_General_Cp1251_Cl_AS
16 дек 04, 13:08    [1185389]     Ответить | Цитировать Сообщить модератору
 Re: Сравнение строк  [new]
Glory
Member

Откуда:
Сообщений: 104760
Taffy
Так. Кое-что стало понятно. Неясно только вот что. В моем примере правильное сравнение идет начиная с char(9).
Это значит дополнение идет char(9)?
У меня на сервере COLLATE SQL_Latin1_General_Cp1251_Cl_AS

У меня как раз все начинает работать "правильно" с символа char(32) т.е. "пробела". До него все работает "неправильно"
16 дек 04, 13:11    [1185408]     Ответить | Цитировать Сообщить модератору
 Re: Сравнение строк  [new]
Taffy
Member

Откуда:
Сообщений: 20501
Glory
У меня как раз все начинает работать "правильно" с символа char(32) т.е. "пробела". До него все работает "неправильно"

И что это значит?
Нет, выводы для себя я сделала, но вот любопытство-то неудовлетворено...
16 дек 04, 13:44    [1185601]     Ответить | Цитировать Сообщить модератору
 Re: Сравнение строк  [new]
Glory
Member

Откуда:
Сообщений: 104760
Taffy
Glory
У меня как раз все начинает работать "правильно" с символа char(32) т.е. "пробела". До него все работает "неправильно"

И что это значит?
Нет, выводы для себя я сделала, но вот любопытство-то неудовлетворено...

Это значит что бинарное представление с добавленным пробелом будет больше
0x0120 > 0x0101
0x0220 > 0x0202
0x0320 > 0x0303
....

0x1F20 > 0x1F1F
0x2020 = 0x2020
16 дек 04, 13:49    [1185623]     Ответить | Цитировать Сообщить модератору
 Re: Сравнение строк  [new]
Taffy
Member

Откуда:
Сообщений: 20501
Glory

Это значит что бинарное представление с добавленным пробелом будет больше
0x0120 > 0x0101
0x0220 > 0x0202
0x0320 > 0x0303
....

0x1F20 > 0x1F1F
0x2020 = 0x2020

Спасибо, Glory! Вы безумно добры! Но это-то я как раз поняла. Я не поняла - почему у меня уже с char(9) начинает выдавать ожидаемый резльтат. То есть, если я не указываю коллейшены.
16 дек 04, 13:58    [1185669]     Ответить | Цитировать Сообщить модератору
 Re: Сравнение строк  [new]
Glory
Member

Откуда:
Сообщений: 104760
То есть, если я не указываю коллейшены.
Если вы не указываете то значит используется коллэйшен текущей базы
16 дек 04, 13:59    [1185676]     Ответить | Цитировать Сообщить модератору
 Re: Сравнение строк  [new]
Taffy
Member

Откуда:
Сообщений: 20501
Ладно, Бог с ним, с этим char(9).
Спасибо, Glory.
16 дек 04, 14:08    [1185721]     Ответить | Цитировать Сообщить модератору
 Re: Сравнение строк  [new]
Glory
Member

Откуда:
Сообщений: 104760
Я думаю что тогда ваш коллейшен SQL_Latin1_General_CP1251_CI_AS таким образом сравнивает символы. Коллэйшен же и есть набор правил сравнения символов с одинаковыми кодами.
16 дек 04, 14:29    [1185825]     Ответить | Цитировать Сообщить модератору
 Re: Сравнение строк  [new]
Zberik
Member

Откуда:
Сообщений: 67
2 Taffy
Glory объяснил, что у каждого collation свой набор правил, да и в BOL так же написано, хотя не сказано в каком порядке это происходит. Например в Вашем случае SQL_Latin1_General_CP1251_CI_AS, если Вы продолжите с char(9) до char(13), то все будет 'That''s right', а дальше снова 'Impossible' до char(32) - пробела.

Надо просто принять к сведению, что при сравнении где-то там в стеке по каким-то правилам строки выравниваются по длине и лишь ПОТОМ работает алгоритм сравнения.

По крайней мере я так СЕЙЧАС думаю. Можно наверно проверить в дебаггере...
17 дек 04, 09:41    [1187820]     Ответить | Цитировать Сообщить модератору
 Re: Сравнение строк  [new]
Glory
Member

Откуда:
Сообщений: 104760
Zberik

Надо просто принять к сведению, что при сравнении где-то там в стеке по каким-то правилам строки выравниваются по длине и лишь ПОТОМ работает алгоритм сравнения.

По крайней мере я так СЕЙЧАС думаю. Можно наверно проверить в дебаггере...

Я нигде не нахожу документированного потдтверждения того, что при сравнении строки выравниваются по длине наибольшей.
Но действительно складывается такое чувство, что именно так и происходит.
17 дек 04, 10:17    [1187975]     Ответить | Цитировать Сообщить модератору
 Re: Сравнение строк  [new]
Taffy
Member

Откуда:
Сообщений: 20501
Ага, я про то же. К сведению приняла, но ПОЧЕМУ так - не поняла. А за 9-13, 13-32 спасибо. Вот опять же - а где про это прочитать можно?
17 дек 04, 10:27    [1188025]     Ответить | Цитировать Сообщить модератору
 Re: Сравнение строк  [new]
Zberik
Member

Откуда:
Сообщений: 67
-- Хочу еще добавить пример для сравнений.

IF EXISTS (SELECT * FROM sysobjects WHERE id = OBJECT_ID(N'[K]') AND OBJECTPROPERTY(id, N'ISUSERTABLE') = 1)
DROP TABLE [K]
ELSE
PRINT 'CANNOT DROP TABLE [K]'
GO

CREATE TABLE K(
NR int IDENTITY (1, 1) NOT NULL ,
KOS varchar (40) COLLATE Latin1_General_BIN NULL ,
CONSTRAINT [K_NR] PRIMARY KEY CLUSTERED
( NR ) ON [PRIMARY]
) ON [PRIMARY]
GO

INSERT INTO K( KOS ) VALUES( 'ASDF' );
INSERT INTO K( KOS ) VALUES( 'ASDF ' ); -- 3 spaces
INSERT INTO K( KOS ) VALUES( 'asdf' );
GO

SELECT 'KOS' = '>' + KOS + '<' FROM K
GO

CREATE UNIQUE INDEX KEY_KOS_0 on K ( KOS );
GO

-- А если все-таки надо такой индекс иметь?
-- И ВАЖНО, чтобы пробелы учитывались.
-- Что делать честным людям?
11 дек 05, 17:19    [2161130]     Ответить | Цитировать Сообщить модератору
 Re: Сравнение строк  [new]
Zberik
Member

Откуда:
Сообщений: 67
-- Забыл добавить, что конечно же
sp_dboption 'LEWELL', 'ANSI padding', 'ON'
12 дек 05, 08:57    [2161752]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить