1

我在 SQL Server 中有这个存储过程:

alter PROCEDURE [dbo].[spSendLogLinesAsXML]
(
    @device_id varchar(128),
    @application_name VARCHAR(64),
    @application_user_name VARCHAR(6),
    @log_lines_xml XML
)
AS
BEGIN

DECLARE
    @ixml INT,
    @log_line_dt DATETIME,
    @log_line_message varchar(max)

EXEC sp_xml_preparedocument @ixml OUTPUT,
    @log_lines_xml

SELECT @log_line_dt = dt,
    @log_line_message = data
FROM OPENXML(@ixml, '/lines/line', 3) WITH (
        dt DATETIME,
        data varchar(max)
        )   

--I want to do the following for each line element      
EXEC spSendLogLine
    @device_id = @device_id,
    @application_name = @application_name,
    @application_user_name = @application_user_name,
    @log_line_dt = @log_line_dt,
    @log_line_message = @log_line_message   

EXEC sp_xml_removedocument @ixml

return -100

END

我这样调用存储过程:

EXEC @return_value = [dbo].[spSendLogLinesAsXML]
     @device_id = N'devid123',
     @application_name = N'CJA App 1',
     @application_user_name = N'anatoli',
     @log_lines_xml = '<lines><line><dt>2013-03-01T13:00:00</dt><data>Something happened and it was logged</data></line><line><dt>2013-03-01T13:01:00</dt><data>Oh my god the building is burning and people are dying</data></line></lines>'

如何修改我的存储过程以为每个行元素调用 spSendLogLine?

编辑:根据SQL - 每个记录游标的调用存储过程都是坏的。所以我想知道一个更好的方法。我不介意我的存储过程为了实现这一点而改变了多少,只要它最终能正常工作并且很好。

4

3 回答 3

1
alter PROCEDURE [dbo].[spSendLogLinesAsXML]
(
    @device_id varchar(128),
    @application_name VARCHAR(64),
    @application_user_name VARCHAR(6),
    @log_lines_xml XML
)
AS
BEGIN

declare @log_line_dt datetime,
        @log_line_message varchar(1024)

declare @curse cursor 
set @curse = cursor fast_forward for 
select n.d.value('dt[1]', 'datetime') as log_line_dt, n.d.value('data[1]', 'varchar(1024)') as log_line_message
from @log_lines_xml.nodes('/lines/line') n(d)

open @curse

fetch next from @curse into @log_line_dt, @log_line_message

while (@@fetch_status = 0)
begin
    EXEC spSendLogLine
        @device_id = @device_id,
        @application_name = @application_name,
        @application_user_name = @application_user_name,
        @log_line_dt = @log_line_dt,
        @log_line_message = @log_line_message   

    fetch next from @curse into @log_line_dt, @log_line_message
end

close @curse;

return -100
END
GO
于 2013-03-01T16:41:23.853 回答
0

这就是我按照 muhmud 的回答而得到的结果。仍然希望有人能告诉我如何在没有光标的情况下做到这一点。

ALTER PROCEDURE [dbo].[spSendLogLinesAsXML] 
(
    @device_id VARCHAR(128),
    @application_name VARCHAR(64),
    @application_user_name VARCHAR(6),
    @log_lines_xml XML
)
AS
BEGIN
DECLARE @ixml INT,
    @log_line_dt DATETIME,
    @log_line_message VARCHAR(max),
    @cursor CURSOR

SET @cursor = CURSOR FAST_FORWARD
FOR

SELECT n.d.value('dt[1]', 'datetime') AS log_line_dt,
    n.d.value('data[1]', 'varchar(max)') AS log_line_message
FROM @log_lines_xml.nodes('/lines/line') n(d)

OPEN @cursor

FETCH NEXT
FROM @cursor
INTO @log_line_dt,
    @log_line_message

WHILE (@@fetch_status = 0)
BEGIN
    EXEC spSendLogLine @device_id = @device_id,
        @application_name = @application_name,
        @application_user_name = @application_user_name,
        @log_line_dt = @log_line_dt,
        @log_line_message = @log_line_message

    FETCH NEXT
    FROM @cursor
    INTO @log_line_dt,
        @log_line_message
END

RETURN - 100
END
于 2013-03-01T17:07:59.217 回答
0

如果您使用的是 SQL Server 2008或更高版本,则可以执行以下操作:

  1. 定义一个用户定义的表类型,其中包含与您的过程相关的所有列:

    CREATE TYPE dbo.SendLogLineType 
         AS TABLE (LineDate DATETIME2(3), LineData VARCHAR(200), DeviceID VARCHAR(128), 
                   ApplicationName VARCHAR(64), AppUserName VARCHAR(6) )
    
  2. 然后,将您的行提取到该表中,并添加其他“固定”参数(这发生在您的[spSendLogLinesAsXML]过程中):

    DECLARE @InputTable dbo.SendLogLineType
    
    INSERT INTO @InputTable(LineDate, LineData, DeviceID, ApplicationName, AppUserName)
       SELECT
          XLine.value('(dt)[1]', 'DATETIME2'),
          XLine.value('(data)[1]', 'varchar(200)'), 
          @device_id,
          @application_name,
          @application_user_name
       FROM     
          @log_lines_xml.nodes('/lines/line') AS XTbl(XLine)  
    
  3. 最后,更改您的spSendLogLine过程以接受该已定义表类型的表值参数并更改其逻辑,以便它将遍历传递给它的所有行:

    CREATE PROCEDURE spSendLogLine
        (@SendLogLineData dbo.SendLogLineType READONLY)
    AS
    BEGIN
        -- iterate over all rows in @SendLogLineData and send out those e-mails!
    END
    

在相关的 MSDN SQL Server 联机丛书文档页面上阅读有关表值参数的更多信息

于 2013-03-01T17:17:26.787 回答