Arinyshka
Белый клоун, бедный мученик...
Постоялец
Offline
Пол:
|
|
« : 22-04-2008 09:15 » |
|
Возник еще вопрос: MS SQL, delphi Необходимо при вставке строки данных в таблицу проверять, не совпадает ли она с уже существующими. то есть двух записей типа "Ветеринарное свидетельство" быть не должно. Пробелы лишние я режу из строки в дельфе, достаточно просто сравнить строку с существующими. Вот и думаю - то ли AnsiCompareText , пробегая по всему датасету перед вызовом хранимой на вставку, то ли разумнее проверять это в самой хранимой... Есть такие механизмы? Сейчас последняя выглядит так:
CREATE PROCEDURE qur_add_RecordType @Name_item nvarchar(255), @active int AS BEGIN set nocount on begin transaction insert into QualitativeRecord ( RecordType, active ) values ( rtrim(ltrim(@Name_item)), @active ) if (@@error != 0) begin select 'Ok', -1 rollback transaction return end commit transaction END
Не подскажете?
|
|
|
Записан
|
Непонятная свобода обручем сдавила грудь...
|
|
|
Sla
|
|
« Ответ #1 : 22-04-2008 09:42 » |
|
1. создать/изменить таблицу с уникальным полем (тогда не нужно делать rollback) 2. повесить триггер на insert (триггер в данном случае, почти равен процедуре) 3. проверить наличие, а потом insert
|
|
|
Записан
|
Мы все учились понемногу... Чему-нибудь и как-нибудь.
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #2 : 22-04-2008 09:50 » |
|
а если назначить поле уникальным индексом ?
|
|
|
Записан
|
|
|
|
Sla
|
|
« Ответ #3 : 22-04-2008 10:01 » |
|
create trigger myTrig on myTable for insert as if (select count(*) from myTable where recordtType=trim(@Name_item))=1 /* хоть одна запись существует */ /* обработка ошибки */ ...
|
|
|
Записан
|
Мы все учились понемногу... Чему-нибудь и как-нибудь.
|
|
|
Arinyshka
Белый клоун, бедный мученик...
Постоялец
Offline
Пол:
|
|
« Ответ #4 : 22-04-2008 10:50 » |
|
а если назначить поле уникальным индексом ?
Мне кажется неверным назначать текстовое поле длиной до 255 симв уникальным.... Может, я неправа, опыта у меня меньше 0. 1. создать/изменить таблицу с уникальным полем (тогда не нужно делать rollback) 2. повесить триггер на insert (триггер в данном случае, почти равен процедуре) 3. проверить наличие, а потом insert
я, конечно, уже почитала, что такое триггер Но самым понятным мне кажется вариант 3) примерно так:
if (select RecordType from QualitativeRecord where RecordType = @Name_item)=0 begin insert into QualitativeRecord
Компилится, но дает ошибку при выполнении: Conversion failed when converting the varchar value 'ddd' to data type int. Зачем он конвертит значение? Без if процедура работает...
|
|
|
Записан
|
Непонятная свобода обручем сдавила грудь...
|
|
|
Arinyshka
Белый клоун, бедный мученик...
Постоялец
Offline
Пол:
|
|
« Ответ #5 : 22-04-2008 10:55 » |
|
О! сообразила Проверила на null, а не 0 - работает Осталось только понять - это стоит сделать уже внутри транзакции или до нее?
|
|
|
Записан
|
Непонятная свобода обручем сдавила грудь...
|
|
|
Sla
|
|
« Ответ #6 : 22-04-2008 11:05 » |
|
Arinyshka, конечно до
|
|
|
Записан
|
Мы все учились понемногу... Чему-нибудь и как-нибудь.
|
|
|
Arinyshka
Белый клоун, бедный мученик...
Постоялец
Offline
Пол:
|
|
« Ответ #7 : 22-04-2008 11:16 » |
|
ничего не сообразила Он любую строку отказывается вставить, что дубль, что нет :'( CREATE PROCEDURE qur_add_RecordType @Name_item nvarchar(255), @active int AS BEGIN Declare @message_ok nvarchar(40), @id int set nocount on set @message_ok = 'Тип документа уже существует!' if (select RecordType from QualitativeRecord where RecordType = @Name_item) = null begin begin transaction set @message_ok = 'Тип документа добавлен успешно!' insert into QualitativeRecord ( RecordType, active ) values ( rtrim(ltrim(@Name_item)), @active ) if (@@error != 0) begin select 'Ok', -1 rollback transaction return end commit transaction end set @id = @@identity SELECT @message_ok, 0, @id END
|
|
« Последнее редактирование: 22-04-2008 11:19 от Arinyshka »
|
Записан
|
Непонятная свобода обручем сдавила грудь...
|
|
|
Arinyshka
Белый клоун, бедный мученик...
Постоялец
Offline
Пол:
|
|
« Ответ #8 : 22-04-2008 12:25 » |
|
РАБОТАЕТ Вот так: CREATE PROCEDURE qur_add_RecordType @Name_item nvarchar(255), @active int AS BEGIN Declare @message_ok nvarchar(40), @id int set nocount on IF EXISTS (select * from QualitativeRecord where RecordType = @Name_item) begin set @message_ok = 'Тип документа уже существует!' set @id = @@identity SELECT @message_ok, -1, @id end ELSE begin begin transaction set @message_ok = 'Тип документа добавлен успешно!' insert into QualitativeRecord ( RecordType, active ) values ( rtrim(ltrim(@Name_item)), @active ) if (@@error != 0) begin select 'Ok', -1 rollback transaction return end commit transaction set @id = @@identity SELECT @message_ok, 0, @id end END
|
|
|
Записан
|
Непонятная свобода обручем сдавила грудь...
|
|
|
Sla
|
|
« Ответ #9 : 22-04-2008 12:33 » |
|
замени * на 1 CREATE PROCEDURE qur_add_RecordType @Name_item nvarchar(255), @active int AS BEGIN
Declare @message_ok nvarchar(40), @id int set nocount on IF EXISTS (select 1 from QualitativeRecord where RecordType = @Name_item) begin set @message_ok = 'Тип документа уже существует!' set @id = @@identity SELECT @message_ok, -1, @id end ELSE begin begin transaction
set @message_ok = 'Тип документа добавлен успешно!' insert into QualitativeRecord ( RecordType, active ) values ( rtrim(ltrim(@Name_item)), @active )
if (@@error != 0) begin
select 'Ok', -1 rollback transaction
return end
commit transaction
set @id = @@identity SELECT @message_ok, 0, @id end
END
|
|
|
Записан
|
Мы все учились понемногу... Чему-нибудь и как-нибудь.
|
|
|
little
|
|
« Ответ #10 : 22-04-2008 13:22 » |
|
а установка на поле уникального индекса (не ключа) не упростит задачу? или проверок всё равно не избежать?
|
|
|
Записан
|
|
|
|
Arinyshka
Белый клоун, бедный мученик...
Постоялец
Offline
Пол:
|
|
« Ответ #11 : 22-04-2008 14:16 » |
|
Заменила, работает... а Вы не поясните разницу? Уникальным сделала, но велено проверять дополнительно. Что велено, то положено, что положено, то покладено... Вот и развлекаюсь
|
|
|
Записан
|
Непонятная свобода обручем сдавила грудь...
|
|
|
RXL
Технический
Администратор
Offline
Пол:
|
|
« Ответ #12 : 22-04-2008 14:22 » |
|
Надо объявлять уникальный индекс и обрабатывать ошибку вставки. Так, как сейчас реализовано, не защищено от параллельной вставки, когда два запроса выполнили проверку одновременно и подошли к вставке. Вероятность такого конфликта всегда существует. С уникальным индексом код получается много проще и правильнее.
|
|
|
Записан
|
... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
|
|
|
Sla
|
|
« Ответ #13 : 22-04-2008 14:35 » |
|
Arinyshka, разница очевидна (или не очивидна ) select * from - может вернуть некий список, под который будет выделена память select 1 from - вернет чуть-чуть поменьше и потом... меня так учили , вернее я так учился сам на чужих исходниках, иногда не задумываясь, а принимая на веру чтобы не было возможности параллельного инсерта можно использовать конструкцию lock на select
|
|
|
Записан
|
Мы все учились понемногу... Чему-нибудь и как-нибудь.
|
|
|
Arinyshka
Белый клоун, бедный мученик...
Постоялец
Offline
Пол:
|
|
« Ответ #14 : 22-04-2008 15:12 » |
|
конструкцию lock на select все чудесатее и чудесатее а это как?
|
|
|
Записан
|
Непонятная свобода обручем сдавила грудь...
|
|
|
Sla
|
|
« Ответ #15 : 22-04-2008 15:31 » |
|
типа такога select * from table (LOCK) where bla-bla-bla
|
|
|
Записан
|
Мы все учились понемногу... Чему-нибудь и как-нибудь.
|
|
|
Arinyshka
Белый клоун, бедный мученик...
Постоялец
Offline
Пол:
|
|
« Ответ #16 : 22-04-2008 15:49 » |
|
Именно на select? не понятно... Впихнуть lock в строчку IF EXISTS (select 1 from QualitativeRecord where RecordType = @Name_item) не удается... да оно и понятно вроде, странно в подзапрос в условии что-то пихать..
|
|
|
Записан
|
Непонятная свобода обручем сдавила грудь...
|
|
|
Sla
|
|
« Ответ #17 : 22-04-2008 15:52 » |
|
IF EXISTS (select 1 from QualitativeRecord (LOCK)....
может я и ошибаюсь, что вполне возможно, даже реально
|
|
|
Записан
|
Мы все учились понемногу... Чему-нибудь и как-нибудь.
|
|
|
Arinyshka
Белый клоун, бедный мученик...
Постоялец
Offline
Пол:
|
|
« Ответ #18 : 22-04-2008 16:07 » |
|
"LOCK" is not a recognized table hints option. If it is intended as a parameter to a table-valued function, ensure that your database compatibility mode is set to 90.
|
|
|
Записан
|
Непонятная свобода обручем сдавила грудь...
|
|
|
RXL
Технический
Администратор
Offline
Пол:
|
|
« Ответ #19 : 22-04-2008 17:29 » |
|
Ну, ребята, вы тут устроили сборную солянку. Хоть раз бы до конца объяснили...
|
|
|
Записан
|
... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
|
|
|
Arinyshka
Белый клоун, бедный мученик...
Постоялец
Offline
Пол:
|
|
« Ответ #20 : 23-04-2008 07:24 » |
|
ага... пожалуйста
|
|
|
Записан
|
Непонятная свобода обручем сдавила грудь...
|
|
|
Sla
|
|
« Ответ #21 : 23-04-2008 08:02 » |
|
Самого заинтересовало почему exist select 1 лучше, чем exist select * The select list of a subquery introduced by EXISTS almost always consists of an asterisk (*). There is no reason to list column names because you are simply testing for the existence of rows that meet the conditions specified in the subquery.
SELECT col1 FROM MyTable WHERE EXISTS (SELECT * FROM Table2 WHERE MyTable.col1=Table2.col2)
The * will be expanded to some potentially big column list and then it will be determined that the semantics of the EXISTS does not require any of those columns, so basically all of them can be removed.
"SELECT 1" will avoid having to examine any unneeded metadata for that table during query compilation.
However, at runtime the two forms of the query will be identical and will have identical runtimes.
все сводится к одному select 1 = select const = select * но предпочтение отдается select 1
|
|
|
Записан
|
Мы все учились понемногу... Чему-нибудь и как-нибудь.
|
|
|
|