Sql server 我是否可以在SQL Server Service Broker的同一消息队列上运行两个存储过程?

Sql server 我是否可以在SQL Server Service Broker的同一消息队列上运行两个存储过程?,sql-server,sql-server-2008,sql-server-2012,message-queue,service-broker,Sql Server,Sql Server 2008,Sql Server 2012,Message Queue,Service Broker,我有一个填充了多种消息类型的队列,我希望在同一队列上运行两个存储过程,每种消息类型一个存储过程 我不想要一个可以检查多种类型的 问题是,我看不出如何在队列定义中定义两个: CREATE QUEUE MyQueue WITH ACTIVATION ( STATUS = ON, -- How have two? PROCEDURE_NAME = [my_listener_proc], MAX_QUEUE_READERS = 4, EXECUTE AS SEL

我有一个填充了多种消息类型的队列,我希望在同一队列上运行两个存储过程,每种消息类型一个存储过程

我不想要一个可以检查多种类型的

问题是,我看不出如何在队列定义中定义两个:

CREATE QUEUE MyQueue  WITH ACTIVATION
(
    STATUS = ON,
    -- How have two?
    PROCEDURE_NAME = [my_listener_proc],
    MAX_QUEUE_READERS = 4,
    EXECUTE AS SELF
)
GO

上面的评论是有权利的-你只能得到一个激活过程。但是您可以在该进程中放入逻辑,根据消息类型执行其他操作。这是我在生产中使用的一个略作修改的版本:

ALTER PROCEDURE [repl].[myActivation]
AS
BEGIN
    DECLARE
        @message_type nvarchar(256),
        @message XML,
        @rc INT,
        @queuing_order BIGINT;
    DECLARE @messages TABLE (
        [message_type] sysname, 
        [message] XML
    );
    SET NOCOUNT ON;

    WHILE(1=1)
    BEGIN

        WAITFOR(
            RECEIVE TOP (1000)
                [message_type_name],
                CAST([message_body] AS XML)
            FROM [repl].[myQueue]
            INTO @messages
        ), TIMEOUT 5000;

        IF (@@rowCount = 0)
            BREAK;
        ELSE
        BEGIN

            DECLARE [messages] CURSOR FAST_FORWARD LOCAL
            FOR
            SELECT [message], [message_type]
            FROM @messages;

            OPEN [messages];
            WHILE(1=1)
            BEGIN
                FETCH NEXT FROM [messages] 
                INTO @message, @message_type;
                IF (@@fetch_Status <> 0)
                    BREAK;

                BEGIN TRY

                    IF (@message_type = 'A')
                    BEGIN
                        EXEC @rc = [repl].[ProcessAMessage] 
                            @message = @message;
                    END
                    ELSE IF (@message_type = 'B')
                    BEGIN
                        EXEC @rc = [repl].[ProcessBMessage]
                            @message = @message;
                    END 

                    IF (@rc <> 0)
                    BEGIN
                        INSERT INTO [repl].[DeadLetters]
                                ( [Payload], [MessageType] )
                        VALUES  ( @message, @message_type );
                    END
                END TRY
                BEGIN CATCH
                    INSERT INTO [repl].[DeadLetters]
                            ( [Payload], [MessageType] )
                    VALUES  ( @message, @message_type );
                END CATCH
            END
            CLOSE [messages];
            DEALLOCATE [messages];

            DELETE @messages;
        END
    END
END
GO
ALTER过程[repl].[myActivation]
作为
开始
声明
@消息类型nvarchar(256),
@消息XML,
@rc INT,
@排队阶BIGINT;
声明@messages表(
[消息类型]系统名,
[消息]XML
);
不计数;
而(1=1)
开始
等待(
接收顶部(1000)
[消息类型\名称],
强制转换([消息体]为XML)
来自[repl].[myQueue]
进入@messages
),超时5000;
如果(@@rowCount=0)
打破
其他的
开始
声明[消息]光标快进本地
对于
选择[消息],[消息类型]
来自@messages;
打开[消息];
而(1=1)
开始
从[消息]获取下一个消息
进入@message,@message_类型;
如果(@@fetch\u状态0)
打破
开始尝试
如果(@message_type='A')
开始
EXEC@rc=[repl].[ProcessAMessage]
@message=@message;
结束
ELSE IF(@message_type='B')
开始
EXEC@rc=[repl].[ProcessBMessage]
@message=@message;
结束
如果(@rc 0)
开始
插入[repl].[DeadLetters]
([Payload],[MessageType])
值(@message,@message_类型);
结束
结束尝试
开始捕捉
插入[repl].[DeadLetters]
([Payload],[MessageType])
值(@message,@message_类型);
端接
结束
关闭[消息];
取消分配[消息];
删除@条消息;
结束
结束
结束
去
除了根据消息类型路由到不同的进程之外,还有很多工作要做,包括:

  • 一次接收多条消息,以免过于频繁地锁定对话
  • 采取两个步骤确保激活过程不会回滚/出错。有害信息会破坏你的一天

我不使用事务,因为还有另一个过程可以确保消息的效果得到应用。因此,任何给定消息是否成功都无关紧要(因为它不会被相对快速地检测到)。

简短回答:否。创建单独的队列或创建存储过程以根据消息类型调用其他两个队列中的一个