| 
			| 
					
						| 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 myTrigon 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 | 
								|  | « Ответ #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 | 
								|  | « Ответ #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 |  
						| 
								|  |  
								|  |  Записан | 
 
 Мы все учились понемногу... Чему-нибудь и как-нибудь. |  |  | 
	|  |