![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Работа уникальными значениями [D7, IB6.x, MSSQL]
den_777 © (2004-05-24 09:46:00)Пока мне приходилось работать только с INFORMIX и IB,FB. Поэтому приведу пример на этих базах.
Надо чтобы была возможность автоматической и ручной вставки значения в поле которое является PRIMARY KEY, т.е. для таблицы с полями ID и CNAME проходили оба SQL insert into tbl1(id,cname) values(0,"myname") и insert into tbl1(cname) values("myname")
Соответственно в INFORMIX я просто задаю этому полю тип SERIAL и все, больше ничего делать не надо. В первом случае INFORMIX просто проверяет не противоречит ли вставляемое мной значение уникальности и если нет то вставляет его во втором случае сам генерит следующее значение.
В IB,FB это решается с помощью генератора и триггера IF NEW.ID IS NULL THEN NEW.ID=GEN_ID(MY_GEN,1).
Вопрос как таких же действий добиться от MSSQL. И вопрос в догонку, если в других базах какой-либо функционал был заложен в триггер перед вставкой, то как этот же функционал реализовать в MSSQL.
den_777 (2004-05-24 13:45:00) [41]
> Всё-таки неясно, зачем самому вставлять ID ? Ведь это фактически
> суррогатный ключ, и в величине его значения никакого смысла
> нет.
Раз уж программисты написавшие INFORMIX (по моему мнению СУБД INFORMIX на порядок лучше чем MSSQL и по надежности, и по скорости работы, и по возможности настроек) сделали тип SERIAL с функционалом, который я уже описывал, значит это кому-нибудь нужно.
> "Microsoft Sql Server 2000 Справочник администратора" стр.
> 519
Жаль, но данная книга у меня сейчас дома, так что прочесть сейчас не смогу. Подожду до завтра. Но вроде как совсем недавно я ее всю прочитал и ответы на заданные мной здесь вопросы не нашел. Интересно, что-же там на 519стр.
paul_k (2004-05-24 13:09:00) [42]
> Это вроде как уже понятно. А вот есть ли мнение по поводу
>
> > den_777 (24.05.04 11:43) [14]
перепечатывать лень
"Microsoft Sql Server 2000 Справочник администратора" стр. 519
или BOL
Johnmen (2004-05-24 13:05:00) [43]>den_777
Всё-таки неясно, зачем самому вставлять ID ? Ведь это фактически суррогатный ключ, и в величине его значения никакого смысла нет.
Да и поведение его (Identity), естественно, "учитывает" многопользовательскую работу...
den_777 (2004-05-24 13:04:00) [44]
> следовательно - либо значение по умолчанию либо через ХП
> организовывать добавление.
Это вроде как уже понятно. А вот есть ли мнение по поводу
> den_777 (24.05.04 11:43) [14]
paul_k (2004-05-24 12:53:00) [45]Виноват...
Если верить вумной книжке
"Если какой-либо оператор пытается выполнить операцию, которая нарушает какое -либо ограничение по таблице, или являеттся причиной какой-то другой ошибки, то связанный с ним триггер не будет активизирован"
то есть проверять непустые поля надо раньше.
следовательно - либо значение по умолчанию либо через ХП организовывать добавление.
den_777 (2004-05-24 12:25:00) [46]
> paul_k © (24.05.04 12:11) [15]
update insertedMSSQL в триггере писать не разрешает
"error286: The logical tables INSERTED and DELETED cannot be updated"
paul_k (2004-05-24 12:11:00) [47]
>
> А как быть с тем, что в случае insert into tbl1(cname) values("myname")
> SERVER ругнется, что ID должно быть обязательно задано.
>
напиши то, что я советовал, в триггере и проверь... работы на 5 минут
создать таблицу с 2-мя полями и в триггере update inserted написать :)
den_777 (2004-05-24 11:43:00) [48]
> ega23 © (24.05.04 11:35) [13]
Спасибо, я тоже думаю что это самый подходящий вариант.
Но вот вопрос про триггеры BEFORE INSERT остается открытым. Ведь в любой базе DEFAULT и CHECK constraints реализовываются с помощью системных триггеров перед вставкой и обновлением. И разработчику баз данных тоже предоставлено право пользоваться возможностью изменения данных в триггере до вставки и обновлений. Если в MSSQL такой возможности нет, то просто любопытно, а как же у них реализованы DEFAULT и CHECK constraints.
ega23 (2004-05-24 11:35:00) [49]Тогда 3-й вариант - построить самому функцию вычисляющую новый ID и в свойствах поля указать её, как значение по умолчанию. ИМХО, разумнее всего будет. Я-то с точки зрения 7.0 советовал...
den_777 (2004-05-24 11:31:00) [50]
> ega23 © (24.05.04 11:21) [11]
> MS SQL-то какой?
2000
ega23 (2004-05-24 11:21:00) [51]MS SQL-то какой?
den_777 (2004-05-24 11:18:00) [52]
> 1 -й вариант почитать про Identyty
надеюсь все что можно про Identyty я уже прочитал
> 2-й вариант - в написать свою процедуру - генерацию уникального
> ID, вызывать её в тригере
> Exec ap_get_id @new_id out
> update inserted set id = @new_id
> если вставка не по 1-й записи то делать это в курсоре по
> inserted
А как быть с тем, что в случае insert into tbl1(cname) values("myname") SERVER ругнется, что ID должно быть обязательно задано.
> 3-й вариант - построить самому функцию вычисляющую новый
> ID и в свойствах поля указать её, как значение по умолчанию.
>
Спасибо за вариант, стоит разобраться с этой возможностью
> 4-й вариант - использовать для ID тип uniqueidentifier (GUID)
> и функцию NewId()
> Если подумать и поковырятся в хелпе можно найти ещё N способов
> организовать уникальный ID.
Не подходит, нужен ID с типом INTEGER
den_777 (2004-05-24 11:11:00) [53]
> ega23 © (24.05.04 10:39) [5]
спасибо, но мы отсекаем возможность вставки в таблицу без ХП, так как в случае insert into tbl1(cname) values("myname")
SERVER ругнется, что ID должно быть обязательно задано.
Ну а насчет Identity в
> ega23 © (24.05.04 10:48) [7]
все написано.
Делать Set Identity_Insert ON/OFF при многопользовательской работе я думаю небезопасно.Одна транзакция будет действительно вставлять необходимые данные в ID, а вот что произойдет с другими транзакциями которые ожидали автоматической подстановки ID остается только догадываться.
> Хотя задачка сама по себе странновата...
Действительно задачка странная, но иногда это необходимо. Например для первоначального заполнения справочника с предопределенными ID и возможностью последующего дополнения и модификации его пользователем. Может быть пример не очень, но суть остается, иногда хочется иметь такую возможность.
Вопрос скорее всего адресован к тем, кто достаточно долго поработал с IB,FB и потом переходил на MSSQL. Какие стандартные замены привычной работе с генераторами и триггерами BEFORE INSERT нашел для себя этот человек в MSSQL.
paul_k (2004-05-24 10:54:00) [54]1 -й вариант почитать про Identyty
2-й вариант - в написать свою процедуру - генерацию уникального ID, вызывать её в тригере
Exec ap_get_id @new_id out
update inserted set id = @new_id
если вставка не по 1-й записи то делать это в курсоре по inserted
3-й вариант - построить самому функцию вычисляющую новый ID и в свойствах поля указать её, как значение по умолчанию.
4-й вариант - использовать для ID тип uniqueidentifier (GUID) и функцию NewId()
Если подумать и поковырятся в хелпе можно найти ещё N способов организовать уникальный ID.
ega23 (2004-05-24 10:48:00) [55]А просто объявить поле Identity ?
Он хочет иметь возможность сам в него значения вставлять. Вопрос стоит в том, как часто он сам значения будет вставлять. Если операция редкая, то делать столбец как Identity и потом Set Identity_Insert ON/OFF ставить. Если частая, то IDENTITY очень неудобно будет.
Хотя задачка сама по себе странновата...
Johnmen (2004-05-24 10:42:00) [56]>den_777
А просто объявить поле Identity ?
:)
ega23 (2004-05-24 10:39:00) [57]IF NEW.ID IS NULL THEN NEW.ID=54677
Причем поле ID NOT NULL.
Не слышал я в MS SQL про такую конструкцию. Реализовать - можно, повторюсь, что с помощью ХП:
Print 'S_PersEdit- модификация таблицы персонала'
go
if exists (select * from sysobjects where id = object_id(N'[S_PersEdit]') and OBJECTPROPERTY(id, N'IsProcedure') = 1)
drop procedure [S_PersEdit]
GO
CREATE PROCEDURE S_PersEdit
--режим работы процедуры
@mode int=-1,--1-add,2-edit,3-del,30 - проверка на удаление 4-New PinCod
--11 -Generatior ADD, 12 --generator -CHK, 13 --generator -DEL
--Сведения об персоне
@persId int=-1 output, -- output для Генератора
@PersNam1 varchar(32)='',
@PersNam2 varchar(32)='',
@PersNam3 varchar(32)='',
As
declare @result int,
@cod int
if @mode=1
begin
if @PersID=-1 Select @PersID=Max(PersID)+1 from Persons
Insert into Persons (PersID, PersNam1, Persnam2, ....)
Values (@PersID, @PersNam1, @Persnam2, ... )
....
-- Далее можно сразу же протоколирование произвести..
.....
Return(@Result)
end
den_777 (2004-05-24 10:30:00) [58]
> Неправильно тебе кажется. Триггер - последний рубеж перед
> операцией
Все может быть, только уточни как реализовать в MSSQL аналог
IF NEW.ID IS NULL THEN NEW.ID=54677
Причем поле ID NOT NULL.
содержимое триггера смысловой нагрузки не несет, только пример.
> Только так и делается. Работать с таблицами напрямую - вредно.
> Только черех ХП. Более того, даже Select'ы через ХП.
Извини, не принимай за грубость, но это только твое мнение. У меня есть свой взгляд на работу с базами данных и опыт написания и поддержки программ взаимодействующих с разработанными мною большими и очень большими базами. Но все это не относится к теме вопроса, давай не будем дальше развивать эту тему.
ega23 (2004-05-24 10:13:00) [59]Мне кажется, что там только триггеры после вставки, обновления и удаления.
Неправильно тебе кажется. Триггер - последний рубеж перед операцией.
да и писать на каждую таблицу хранимую процедуру только для того чтобы провести обычную вставку это как-то не хорошо
Только так и делается. Работать с таблицами напрямую - вредно. Только черех ХП. Более того, даже Select'ы через ХП.
den_777 (2004-05-24 10:04:00) [60]
> Точно так же, как и в других СУБД.
А разве в MSSQL есть триггер перед вставкой. Мне кажется, что там только триггеры после вставки, обновления и удаления. А перед вставкой и после вставки - это не одно и тоже.
А по поводу ID, может есть другие варианты. Насчет процедуры - это слишком сильное орграничение себе делать.Все таки insert into намного проще, да и писать на каждую таблицу хранимую процедуру только для того чтобы провести обычную вставку это как-то не хорошо.