科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道在SQL Server 2005中实现异步触发器架构

在SQL Server 2005中实现异步触发器架构

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

在SQL Server 2005数据库中,通过新增的Service Broker可以实现异步触发器的处理功能。本文提供一种使用Service Broker实现的通用异步触发器方法。

作者:赛迪网 Alice 来源:天新网 2008年3月20日

关键字: 数据库 Mssql SQL SQL Server

  • 评论
  • 分享微博
  • 分享邮件

3. 使用示例

下面的T-SQL演示使用异步触发器构架。示例中创建了三个表:

Dbo.t1 这个是源表,此表的数据变化将用于其他表

Dbo.t2 这个表要求保持与dbo.t1同步

Dbo.tb_log 这个表记录dbo.t1中的数据变化情况

触发器 TR_async_trigger 用于将表Dbo.t1中的数据变化发送到异步触发器构架中。dbo.p_Sync_t1_t2和dbo.p_Record_log用于处理dbo.t1于中变化的数据。

在处理时,需要把相关的信息登记到异步触发器架构的表中。

-- =======================================
-- 3. 使用示例
-- =======================================
-- ===============================
-- 测试对象
-- a. 源表
CREATE TABLE dbo.t1(
    id int IDENTITY
        PRIMARY KEY,
    col int
)
-- b. 同步的目的表
CREATE TABLE dbo.t2(
    id int IDENTITY
        PRIMARY KEY,
    col int
)
-- c. 记录操作的日志表
CREATE TABLE dbo.tb_log(
    id int IDENTITY
        PRIMARY KEY,
    user_name sysname,
    operate_type varchar(10),
    inserted XML,
    deleted xml
)
GO
 
-- a. 异步发送处理消息的触发器
CREATE TRIGGER TR_async_trigger
ON dbo.t1
FOR INSERT, UPDATE, DELETE
AS
IF @@ROWCOUNT = 0
    RETURN
 
SET NOCOUNT ON
 
-- 将要发送的数据生成xml 数据
DECLARE
    @message xml
SELECT
    @message = (
            SELECT
                table_name = (
                        SELECT TOP 1
                            OBJECT_NAME(parent_object_id)
                        FROM sys.objects
                        WHERE object_id = @@PROCID),
                trigger_name = OBJECT_NAME(@@PROCID),
                user_name = SUSER_SNAME(),
                inserted = (
                        SELECT * FROM inserted FOR XML AUTO, TYPE),
                deleted = (
                        SELECT * FROM deleted FOR XML AUTO, TYPE)
            FOR XML PATH(''), ROOT('root'), TYPE
        )
-- 发送消息
EXEC dbo.p_async_trigger_send
    @message = @message
GO
 
-- b. 处理异步触发器的存储过程
-- b.1 同步到t2 的存储过程
CREATE PROC dbo.p_Sync_t1_t2
    @message xml
AS
SET NOCOUNT ON
DECLARE
    @inserted bit,
    @deleted bit
SELECT
    @inserted = @message.exist('/root/inserted'),
    @deleted = @message.exist('/root/deleted')
IF @inserted = 1
    IF @deleted = 1 -- 更新
    BEGIN
        ;WITH
        I AS(
            SELECT
                id = T.c.value('@id[1]', 'int'),
                col = T.c.value('@col[1]', 'int')
            FROM @message.nodes('/root/inserted/inserted') T(c)
        ),
        D AS(
            SELECT
                id = T.c.value('@id[1]', 'int'),
                col = T.c.value('@col[1]', 'int')
            FROM @message.nodes('/root/deleted/deleted') T(c)
        )
        UPDATE A SET
            col = I.col
        FROM dbo.t2 A, I, D
        WHERE A.ID = I.ID
            AND I.ID = D.ID
    END
    ELSE            -- 插入
    BEGIN
        SET IDENTITY_INSERT dbo.t2 ON
        ;WITH
        I AS(
            SELECT
                id = T.c.value('@id[1]', 'int'),
                col = T.c.value('@col[1]', 'int')
            FROM @message.nodes('/root/inserted/inserted') T(c)
        )
        INSERT dbo.t2(
            id, col)
        SELECT
            id, col
        FROM I
        SET IDENTITY_INSERT dbo.t2 OFF
    END
ELSE                -- 删除
BEGIN
    ;WITH
    D AS(
        SELECT
            id = T.c.value('@id[1]', 'int'),
            col = T.c.value('@col[1]', 'int')
        FROM @message.nodes('/root/deleted/deleted') T(c)
    )
    DELETE A
    FROM dbo.t2 A, D
    WHERE A.ID = D.ID
END
GO
 
-- b.2 记录操作记录到dbo.tb_log 的存储过程
CREATE PROC dbo.p_Record_log
    @message xml
AS
SET NOCOUNT ON
DECLARE
    @inserted bit,
    @deleted bit
SELECT
    @inserted = @message.exist('/root/inserted'),
    @deleted = @message.exist('/root/deleted')
INSERT dbo.tb_log(
    user_name,
    operate_type,
    inserted,
    deleted)
SELECT
    @message.value('(/root/user_name)[1]', 'sysname'),
    operate_type = CASE
                    WHEN @inserted = 1 AND @deleted = 1 THEN 'update'
                    WHEN @inserted = 1 THEN 'insert'
                    WHEN @deleted = 1 THEN 'delete'
                END,
    @message.query('/root/inserted'),
    @message.query('/root/deleted')
GO
 
 
-- ===============================
-- 在异步触发器处理系统中登记对象
INSERT dbo.tb_async_trigger(
    table_name, trigger_name)
VALUES(
    N't1', N'TR_async_trigger')
 
INSERT dbo.tb_async_trigger_subscriber(
    procedure_name)
SELECT N'dbo.p_Sync_t1_t2' UNION ALL
SELECT N'dbo.p_Record_log'
 
INSERT dbo.tb_async_trigger_subscribtion(
    trigger_id, procedure_id)
SELECT 1, 1 UNION ALL
SELECT 1, 2
GO

4.使用测试

下面的T-SQL修改表dbo.t1中的数据,并检查dbo.t2、dbo.tb_log中的数据,以确定异步触发器架构的工作是否成功。

执行完成后可以看到dbo.t2、dbo.tb_log中有相关的记录。

-- ===============================
-- 测试
INSERT dbo.t1
SELECT 1 UNION ALL
SELECT 2
 
UPDATE dbo.t1 SET
    col = 2
WHERE id = 1
 
DELETE dbo.t1
WHERE id = 2
 
-- 显示结果
WAITFOR DELAY '00:00:05' 
-- 延迟5 分钟, 以便有时间处理消息(因为是异步的)
SELECT * FROM dbo.t2
SELECT * FROM dbo.tb_log
GO

5.使用测试

下面的T-SQL删除本文中建立的所有对象。

-- =======================================
-- 5. 删除相关的对象
-- =======================================
-- a. 删除service broker 对象
DROP SERVICE SRV_async_trigger
DROP QUEUE dbo.Q_async_trigger
DROP CONTRACT CNT_async_trigger
DROP MESSAGE TYPE MSGT_async_trigger
GO
 
-- b. 删除异步触发器处理的相关对象
DROP PROC dbo.p_async_trigger_process
DROP PROC dbo.p_async_trigger_send
DROP TABLE dbo.tb_async_trigger_subscribtion
DROP TABLE dbo.tb_async_trigger_subscriber
DROP TABLE dbo.tb_async_trigger
GO
 
-- c. 删除测试的对象
DROP TABLE dbo.tb_log, dbo.t1, dbo.t2
DROP PROC dbo.p_Sync_t1_t2, dbo.p_Record_log
    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章