编写复杂的触发器

发布于 2024-08-07 22:01:24 字数 693 浏览 7 评论 0原文

我正在使用 SQL Server 2000。我正在编写一个触发器,当字段 Applicant.AppStatusRowID

表 Applicant 链接到表 Location、表 Company & 时执行该触发器。表应用程序状态。

我的问题是在查询中创建联接。

当 Applicant.AppStatusRowID 更新时,我想从中获取值 Applicant.AppStatusRowID、Applicant.FirstName、Applicant.Lastname、Location.LocNumber、Location.LocationName、Company.CompanyCode、AppStatus.DisplayText

连接将为:

Select * from Applicant A
Inner Join AppStatus ast on ast.RowID = a.AppStatusRowID
Inner Join Location l on l.RowID = a.LocationRowID
Inner Join Company c on c.RowID = l.CompanyRowID

这将被插入审核表中(字段为 ApplicantID、LastName、FirstName、日期、时间、公司、位置编号、位置名称、StatusDisposition、用户)

我的问题是内部联接的查询...

I am using SQL Server 2000. I am writing a trigger that is executed when a field Applicant.AppStatusRowID

Table Applicant is linked to table Location, table Company & table AppStatus.

My issue is creating the joins in my query.

When Applicant.AppStatusRowID is updated, I want to get the values from
Applicant.AppStatusRowID, Applicant.FirstName, Applicant.Lastname, Location.LocNumber, Location.LocationName, Company.CompanyCode, AppStatus.DisplayText

The joins would be :

Select * from Applicant A
Inner Join AppStatus ast on ast.RowID = a.AppStatusRowID
Inner Join Location l on l.RowID = a.LocationRowID
Inner Join Company c on c.RowID = l.CompanyRowID

This is to be inserted into an Audit table (fields are ApplicantID, LastName, FirstName, Date, Time, Company, Location Number, Location Name, StatusDisposition, User)

My issue is the query for the inner join...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

记忆里有你的影子 2024-08-14 22:01:24

首先让我们向您介绍仅在触发器中可用的插入和删除的伪表。 Inserted 有新值,delted 有旧值或被删除的记录。

您不想将所有记录插入到审计表中,而只将那些已插入的记录插入到审计表中。

因此,要插入到审计表中,您可能需要类似于触发器代码中的内容:

insert Myaudittable (<insert field list here>)
Select <insert field list here> from Inserted i
Inner Join AppStatus ast on ast.RowID = i.AppStatusRowID
Inner Join Location l on l.RowID = i.LocationRowID
Inner Join Company c on c.RowID = l.CompanyRowID 

我个人会添加用于旧值和新值的列,用于更改类型的列以及更改的日期和用户进行更改的列,但是我确信你有自己的要求要遵循。

建议您阅读在线书籍中有关触发器的内容,因为它们可能很难正确使用。

这是我经常使用的一种测试和调试触发器的方法。首先,我创建临时表名称 #delted 和 #inserted,它们具有我要放置触发器的表的结构。然后我编写代码来使用这些表而不是删除或插入的表。这样我就可以边走边看,并确保在将代码更改为触发器之前一切正常。下面的示例中添加了代码并稍作修改:

  Create table #inserted(Rowid int, lastname varchar(100), firstname varchar(100), appstatusRowid int)
  Insert #inserted
  select 1, 'Jones', 'Ed', 30
  union all
  select 2, 'Smith', 'Betty', 20

     Create table #deleted (Rowid int, lastname varchar(100), firstname varchar(100), appstatusRowid int)
  Insert #deleted
  select 1, 'Jones', 'Ed', 10
  union all
  select 2, 'Smith', 'Betty', 20

 --CREATE TRIGGER tri_UpdateAppDisp ON dbo.Test_App 
 --For Update 
 --AS 
 --If Update(appstatusrowid) 
 IF  exists (select i.appstatusRowid from #inserted i join #deleted d on i.rowid = d.rowid
            Where d.appstatusrowid <> i.appstatusrowid)
 BEGIN 
 --Insert AppDisp(AppID, LastName, FirstName, [DateTime],Company,Location,LocationName, StatusDisp,[Username]) 
 Select d.Rowid,d.LastName, d.FirstName, getDate(),C.CompanyCode,
 l.locnum,l.locname, ast.Displaytext, SUSER_SNAME()+' '+User 
 From #deleted d
 Join #inserted i on i.rowid = d.rowid
 --From deleted d 
 --Join inserted i on i.rowid = d.rowid
 Inner join Test_App a with (nolock) on a.RowID = d.rowid 
 inner join location l with (nolock) on l.rowid = d.Locationrowid 
 inner join appstatus ast  with (nolock) on ast.rowid = d.appstatusrowid 
 inner join company c with (nolock) on c.rowid = l.CompanyRowid
 Where d.appstatusrowid <> i.appstatusrowid)
 end

一旦获得正确的选择数据,就可以轻松取消注释触发代码和插入行并将 #deleted 或 #inserted 更改为删除或插入。

您会注意到我在临时表中有两条记录,其中一条满足您的条件,另一条不满足您的条件。这允许您测试多个记录更新以及满足条件和不满足条件的结果。所有触发器都应编写为处理多个记录,因为它们不是逐行触发而是批量触发。

First lets introduce you to the inserted and deleted pseudotables which are available only in triggers. Inserted has new values and delted has old values or records being deleted.

You do not want to insert all records into your audit table only those in inserted.

So to insert into an audit table you might want something like inside the trigger code:

insert Myaudittable (<insert field list here>)
Select <insert field list here> from Inserted i
Inner Join AppStatus ast on ast.RowID = i.AppStatusRowID
Inner Join Location l on l.RowID = i.LocationRowID
Inner Join Company c on c.RowID = l.CompanyRowID 

I would personally add columns for old and new values, a column for the type of change and what the date of the change and what user made the change, but you I'm sure have your own requirement to follow.

Suggest you read about triggers in Books online as they can be tricky to get right.

Here's one way to test and debug trigger that I often use. First I create temp tables names #delted and #inserted that have the sturcture of the table I'm going to put the trigger on. Then I write the code to use those instead of the deleted or inserted tables. That wa y I can look at things as I go and make sure everything is right before I change the code to a trigger. Example below with you code added in and modified slightly:

  Create table #inserted(Rowid int, lastname varchar(100), firstname varchar(100), appstatusRowid int)
  Insert #inserted
  select 1, 'Jones', 'Ed', 30
  union all
  select 2, 'Smith', 'Betty', 20

     Create table #deleted (Rowid int, lastname varchar(100), firstname varchar(100), appstatusRowid int)
  Insert #deleted
  select 1, 'Jones', 'Ed', 10
  union all
  select 2, 'Smith', 'Betty', 20

 --CREATE TRIGGER tri_UpdateAppDisp ON dbo.Test_App 
 --For Update 
 --AS 
 --If Update(appstatusrowid) 
 IF  exists (select i.appstatusRowid from #inserted i join #deleted d on i.rowid = d.rowid
            Where d.appstatusrowid <> i.appstatusrowid)
 BEGIN 
 --Insert AppDisp(AppID, LastName, FirstName, [DateTime],Company,Location,LocationName, StatusDisp,[Username]) 
 Select d.Rowid,d.LastName, d.FirstName, getDate(),C.CompanyCode,
 l.locnum,l.locname, ast.Displaytext, SUSER_SNAME()+' '+User 
 From #deleted d
 Join #inserted i on i.rowid = d.rowid
 --From deleted d 
 --Join inserted i on i.rowid = d.rowid
 Inner join Test_App a with (nolock) on a.RowID = d.rowid 
 inner join location l with (nolock) on l.rowid = d.Locationrowid 
 inner join appstatus ast  with (nolock) on ast.rowid = d.appstatusrowid 
 inner join company c with (nolock) on c.rowid = l.CompanyRowid
 Where d.appstatusrowid <> i.appstatusrowid)
 end

Once you get the data for the select correct, then it is easy to uncomment out the trigger code and the insert line and change #deleted or #inserted to deleted or inserted.

You'll note I had two records in the temp tables, one of which met your condition and one of which did not. This allows you to test mulitple record updates as well as results that meet the condition and ones that don't. All triggers should be written to handle multiple records as they are not fired row-by-row but by batch.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文