? Как заставить 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
Здравствуйте, 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.
Здравствуйте, pkarklin, Вы писали:
P>Здравствуйте, Аноним, Вы писали:
А>>Не получилось...
P>Что не получилось?! Вы приведенный мной скрипт запускали?! Где там CREATE INDEX?!
Да, я скопировал и в QA запустил. Про индексы ничего не было, это верно. Наверно я не точно описал проблему.
Нужно, чтобы сервер при создании уникального индекса, т.е. при проверке полей, различал поля, отличающиеся количеством пробелов в конце. Это также должно работать при запросах вида
SELECT * FROM K WHERE KOS = 'ASDF ' (1 пробел) — должна быть только 1 строчка. А у нас получается 3.
Если при создании БД запустить
exec sp_dboption 'LEWELL', 'ANSI padding', 'ON'
то все пробелы в конце полей сохраняются.
Вот с такой поправочкой, может хотя бы укажете где копать. Был бы очень признателен. А то я кроме как привести тип поля к varbinary ничего не придумал. Неужели мелкософт не оставил возможность сравнивать поля такого типа, как я указал?
Здравствуйте, 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'
Здравствуйте, 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<
Здравствуйте, pkarklin, Вы писали:
P>Здравствуйте, Zberik, Вы писали:
Z>>Увы, мне нужно чтобы запрос Z>>SELECT 'KOS' = '>' + KOS + '<' FROM K WHERE KOS = 'ASDF' Z>>вернул только одно значение 'ASDF'
P>Вы же '=' используете, а надо LIKE.
Вы верно заметили мою ошибку.
Спасибо большое, теперь я сообразил куда двигаться.
Так оно лучшее.
Еще раз спасибо.