Сравнение строк
От: Zberik  
Дата: 12.12.05 09:42
Оценка:
? Как заставить MSSQL сервер различать строки, оканчивающиеся пробелами ?

Условия работы:
База данных имеет collation Latin1_General_BIN
sp_dboption 'DBNAME', 'ANSI padding', 'ON'

При создании индекса MSSQL сравнивает строки. На руках есть таблица, в которой поле, на котором хочу уникальный индекс, имеет значения типа 'ASDF' и 'ASDF ' (3 spaces). Кроме типа varbinary, что еще можете посоветовать?
Желательно бы чтобы работало с varchar.




Вот как заставить сервер различать подобные данные???





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
Re: Сравнение строк
От: pkarklin  
Дата: 12.12.05 10:51
Оценка:
Здравствуйте, Zberik, Вы писали:

Z>? Как заставить MSSQL сервер различать строки, оканчивающиеся пробелами ?

Z> ...
Z>Вот как заставить сервер различать подобные данные???

Если бы поле было NOT NULL, то можно бы было:
IF OBJECT_ID('[K]', 'Table') IS NOT NULL DROP TABLE [K]
GO
CREATE TABLE K(
NR int IDENTITY (1, 1) NOT NULL ,
KOS varchar (40) COLLATE Latin1_General_BIN NOT NULL,
C AS DATALENGTH(KOS)- LEN(KOS),
CONSTRAINT [K_NR] PRIMARY KEY CLUSTERED 
( NR ) ON [PRIMARY],
CONSTRAINT [K_C] UNIQUE 
( KOS, C ) ON [PRIMARY],
) ON [PRIMARY]
GO

INSERT INTO K( KOS ) VALUES( 'ASDF' );
INSERT INTO K( KOS ) VALUES( 'ASDF ' );
INSERT INTO K( KOS ) VALUES( 'ASDF  ' ); 
INSERT INTO K( KOS ) VALUES( 'asdf   ' );
INSERT INTO K( KOS ) VALUES( 'ASDF' );

GO

SELECT NR, C, 'KOS' = '>' + KOS + '<' FROM K
GO
Re[2]: Сравнение строк
От: Аноним  
Дата: 12.12.05 11:58
Оценка:
Здравствуйте, pkarklin, Вы писали:

P>Если бы поле было NOT NULL, то можно бы было:

...

К сожалению, 2 ЗАПРОСА

SELECT NR, C, 'KOS' = '>' + KOS + '<' FROM K WHERE KOS = 'ASDF '
и
CREATE UNIQUE INDEX KEY_KOS_0 on K ( KOS );

показывают, что
1) результат — 3 строчки
2) CREATE UNIQUE INDEX terminated because a duplicate key was found for index ID 3. Most significant primary key is 'ASDF '. The statement has been terminated.

Не получилось...

Вобщем-то, этот вопрос — продолжение моего старого поста
http://www.sql.ru/forum/actualthread.aspx?tid=146049

Подскажите пожалуйста кто-нибудь, есть ли возможность заставить таки сервер сравнивать так, как я хочу его заставить?
Re[3]: Сравнение строк
От: pkarklin  
Дата: 12.12.05 12:06
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Не получилось...


Что не получилось?! Вы приведенный мной скрипт запускали?! Где там CREATE INDEX?!
Re[4]: Сравнение строк
От: Zberik  
Дата: 12.12.05 13:40
Оценка:
Здравствуйте, pkarklin, Вы писали:

P>Здравствуйте, Аноним, Вы писали:


А>>Не получилось...


P>Что не получилось?! Вы приведенный мной скрипт запускали?! Где там CREATE INDEX?!


Да, я скопировал и в QA запустил. Про индексы ничего не было, это верно. Наверно я не точно описал проблему.

Нужно, чтобы сервер при создании уникального индекса, т.е. при проверке полей, различал поля, отличающиеся количеством пробелов в конце. Это также должно работать при запросах вида
SELECT * FROM K WHERE KOS = 'ASDF ' (1 пробел) — должна быть только 1 строчка. А у нас получается 3.

Если при создании БД запустить
exec sp_dboption 'LEWELL', 'ANSI padding', 'ON'
то все пробелы в конце полей сохраняются.

Вот с такой поправочкой, может хотя бы укажете где копать. Был бы очень признателен. А то я кроме как привести тип поля к varbinary ничего не придумал. Неужели мелкософт не оставил возможность сравнивать поля такого типа, как я указал?
Re[5]: Сравнение строк
От: pkarklin  
Дата: 12.12.05 14:26
Оценка:
Здравствуйте, Zberik, Вы писали:

Z>Вот с такой поправочкой, может хотя бы укажете где копать. Был бы очень признателен. А то я кроме как привести тип поля к varbinary ничего не придумал. Неужели мелкософт не оставил возможность сравнивать поля такого типа, как я указал?


Если только перейти на nvarchar:


IF OBJECT_ID('[K]', 'Table') IS NOT NULL DROP TABLE [K]
GO
CREATE TABLE K(
NR int IDENTITY (1, 1) NOT NULL ,
KOS nvarchar (40) NULL,
C AS (DATALENGTH(KOS) - LEN(KOS) * 2) / 2,
CONSTRAINT [K_NR] PRIMARY KEY CLUSTERED 
( NR ) ON [PRIMARY],
CONSTRAINT [K_NR1] UNIQUE 
( KOS, C ) ON [PRIMARY],

) ON [PRIMARY]
GO

INSERT INTO K( KOS ) VALUES( N'ASDF' );
INSERT INTO K( KOS ) VALUES( N'ASDF ' );
INSERT INTO K( KOS ) VALUES( N'ASDF  ' ); 
INSERT INTO K( KOS ) VALUES( N'asdf   ' );
GO
INSERT INTO K( KOS ) VALUES( N'ASDF' );
GO

SELECT NR, C, 'KOS' = '>' + KOS + '<' FROM K

SELECT 'KOS' = '>' + KOS + '<' FROM K WHERE KOS LIKE ' ASDF'
Re[6]: Сравнение строк
От: Zberik  
Дата: 14.12.05 07:32
Оценка:
Здравствуйте, pkarklin, Вы писали:

P>Если только перейти на nvarchar:



P>
P>IF OBJECT_ID('[K]', 'Table') IS NOT NULL DROP TABLE [K]
P>GO
P>CREATE TABLE K(
P>NR int IDENTITY (1, 1) NOT NULL ,
P>KOS nvarchar (40) NULL,
P>C AS (DATALENGTH(KOS) - LEN(KOS) * 2) / 2,
P>CONSTRAINT [K_NR] PRIMARY KEY CLUSTERED 
P>( NR ) ON [PRIMARY],
P>CONSTRAINT [K_NR1] UNIQUE 
P>( KOS, C ) ON [PRIMARY],

P>) ON [PRIMARY]
P>GO

P>INSERT INTO K( KOS ) VALUES( N'ASDF' );
P>INSERT INTO K( KOS ) VALUES( N'ASDF ' );
P>INSERT INTO K( KOS ) VALUES( N'ASDF  ' ); 
P>INSERT INTO K( KOS ) VALUES( N'asdf   ' );
P>GO

P>SELECT NR, C, 'KOS' = '>' + KOS + '<' FROM K

P>SELECT 'KOS' = '>' + KOS + '<' FROM K WHERE KOS LIKE ' ASDF'
P>



Увы, мне нужно чтобы запрос
SELECT 'KOS' = '>' + KOS + '<' FROM K WHERE KOS = 'ASDF'
вернул только одно значение 'ASDF'

А этот запрос мне возвращает три значения
>ASDF<
>ASDF <
>ASDF <

Пока что решил этот вопрос заменой типа на varbinary. жаль, что мелкософт не позволил мне такую вот вещь сделать с типом данных varchar.
Re[7]: Сравнение строк
От: pkarklin  
Дата: 14.12.05 07:39
Оценка:
Здравствуйте, Zberik, Вы писали:

Z>Увы, мне нужно чтобы запрос

Z>SELECT 'KOS' = '>' + KOS + '<' FROM K WHERE KOS = 'ASDF'
Z>вернул только одно значение 'ASDF'

Z>А этот запрос мне возвращает три значения

>>ASDF<
>>ASDF <
>>ASDF <

Не может такого быть:


SET NOCOUNT ON
GO
IF OBJECT_ID('[K]', 'Table') IS NOT NULL DROP TABLE [K]
GO
CREATE TABLE K(
NR int IDENTITY (1, 1) NOT NULL ,
KOS nvarchar (40) NULL,
C AS (DATALENGTH(KOS) - LEN(KOS) * 2) / 2,
CONSTRAINT [K_NR] PRIMARY KEY CLUSTERED 
( NR ) ON [PRIMARY],
CONSTRAINT [K_NR1] UNIQUE 
( KOS, C ) ON [PRIMARY],

) ON [PRIMARY]
GO

INSERT INTO K( KOS ) VALUES( N'ASDF' );
INSERT INTO K( KOS ) VALUES( N'ASDF ' );
INSERT INTO K( KOS ) VALUES( N'ASDF  ' ); 
INSERT INTO K( KOS ) VALUES( N'asdf   ' );

GO

SELECT NR, C, 'KOS' = '>' + KOS + '<' FROM K

SELECT 'KOS' = '>' + KOS + '<' FROM K WHERE KOS LIKE 'ASDF'

NR          C           KOS                                        
----------- ----------- ------------------------------------------ 
1           0           >ASDF<
2           1           >ASDF <
3           2           >ASDF  <
4           3           >asdf   <

KOS                                        
------------------------------------------ 
>ASDF<
Re[7]: Сравнение строк
От: pkarklin  
Дата: 14.12.05 07:49
Оценка:
Здравствуйте, Zberik, Вы писали:


Z>Увы, мне нужно чтобы запрос

Z>SELECT 'KOS' = '>' + KOS + '<' FROM K WHERE KOS = 'ASDF'
Z>вернул только одно значение 'ASDF'

Вы же '=' используете, а надо LIKE.
Re[8]: Сравнение строк
От: Zberik  
Дата: 15.12.05 12:00
Оценка:
Здравствуйте, pkarklin, Вы писали:

P>Здравствуйте, Zberik, Вы писали:



Z>>Увы, мне нужно чтобы запрос

Z>>SELECT 'KOS' = '>' + KOS + '<' FROM K WHERE KOS = 'ASDF'
Z>>вернул только одно значение 'ASDF'

P>Вы же '=' используете, а надо LIKE.


Вы верно заметили мою ошибку.
Спасибо большое, теперь я сообразил куда двигаться.
Так оно лучшее.
Еще раз спасибо.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.