Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: Проверка на уникальность текстовой записи  (Прочитано 19727 раз)
0 Пользователей и 1 Гость смотрят эту тему.
Arinyshka
Белый клоун, бедный мученик...
Постоялец

by
Offline 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
Команда клуба

ua
Offline Offline
Пол: Мужской

WWW
« Ответ #1 : 22-04-2008 09:42 » 

1. создать/изменить таблицу с уникальным полем (тогда не нужно делать rollback)
2. повесить триггер на insert (триггер в данном случае, почти равен процедуре)
3. проверить наличие, а потом insert


Записан

Мы все учились понемногу... Чему-нибудь и как-нибудь.
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #2 : 22-04-2008 09:50 » 

а если назначить поле уникальным индексом ?
Записан

Sla
Команда клуба

ua
Offline Offline
Пол: Мужской

WWW
« Ответ #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
Белый клоун, бедный мученик...
Постоялец

by
Offline 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
Белый клоун, бедный мученик...
Постоялец

by
Offline Offline
Пол: Женский

« Ответ #5 : 22-04-2008 10:55 » 

О! сообразила Улыбаюсь Проверила на null, а не 0 - работает Улыбаюсь Осталось только понять - это стоит сделать уже внутри транзакции или до нее?
Записан

Непонятная свобода обручем сдавила грудь...
Sla
Команда клуба

ua
Offline Offline
Пол: Мужской

WWW
« Ответ #6 : 22-04-2008 11:05 » 

Arinyshka, конечно до Улыбаюсь
Записан

Мы все учились понемногу... Чему-нибудь и как-нибудь.
Arinyshka
Белый клоун, бедный мученик...
Постоялец

by
Offline 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
Белый клоун, бедный мученик...
Постоялец

by
Offline 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
Команда клуба

ua
Offline Offline
Пол: Мужской

WWW
« Ответ #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
Помогающий

de
Offline Offline
Пол: Мужской

« Ответ #10 : 22-04-2008 13:22 » 

а установка на поле уникального индекса (не ключа) не упростит задачу? или проверок всё равно не избежать?
Записан
Arinyshka
Белый клоун, бедный мученик...
Постоялец

by
Offline Offline
Пол: Женский

« Ответ #11 : 22-04-2008 14:16 » 

Заменила, работает...  Что, съел? а Вы не поясните разницу?
Уникальным сделала, но велено проверять дополнительно. Что велено, то положено, что положено, то покладено... Улыбаюсь Вот и развлекаюсь
Записан

Непонятная свобода обручем сдавила грудь...
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #12 : 22-04-2008 14:22 » 

Надо объявлять уникальный индекс и обрабатывать ошибку вставки. Так, как сейчас реализовано, не защищено от параллельной вставки, когда два запроса выполнили проверку одновременно и подошли к вставке. Вероятность такого конфликта всегда существует. С уникальным индексом код получается много проще и правильнее.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Sla
Команда клуба

ua
Offline Offline
Пол: Мужской

WWW
« Ответ #13 : 22-04-2008 14:35 » 

Arinyshka, разница очевидна (или не очивидна Улыбаюсь )
select * from - может вернуть некий список, под который будет выделена память
select 1 from - вернет чуть-чуть поменьше

и потом... меня так учили Улыбаюсь , вернее я так учился сам на чужих исходниках, иногда не задумываясь, а принимая на веру
чтобы не было возможности параллельного инсерта можно использовать конструкцию lock на select
Записан

Мы все учились понемногу... Чему-нибудь и как-нибудь.
Arinyshka
Белый клоун, бедный мученик...
Постоялец

by
Offline Offline
Пол: Женский

« Ответ #14 : 22-04-2008 15:12 » 

конструкцию lock на select все чудесатее и чудесатее Улыбаюсь а это как?
Записан

Непонятная свобода обручем сдавила грудь...
Sla
Команда клуба

ua
Offline Offline
Пол: Мужской

WWW
« Ответ #15 : 22-04-2008 15:31 » 

типа такога
select *  from table (LOCK) where bla-bla-bla
Записан

Мы все учились понемногу... Чему-нибудь и как-нибудь.
Arinyshka
Белый клоун, бедный мученик...
Постоялец

by
Offline Offline
Пол: Женский

« Ответ #16 : 22-04-2008 15:49 » 

Именно на select? не понятно... Впихнуть lock в строчку IF EXISTS (select  1  from  QualitativeRecord  where RecordType = @Name_item) не удается... да оно и понятно вроде, странно в подзапрос в условии что-то пихать..
Записан

Непонятная свобода обручем сдавила грудь...
Sla
Команда клуба

ua
Offline Offline
Пол: Мужской

WWW
« Ответ #17 : 22-04-2008 15:52 » 

IF EXISTS (select  1  from  QualitativeRecord  (LOCK)....


может я и ошибаюсь, что вполне возможно, даже реально
Записан

Мы все учились понемногу... Чему-нибудь и как-нибудь.
Arinyshka
Белый клоун, бедный мученик...
Постоялец

by
Offline 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
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #19 : 22-04-2008 17:29 » 

Ну, ребята, вы тут устроили сборную солянку. Хоть раз бы до конца объяснили...
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Arinyshka
Белый клоун, бедный мученик...
Постоялец

by
Offline Offline
Пол: Женский

« Ответ #20 : 23-04-2008 07:24 » 

ага... пожалуйста Улыбаюсь
Записан

Непонятная свобода обручем сдавила грудь...
Sla
Команда клуба

ua
Offline Offline
Пол: Мужской

WWW
« Ответ #21 : 23-04-2008 08:02 » new

Самого заинтересовало почему 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
Записан

Мы все учились понемногу... Чему-нибудь и как-нибудь.
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines