[mssql] вопрос про delete ...

Alena_08_11

в общем на таблицу повешен триггер (стрёмненький по исполнению) for delete, который при удалении записи берёт значение какого то поля из ... from Deleted, и уменьшает значение другого поля в другой таблице на эту величину.
то есть таблица не позволяет удалять за раз больше одной записи.
( то есть например delete from table where id>5 - не прокатывает)
можно ли как нить простым путём осуществить такое удаление, так чтобы запрос был типа таким же, а само удаление производилось построчно.
(без написания процедуры, которая по очереди бы удаляла, без переделки триггера, и без генерации в приложении кучи удалятельных запросов )

kruzer25

Где-то что-то не так.
> mysql> DELETE FROM tbl_name WHERE 1>0;
> This is much slower than TRUNCATE tbl_name, because it deletes rows one at a time.
---
...Я работаю...

qsk78

При чем здесь mysql?

anton7805

в общем случае без триггера не обойтись. А так если по одной удалять - завести какой нить PK и удалять по одному используя этот PK

rosali

Всю жизнь думал, что если написать delete from table where id>5 то триггер исполнится для каждой удаленной строчки по отдельности, разве нет?

Alena_08_11

нет
пишет ошибку

Server: Msg 512, Level 16, State 1, Procedure table_trigg_del, Line 10
Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >=
or when the subquery is used as an expression.
The statement has been terminated.

нада то ли триггер переделать, либо какую нить процедуру замутить, чтобы построчно удаляла, либо хз

rosali

По моему не там проблему ищешь. Покажи что ли триггер и delete полностью...

Alena_08_11

ok

таблица :
CREATE TABLE [sfSupp_dtl] (
[id] [int] IDENTITY (1, 1) NOT NULL ,
[sfs_id] [int] NOT NULL ,
[ord_id] [int] NOT NULL ,
[bod_id] [int] NOT NULL ,
[pr_id] [int] NOT NULL ,
[amount] [decimal](9, 3) NOT NULL ,
[price] [decimal](18, 2) NOT NULL ,
[summ_nds] [decimal](18, 2) NOT NULL ,
PRIMARY KEY CLUSTERED
(
[id]
) ON [PRIMARY]
) ON [PRIMARY]
GO
триггер :
SET QUOTED_IDENTIFIER OFF
GO
SET ANSI_NULLS ON
GO
create trigger sfSupp_dtl_del on sfsupp_dtl for delete as
declare
@bod_id int,
@old_sfstatus_amount dec(9,3
@sfstatus_amount_toRemove dec(9,3
@sfs_id int,
@old_sfs_summ decimal(18,2
@summ_toRemove decimal(18,2)
select
@bod_id = (select bod_id from deleted
@old_sfstatus_amount = (select sfs_amount from sfstatus where bod_id = (select bod_id from deleted
@sfstatus_amount_toRemove = (select amount from deleted
@sfs_id = (select sfs_id from deleted
@old_sfs_summ = (select summ from sfSupp where id = (select sfs_id from deleted
@summ_toRemove = (select CONVERT(decimal(18,2price*amount) from deleted)
update sfSupp set summ = CONVERT(decimal(18,old_sfs_summ - @summ_toRemove summ_nds =
CONVERT(decimal(18,old_sfs_summ - @summ_toRemove)*1.18) where id = @sfs_id
update sfstatus set sfs_amount = @old_sfstatus_amount - @sfstatus_amount_toRemove where bod_id = @bod_id
GO
SET QUOTED_IDENTIFIER OFF
GO
SET ANSI_NULLS ON
GO

Если под условие в delete попадает больше 1 записи (например delete from sfsupp_dtl where ord_id = 123 при условии что ord_id = 123 больше чем в одной строке) вылезает вышеуказанная ошибка
ps. по поводу триггера прошу особо не стебацца - работает да и пох ... только удалять много не позволяет :-D

rosali

Ну вобщем да, все логично что не работает
Можно переписать триггер с update на replace будет нормально. Ну и естественно вместо этих переменных временные таблицы надо будет сделать, а лучше вообще всё подставить и не парицца. SQL это вам не паскаль чтобы так писать А как тут update-ом разрулить я не понимаю.

hprt

Попробуй триггер AFTER DELETE. Вроде как он сначала все удалит, а потом для удаленных записей запустится

hprt

Блин, из-за этого пенартура суть вопроса при беглом прочтении понял неправильно - думал, проблема в скорости.
Используй UPDATE FROM:

UPDATE table1
SET
field1 = table2.field1
, field2 = field2 + table2.field2
FROM
table2
WHERE
table1.id = table2.id

Еще: такие конструкции "select @bod_id = (select bod_id from deleted)" более читабельны в виде "select @bod_id = bod_id from deleted"

Alena_08_11

на досуге подумаю :-D
тот триггер я писал через день после того как вообще узнал, что бывают триггеры :-

rosali

О! ты мне глаза открым... update from... пойду думать
А он в mysql-е есть?

rosali

более читабельны в виде "select @bod_id = bod_id from deleted"

зато вместо той ошибки которую тут обсуждаем, получили бы код, который что называется silently wrong...

hprt

зато вместо той ошибки которую тут обсуждаем, получили бы код, который что называется silently wrong...
Это почему? Вообще, во всех доках по MS SQL именно так и делают.
А насчет MySQL ничего сказать не могу - слишком мало с ним общался

rosali

что
select @bod_id = bod_id from deleted
выдает ошибку если в deleted >1 строки?

bastii

нет

rosali

ну? а
select @bod_id = (select bod_id from deleted)

выдает. это и называется silently wrong - делает не то что задумано и молчит...

hprt

На самом деле, думал, что выдаст ошибку... Это ж с умом надо делать. И не важно, DELETED там или просто табличка. Я сделал замечание по оформлению, не больше. Вообще, если есть "типа ключ", но на самом деле ключа нет, я пишу top 1

madik_zxz

select
@bod_id = (select bod_id from deleted
@old_sfstatus_amount = (select sfs_amount from sfstatus where bod_id = (select bod_id from deleted
@sfstatus_amount_toRemove = (select amount from deleted
@sfs_id = (select sfs_id from deleted
@old_sfs_summ = (select summ from sfSupp where id = (select sfs_id from deleted
@summ_toRemove = (select CONVERT(decimal(18,2price*amount) from deleted)
update sfSupp set summ = CONVERT(decimal(18,old_sfs_summ - @summ_toRemove summ_nds =
CONVERT(decimal(18,old_sfs_summ - @summ_toRemove)*1.18) where id = @sfs_id
update sfstatus set sfs_amount = @old_sfstatus_amount - @sfstatus_amount_toRemove where bod_id = @bod_id
Чтобы триггер корректно обрабатывал удаление нескольких записей этот блок необходимо заключить в цикл, объявить курсор и фетчить данные на каждой итерации.
Оставить комментарий
Имя или ник:
Комментарий: