Sql触发父子

时间:2013-11-14 16:39:58

标签: sql sql-server triggers

我正在尝试找出创建触发器的最佳方法,但我使用sql server 2008打了一个砖墙 我希望创建一个存储所有电话号码(号码)的中央表,其中应包含来自客户表的所有客户号码。 Numbers有一个子表numbercustomer,它将一个数字链接到一个或多个客户。 我的表:

CREATE TABLE [Campaign].[Number](
    [NumberID] [int] IDENTITY(1,1) NOT NULL,
    [Number] [varchar](15) NOT NULL,
    [LastUpdated] [timestamp] NOT NULL,
 CONSTRAINT [Pk_Number] PRIMARY KEY CLUSTERED 
(
    [NumberID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

CREATE TABLE [Campaign].[NumberCustomer](
    [CustomerNumberID] [int] IDENTITY(1,1) NOT NULL,
    [NumberID] [int] NOT NULL,
    [CustomerID] [int] NOT NULL,
 CONSTRAINT [PK_CustomerNumber] PRIMARY KEY CLUSTERED 
(
    [CustomerNumberID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

CREATE TABLE [Crm].[Customer](
    [CustomerID] [int] IDENTITY(30000,1) NOT NULL,
    [FirstName] [varchar](255) NULL,
    [LastName] [varchar](255) NULL,
    [MobileNumber] [varchar](11) NULL,
    [LandlineNumber] [varchar](11) NULL,
 CONSTRAINT [PK__Customer__8CB286B91CF15040] PRIMARY KEY CLUSTERED 
(
    [CustomerID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

我希望触发器检查数字表并插入数字(如果不存在)。触发器的第二部分然后检查并插入如果不存在到客户的链接。 我可以使用触发器来更新数字表,如下所示bbut我对性能有所了解。

CREATE TRIGGER [Crm].[Customer_Number_Updated] ON [Crm].[Customer]
 AFTER Update, INSERT
 NOT FOR REPLICATION AS
 SET NoCount On 

DECLARE 
  @AuditTime DATETIME, 
  @IsDirty BIT
SET @AuditTime = GetDate()

SET @IsDirty = 0

  Begin Try
    INSERT INTO 
        [Campaign].[Number]([Number])
    select 
        number 
    from 
    (
    Select
        i.MobileNumber as number
    From 
        inserted i
    join 
        deleted d
    on 
        i.CustomerID = d.CustomerID 
    and
    isnull(i.MobileNumber ,'') <> isnull(d.MobileNumber,'')
    UNION
    Select
        i.LandlineNumber as number
    From 
        inserted i
    join 
        deleted d
    on 
        i.CustomerID = d.CustomerID 
    and
    isnull(i.LandlineNumber ,'') <> isnull(d.LandlineNumber,'')
    UNION
    Select
        i.AlternateContactNumber as number
    From 
        inserted i
    join 
        deleted d
    on 
        i.CustomerID = d.CustomerID 
    and
    isnull(i.AlternateContactNumber ,'') <> isnull(d.AlternateContactNumber,'')
    ) as nums
    WHERE NOT EXISTS
        (
            SELECT 
                *
            FROM 
                [Campaign].[Number] cn
            WHERE 
                cn.Number = nums.number 
        )
End try
 Begin Catch 
 IF ERROR_NUMBER() <> 2627
   DECLARE @ErrorMessage NVARCHAR(4000), @ErrorSeverity INT, @ErrorState INT;
   SET @ErrorMessage = ERROR_MESSAGE();  
   SET @ErrorSeverity = ERROR_SEVERITY(); 
   SET @ErrorState = ERROR_STATE();  
   RAISERROR(@ErrorMessage,@ErrorSeverity,@ErrorState) with log;
 End Catch

GO

非常感谢任何帮助?

Rob

1 个答案:

答案 0 :(得分:0)

您的触发器适用于UPDATE但不适用于INSERT:您正在加入DELETED和INSERTED,当您插入新记录时,没有任何内容被删除。 您应该在触发器中执行INSERT和UPDATE,或者执行MERGE。

这是带有插入和更新的代码(只有try块中的代码)

插入执行带删除的左连接,并检查id为null(反半连接,相当于没有texist)。

更新执行带插入的内部联接以仅检查更新记录

  Begin Try

    -- insert new records
    INSERT INTO 
        [Campaign].[Number]([Number])
    select 
        i.MobileNumber
    from inserted i
    left join deleted d on i.customerid = d.customerid
    where d.customerid is null -- new records (no deleted record)
    and not exists( select Number from [Campaign].[Number] c where c.number = i.MobileNumber)
    -- union the same for LAndLineNumber
    -- union the same for AlternateNumber

    -- update existing number
    update [Campaign].[Number] 
        set Number = i.MobileNumber
        -- set LandLineNumber too
        -- and AlternateNumber
    from [Campaign].[Number] n
        left join deleted d on d.MobileNumber = n.Number
        inner join inserted i on i.CustomerId = d.CustomerId

End try