2012-05-17 53 views
2

我有2个表格称为患者和诊断。如下插入SQL触发器,删除2个表格

 
Patient  Diagnosis 
---------  ------------ 
ID (PK)  ID (PK) 
Name   PatientID (FK: Reference to Patient => ID) 
Status 
******   ***** 
----------  ----------- 

在此,患者状态可以是[注册诊断OnCourse]

期间,

  • 新患者插入,患者状态将是注册
  • 新诊断I nsert,患者状态将诊断

现在, 诊断删除,我需要检查,如果患者在诊断表至少一个诊断条目,那么患者状态会诊断否则注册

所以,如何做到单触发所有这些条件?

请帮帮我。

+0

这可能只是我,但我不是你问清楚。请你可以列出*(作为你的问题的编辑)*你想要触发器做什么? * [我认为你一定想要3),也许2),但也可能是1)。从你的问题来看,这不是很清楚。] *'1).'当插入新的病人记录时,强制登记状态? '2).'当插入一个新的诊断时,状态将被诊断? '3).'删除*最后*诊断记录时,强制状态为注册? – MatBailie

回答

5

触发器根据诊断表上的INSERT和DELETE更新Patient.Status。

CREATE TRIGGER dbo.Diagnosis_TrgInsDel 
    ON dbo.Diagnosis 
    AFTER DELETE, INSERT 
AS 
BEGIN 

    -- SET NOCOUNT ON added to prevent extra result sets from 
    -- interfering with SELECT statements. 
    SET NOCOUNT ON; 


    -- Change the Status to 'Registered' after the last 
    -- Diagnosis record is deleted 
    -------------------------------------------------------------------------------- 
    UPDATE 
     Patient 
    SET 
     [Status] = 'Registered' 
    FROM 
     Patient 
    INNER JOIN 
     Deleted 
     ON Deleted.PatientID = Patient.ID 
    WHERE 
     NOT EXISTS (SELECT * FROM Diagnosis WHERE PatientID = Deleted.PatientID) 


    -- Change the Status to 'Diagnosed' after an Insert and the 
    -- current Status is 'Registered' 
    -------------------------------------------------------------------------------- 
    UPDATE 
     Patient 
    SET 
     [Status] = 'Diagnosed' 
    FROM 
     Patient 
    INNER JOIN 
     Inserted 
     ON Inserted.PatientID = Patient.ID 
    WHERE 
     Patient.[Status] = 'Registered' 

END 

我实际上不会将此作为两个触发器。一个用于AFTER DELETE,另一个用于AFTER INSERT。这意味着当存在INSERT时,DELETE代码不会运行,反之亦然。但是上面的代码确实可以正常工作。

EDIT

AS通过尼古拉斑点;如果插入或更新多个诊断,在相同的操作中,对于同一患者,则这可能会多次更新单个患者记录。这些修改应该解决...

UPDATE 
     Patient 
    SET 
     [Status] = 'Registered' 
    WHERE 
     NOT EXISTS (SELECT * FROM Diagnosis WHERE PatientID = Patient.ID) 
     AND EXISTS (SELECT * FROM Deleted WHERE PatientID = Patient.ID) 

而且......

UPDATE 
     Patient 
    SET 
     [Status] = 'Diagnosed' 
    WHERE 
      Patient.[Status] = 'Registered' 
     AND EXISTS (SELECT * FROM Inserted WHERE PatientID = Patient.ID) 
2

在第一部分,你可以简单地添加默认约束:

alter table patient add constraint df_status default 'Registered' for status 

如果这是不够的,因为你的前端是不能在插入省略状态或设定值设为默认,你可以创建一个触发:

create trigger PatientInsertTrigger on patient 
after insert 
as 
    -- trigger should not alter @@rowcount 
    set nocount on 

    update patient 
     set status = 'Registered' 
    from Patient 
    -- Inserted is a pseudotable holding newly inserted rows 
    -- This is how we know what records to update 
    inner join Inserted 
     on Patient.ID = Inserted.ID 

当记录添加到诊断或从诊断中删除时,应根据诊断中匹配记录的数量更新患者状态。幸运的是,在调用触发器的时候,记录已经在表中了,所以在这两种情况下都需要count()。

create trigger DiagnosisTrigger on diagnosis 
after insert, delete 
as 
    set nocount on 

    update patient 
     set status = case when d.NumberOfDiagnosis <> 0 
         then 'Diagnosed' 
         else 'Registered' 
        end 
    from Patient 
    inner join 
    (
     select PatientID, count(*) NumberOfDiagnosis 
     from Diagnosis 
     -- Get all patients with added or removed diagnosis 
     where PatientID in (select PatientID 
          from Inserted 
          union 
          select PatientID 
          -- Pseudotable holding removed records 
          from Deleted) 
     group by PatientID 
    ) d 
     on Patient.ID = d.PatientID 

状态应该是StatusID,但是您没有提到适当的id号。

+0

尽管没有*错误*这确实有轻微的低效率 - 即使不需要它也会更新状态。 *(在第二次插入时,您将状态从“诊断”更改为“诊断”,删除后还有另一条诊断记录。)*另外,通过使用COUNT(*)而不是使用'随着诊断次数的增加,性能会下降。 * [在这种特殊情况下,这些可能只是次要的,但它们值得注意的是OP的学习目的,而且在大型数据库中非常重要。] – MatBailie

+0

@Dems感谢您的洞察力。当我__trying__保持简单时,__did__很简单。我有一个问题 - 在“插入...选择”的情况下,您的代码可能会使用相同的值多次更新同一患者;而且,将更新过滤到相同的值是否真的很有效?例如,status <>'x'是'更新病人设置状态='x',其中patientid = 123和状态<>'x''或混乱是否有改善?我知道这只是一个记录,但我有一些排名更新,并不确定是否要过滤或不更新相同的值。 –

+0

你是对的,如果同一位患者有多个诊断插入/删除,那么我的答案会多次更新同一患者记录。我的错误,和好的地方!至于'status'>'x'',那么这*是一个改进。无论如何,该记录正在被读入内存,并且此cpu开销很低;当设置状态不必要时,远远低于不必要的写入。 *(虽然人们可以正确地认为这取决于不必要的写入实际发生的频率。)* – MatBailie