Страница 1 из 2
Обновление вместо вставки.
Добавлено: 03 фев 2007, 16:12
pum
Доброго времени суток всем!
Если кто-нибудь знает, подскажите, пожалуйста.
При вставке новой записи в таблицу, я проверяю наличие в этой таблице необходимой записи. Если нет, то просто добавляю. Если есть, то обновляю некоторые поля этой записи.
Собственно, вопрос: Как в триггере BeforeInsert остановить добавление
новой записи, не отменяя сделанные изменения и не используя exception.
Добавлено: 04 фев 2007, 23:14
kdv
рекомендую воспользоваться поиском, т.к. эта тема уже обсуждалась.
В общем случае вставку превратить в обновление в триггере на вставку нельзя. То есть, нужно пользоваться процедурой. Например как тут:
www.ibase.ru/devinfo/testiu.htm
Добавлено: 13 фев 2007, 16:53
pum
Спасибо, Дмитрий.
Так и делал (по первому варианту), но решил спросить, может есть способ обойтись триггером. Нету.
И еще вопрос. Как получить идентификатор записи, на котой произошла ошибка (применительно к третьему варианту)?
Добавлено: 13 фев 2007, 17:19
kdv
может есть способ обойтись триггером. Нету.
ну КАК тут можно обойтись триггером, объясните мне пожалуйста, а?
Честное слово - Вы не представляете, как триггеры работают, и уже пытаетесь туда какой-то изврат запихнуть.
Как получить идентификатор записи, на котой произошла ошибка
обработкой when. А Вы прямо так процедурой и шпарите? Статья ведь просто пример, плюс один из способов импорта - через external table.
там же и пример when есть.
или я не понимаю, о чем Вы спрашиваете. Можно поподробнее?
Добавлено: 13 фев 2007, 18:03
WildSery
kdv писал(а):ну КАК тут можно обойтись триггером, объясните мне пожалуйста, а?
Если ССЗБ, то ведущие проктологи рекомендуют так:
Код: Выделить всё
CREATE TRIGGER ... BEFORE INSERT
as begin
if (exists (select 1 from Table1 a1 where a1.id = new.id)) then begin
update Table1 a
set a.val1 = new.val1,
a.val2 = new.val2,
...
where a.id = new.id;
new.id = -1;
end
end
CREATE TRIGGER ... AFTER INSERT
as begin
if (new.id < 0) then
delete from Table1 a where a.id = new.id;
end
PS: Автор, это чиста теория, так делать
не надо!
Добавлено: 13 фев 2007, 18:22
Merlin
А в глаз?

За смущение неокрепших умов? Это даже не теория, а искусственный этюд, предполагающий невозможность типа одноврменной вставки двух дубликатов даже с разными значениями ключа.
Добавлено: 13 фев 2007, 19:04
WildSery
Merlin писал(а):невозможность типа одноврменной вставки двух дубликатов даже с разными значениями ключа.

чего-то я не понял этой фразы.
Как это "дубликаты с разными id" ? Какие ж они дубликаты?
Добавлено: 13 фев 2007, 20:17
Merlin
Пардон муа, великим руский языка (С). Две пары дубликатов. Обоих будешь замещать -1. Компрене ву? (C)
Добавлено: 13 фев 2007, 20:47
WildSery
Думаешь, загнётся на конкурентной вставке? Хм.
Ну тогда "-1" заменяем на "-new.id".
Ы?
Добавлено: 13 фев 2007, 20:50
Merlin
Тады в r_c загнётся на (exists (select 1 from Table1 a1 where a1.id = new.id)) ежели оно там есть, но ещё не закоммичено, или работаем в снапшоте и закоммичено после нашего старта.
Добавлено: 13 фев 2007, 21:05
WildSery
Решение я придумывал для одной вставляющей транзакции

Щас прикину, можно ли как обойти...
Добавлено: 25 апр 2007, 14:28
mik83only
У меня похожая проблема, но только не нужно делать update, а просто проверять перед insert'ом, есть ли уже такие записи.
Извиняюсь за свою тупость, но после прочтения статьи не совсем понял - нужно все инсерты делать через хранимую процедуру и в ней уже проверять ?
Добавлено: 25 апр 2007, 15:13
WildSery
mik83only писал(а):а просто проверять перед insert'ом, есть ли уже такие записи.
И что делать в случае, если есть?
Добавлено: 25 апр 2007, 15:55
mik83only
WildSery писал(а):mik83only писал(а):а просто проверять перед insert'ом, есть ли уже такие записи.
И что делать в случае, если есть?
Насколько я понимаю - не вставлять, то есть ничего не делать.
Добавлено: 25 апр 2007, 16:03
WildSery
Ну так бери первую или вторую процедуру, оставляй только ветку "INSERT" и будет щастье.
Можно конечно и с клиента пихать всё INSERT'ом, что уже есть отшибёт по PK, в клиенте перехватываешь.
Добавлено: 25 апр 2007, 16:10
mik83only
Так у меня проверка по трем полям сразу и они не PK.
Просто таких таблиц в которых нужно проверять на уникальность - несколько и я подумал, что писать для каждой процедуру на добавление - не совсем правильно и можно сделать как-то проще(со стороны клиента через запрос). Я заблуждаюсь ?
Добавлено: 25 апр 2007, 18:17
WildSery
Посуди сам - с клиента ты делаешь два запроса, сперва проверка существования, затем вставка или ничего.
А в случае процедуры - один запрос, на вызов процедуры, дальше всё выполняется внутри сервера.
Добавлено: 25 апр 2007, 22:55
pum
Привет еще раз.
Написал, думал, что "светлые головы" что нибудь посоветуют по делу. Напрасно надеялся. Только посмеялись. ':twisted:'
Свои проблемы решил так. В таблице есть некое составное уникальное поле. Приложение (один из видов клиентов) постоянно осуществляет вставку (это о нем речь), остальные только читают, скрипт при перед backup удаляет лишнее. Вставка осуществляется только процедурой. При возникновении ошибки WHEN ANY DO (SQLCODE 803), т.е. попытка вставить новую уникальную запись, провожу поиск идентификатора записи, на которой встали, и обновляю ее, меняя некоторые значения не входящие в составное уникальное поле (ну, мне так надо).
А хотел я от Вас узнать, Нельзя ли, НЕ ДЕЛАЯ ДОПОЛНИТЕЛЬНОГО SELECT, в момент, когда процедура споткнулась на INSERT, узнать номер, ID или еще как выяснить идентификатор этой записи, которая содержит набор таких же значений составного поля, что и в запросе INSERT. ':?'
С уважением.
Добавлено: 26 апр 2007, 01:46
kdv
Написал, думал, что "светлые головы" что нибудь посоветуют по делу. Напрасно надеялся. Только посмеялись.
тупой вопрос - тупой ответ, извини за прямоту.
Нельзя ли, НЕ ДЕЛАЯ ДОПОЛНИТЕЛЬНОГО SELECT, в момент, когда процедура споткнулась на INSERT, узнать номер, ID или еще
см. цитату выше. В приведенной ссылке нормальный вариант когда сначала ИЩУТ запись, а потом по ее СУЩЕСТВОВАНИЮ или нет делают update или insert.
как выяснить идентификатор этой записи, которая содержит набор таких же значений составного поля, что и в запросе INSERT.
ты определись сначала, что у тебя является идентификатором записи. А потом подумай над тем, что ты спросил.
Если у тебя на таблице только ПК, то вопроса как такового нет. Если же есть еще и альтернативный ключ, то ты уж тогда как-нибудь сам разберись, чего ты пытаешься задублировать - или повторить значение ПК, или повторить значение альтернативного ключа.
В общем, с моделью данных разберись

Добавлено: 26 апр 2007, 14:05
mik83only
WildSery писал(а):Посуди сам - с клиента ты делаешь два запроса, сперва проверка существования, затем вставка или ничего.
А в случае процедуры - один запрос, на вызов процедуры, дальше всё выполняется внутри сервера.
Понятно, спасибо за консультацию
