CREATE TRIGGER [dbo].[C1_Deletions] ON [dbo].[C1] INSTEAD OF DELETE AS
SET NOCOUNT ON
IF EXISTS ( SELECT 'True' FROM deleted JOIN C1 ON deleted.ACCOUNTNO = C1.ACCOUNTNO )
BEGIN
INSERT INTO [GDeletions].[dbo].[C1] SELECT * FROM deleted
DELETE C1 FROM C1 INNER JOIN DELETED ON C1.ACCOUNTNO = DELETED.ACCOUNTNO
END
因此,这是我尝试使用的触发器,当我通过accountno删除它时效果很好,但是当我需要通过recid(另一列)删除时,我无法使用。
如果我将INSTEAD OF更改为AFTER,我会收到有关ntext的错误,不允许使用图像列。有没有解决这个问题的方法?我不能指定删除字符串,程序本身就是我只需要触发器来获取正在删除的数据。
我遇到的另一个更大的问题是另一个存储历史记录的表,它使用与c1表匹配的accountno存储它,但是还有recid,它对每个条目都是唯一的。如果我去删除C1条目,它会使用accountno从历史记录中删除所有条目,但是如果我删除单个历史记录条目,则它将被recid删除。
答案 0 :(得分:4)
您无法从INSERTED或DELETED访问TEXT,NTEXT或IMAGE字段。但是,您可以通过与INSERTED连接从基表访问它们。这仅适用于INSERT和UPDATE,因为在DELETE中,基行不再存在。
要实现所需,在另一个触发器中,将主键和TEXT,NTEXT和IMAGE列复制到边表。
例如
create table C1(
accountNo int identity primary key,
someColumn nvarchar(10),
someNtext ntext
)
create table C1_side(
accountNo int primary key,
someNtext ntext
)
create trigger trgC1_IU on C1 AFTER INSERT, UPDATE
as
BEGIN
-- Ensure side row exists
insert C1_side(accountNo, someNtext)
select accountNo from INSERTEd
where not exists (select 1 from C1_side where C1_side.accountNo = inserted.accountNo)
-- Copy NTEXT value to side row
update C1_side
set someNtext = c1.someNtext
from C1_side inner join C1 on C1_side.accountNo = C1.accountNo
inner join INSERTED on INSERTED.accountNo = C1.accountNo
-- Could improve by checking if the column was updated for efficiency
END
现在,在DELETE触发器中,您可以将DELETED连接到C1_side以读取ntext列的先前值。请注意,对于已存在于C1中的行,您必须填充边表的初始值。
答案 1 :(得分:3)
停止使用ntext和image:they are deprecated。请改用nvarchar(max)和varbinary(max)。与不推荐使用的数据类型不同,它们的行为类似于普通数据类型。
答案 2 :(得分:0)
我发现,即使您一次删除多行,在查询执行期间每行仍然会被放入DELETED临时表中,因此我的触发器会遍历每条记录并在recid上匹配(这对每个行都是唯一的)行)并从那里删除/移动。