我在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 - Call Stored Procedure for each record游标很糟糕。所以我想知道更好的方法。我不介意我的存储过程有多少改变来实现这一点,只要它最终正常工作并且很好。
答案 0 :(得分: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
答案 1 :(得分:0)
根据穆罕默德的回答,这就是我最终的结果。仍然希望有人能告诉我如何做到没有游标。
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
答案 2 :(得分:0)
如果您使用的是SQL Server 2008 或更新版本,则可以执行以下操作:
定义用户定义的表格类型,其中包含与您的过程相关的所有列:
CREATE TYPE dbo.SendLogLineType
AS TABLE (LineDate DATETIME2(3), LineData VARCHAR(200), DeviceID VARCHAR(128),
ApplicationName VARCHAR(64), AppUserName VARCHAR(6) )
然后,将您的行提取到该表中,并添加其他“固定”参数(这发生在您的[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)
最后,更改您的spSendLogLine
过程以接受该定义的表类型的表值参数并更改其逻辑,以便它将遍历所有传递的行进入它:
CREATE PROCEDURE spSendLogLine
(@SendLogLineData dbo.SendLogLineType READONLY)
AS
BEGIN
-- iterate over all rows in @SendLogLineData and send out those e-mails!
END