【问题标题】:Find the original record and change only that not the inserted one找到原始记录并仅更改不插入的记录
【发布时间】:2011-12-11 20:35:39
【问题描述】:

我已经尝试过了,但到目前为止还没有成功。由于我的查询知识有限,我想我最好在这里发布。

我有以下结构的学生表

create table students(
id int not null primary key identity,
sname varchar(25),
status varchar(25),
renew varchar(15),
enrollment datetime,
)

我有一些学生有一个 ID、学生姓名(sname)、状态(“活跃”或“不活跃”)、续订(“否”表示新学生,“是”表示续签学生)和注册日期.

insert into students values('jay','active','no','2010-01-01')
insert into students values('Phil','active','no','2010-01-01')
insert into students values('Cru','active','no','2010-01-01')
insert into students values('slow','active','no','2010-01-01')
insert into students values('true','active','no','2010-01-01')
insert into students values('false','active','no','2010-01-01')

现在我有一个 INSERT 触发器,它假设在更新学生时停用一个老学生。因此,如果我插入以下更新设置为“是”的内容,它应该使已经存在的记录“无效”。

insert into students values('false','active','yes','2011-01-01')

我编写了这个 INSERT 触发器,它可以工作,但它使新插入的旧记录和新插入记录都处于非活动状态。我只想停用原始记录。也不是只有注册日期和新字段不同,原始记录和插入记录之间的其余部分相同。如何解决这个问题?这是我的触发器

set ANSI_NULLS ON
set QUOTED_IDENTIFIER ON
GO
CREATE TRIGGER [dbo].[tr_renew_student]
ON [dbo].students
-- WITH ENCRYPTION
FOR INSERT
-- WITH APPEND
-- NOT FOR REPLICATION
AS
-- insert sql here
if exists(select * from inserted where Renew = 'yes')
BEGIN

UPDATE students 
    SET status = 'Inactive'

    FROM Inserted i
        INNER JOIN students T2
            ON i.sname = T2.sname

END

请注意,这与我的问题非常接近。谢谢

【问题讨论】:

    标签: sql sql-server-2005 join triggers


    【解决方案1】:

    你看过@@identity 吗?几年前,我处理过类似的事情并使用@@identity 来获取最后创建的身份值;基本上是获取最新的身份值,然后设置所有符合条件的记录,除了通过@@identity 返回的 ID 记录。

    在此处了解身份值获取器: http://blog.sqlauthority.com/2007/03/25/sql-server-identity-vs-scope_identity-vs-ident_current-retrieve-last-inserted-identity-of-record/

    添加:您对inserted 表的看法是正确的。如果您不想/不能使用插入的表,您的触发器可能看起来像这样。

    SELECT @@identity //  <- this gets the last identity value inserted.
    
    UPDATE students
    SET status = 'Inactive'
    WHERE students.name = (SELECT name FROM students WHERE id = @@identity)
      AND id <> @@identity
    

    注意:从内存中写入,未经测试。

    【讨论】:

    • 我认为最后插入的记录没有提供解决方案。 Inserted table 包含我需要加入原始表并找到我需要修改的实际记录的所有内容。
    • 我通常不使用触发器,所以 Inserted 早些时候让我忘记了。有关我正在考虑的方法的更多详细信息,请参阅我的更新答案。
    【解决方案2】:

    将您的更新更改为:

    UPDATE students 
        SET status = 'Inactive'
    
        FROM Inserted i
            INNER JOIN students T2
                ON i.sname = T2.sname
                AND i.id <> t2.id
    

    这会检查您正在更新的行不是新插入的行。

    【讨论】:

    • 问题:它将如何确保它会更新原始记录,而不是插入记录?顺便说一句,它成功了
    • @Thecrocodilehunter - 因为您要确保插入时自动生成的 Id 与新行的 id 不匹配。
    • 这在我的测试示例中工作正常,但在我的实际代码中,它可以反过来工作。该行在 INSERTED 表中更新,而不是需要更新的行。
    • 然后显示您的实际代码。如果您不提供准确的示例,我们应该如何帮助您?
    • 当然这是一个项目,您的解决方案在此示例中有效,但在实际代码中无效。它具有与此处相同的 ID 字段。我的原始问题是:它不会更新插入记录的逻辑是什么?因为似乎没有一个坚定的逻辑。它可以去任何一种方式?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-24
    • 2014-12-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多