[mssql] вопрос про delete ...
> mysql> DELETE FROM tbl_name WHERE 1>0;
> This is much slower than TRUNCATE tbl_name, because it deletes rows one at a time.
---
...Я работаю...
При чем здесь mysql?
в общем случае без триггера не обойтись. А так если по одной удалять - завести какой нить PK и удалять по одному используя этот PK
Всю жизнь думал, что если написать delete from table where id>5 то триггер исполнится для каждой удаленной строчки по отдельности, разве нет?
пишет ошибку
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.
нада то ли триггер переделать, либо какую нить процедуру замутить, чтобы построчно удаляла, либо хз
По моему не там проблему ищешь. Покажи что ли триггер и delete полностью...
таблица :
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
Можно переписать триггер с update на replace будет нормально. Ну и естественно вместо этих переменных временные таблицы надо будет сделать, а лучше вообще всё подставить и не парицца. SQL это вам не паскаль чтобы так писать А как тут update-ом разрулить я не понимаю.
Попробуй триггер AFTER DELETE. Вроде как он сначала все удалит, а потом для удаленных записей запустится
Используй 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"
тот триггер я писал через день после того как вообще узнал, что бывают триггеры :-
А он в mysql-е есть?
более читабельны в виде "select @bod_id = bod_id from deleted"
зато вместо той ошибки которую тут обсуждаем, получили бы код, который что называется silently wrong...
зато вместо той ошибки которую тут обсуждаем, получили бы код, который что называется silently wrong...Это почему? Вообще, во всех доках по MS SQL именно так и делают.
А насчет MySQL ничего сказать не могу - слишком мало с ним общался
select @bod_id = bod_id from deletedвыдает ошибку если в deleted >1 строки?
нет
select @bod_id = (select bod_id from deleted)
выдает. это и называется silently wrong - делает не то что задумано и молчит...
На самом деле, думал, что выдаст ошибку... Это ж с умом надо делать. И не важно, DELETED там или просто табличка. Я сделал замечание по оформлению, не больше. Вообще, если есть "типа ключ", но на самом деле ключа нет, я пишу top 1
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
Оставить комментарий
Alena_08_11
в общем на таблицу повешен триггер (стрёмненький по исполнению) for delete, который при удалении записи берёт значение какого то поля из ... from Deleted, и уменьшает значение другого поля в другой таблице на эту величину.то есть таблица не позволяет удалять за раз больше одной записи.
( то есть например delete from table where id>5 - не прокатывает)
можно ли как нить простым путём осуществить такое удаление, так чтобы запрос был типа таким же, а само удаление производилось построчно.
(без написания процедуры, которая по очереди бы удаляла, без переделки триггера, и без генерации в приложении кучи удалятельных запросов )