SQL 服务器查询性能:嵌套游标
SQL Server query performance: Nested cursors
我有一个存储过程,它选择一些 1-n 关系和相关数据到引用列作为 XML 数据。
目的是 return 一条记录和它的 1-n 关系作为一个带有额外数据列的记录,这是通过将这些相关数据添加为 XML.
来完成的
参考文献table:(TABLEA)
ID NAME VALUE
---------------------
1 Sepehr 1000
2 Sarah 1001
相关table: (TABLE B)
ID Value FK_Value ORDER TITLE
-------------------------------------
1 A 1000 1 t1
2 B 1000 2 t2
3 C 1000 3 t3
我想要得到这个输出:
ID NAME FK_Value Attribs
-----------------------------------------------------
1 Sepehr 1000 <XML><ID>1</ID><ID>2</ID><ID>3</ID></XML>
2 Sarah 1001 null
实际上我希望创建一个视图来执行此操作,但我做不到,有人告诉我使用视图是不可能的。
最后这是我写的存储过程 - 这是正确的方法还是有其他方法?
DECLARE @T1 table (A_ID int,Attribs XML)
DECLARE db_cursorLegendRowsValues CURSOR FOR
SELECT ID, VALUE
FROM A
OPEN db_cursorLegendRowsValues
FETCH NEXT FROM db_cursorLegendRowsValues INTO @loop_ID, @loop_VALUE
WHILE @@FETCH_STATUS = 0
BEGIN
DECLARE db_cursorInternal CURSOR FOR
SELECT TITLE, ORDER
FROM B
WHERE FK_Value = @loop_VALUE
OPEN db_cursorInternal
FETCH NEXT FROM db_cursorInternal INTO @tmpTitle, @ORDER
WHILE @@FETCH_STATUS = 0
BEGIN
SET @querySelect = @querySelect + ', MAX(CASE WHEN order = ' + cast(@ORDER as nvarchar(max)) + ' THEN value END) AS [' +REPLACE (@tmpTitle,' ','_') + '] '
FETCH NEXT FROM db_cursorInternal INTO @tmpTitle, @ORDER
END
CLOSE db_cursorInternal
DEALLOCATE db_cursorInternal
SET @query =
' SELECT ' + cast(@loop_ID as nvarchar(max)) +',(
SELECT A.Value,
'
SET @query = @query + STUFF(@querySelect,1,1,'') + ' FROM A
WHERE [A.Value] = ' + cast(@loop_VALUE as nvarchar(max)) + '
FOR XML RAW (''Item''), root (''Items'') , ELEMENTS XSINIL )'
SET @querySelect = ''
--PRINT(@query)
INSERT into @T1 execute (@query )
FETCH NEXT FROM db_cursorLegendRowsValues INTO @loop_ID, @loop_VALUE
END
CLOSE db_cursorLegendRowsValues
DEALLOCATE db_cursorLegendRowsValues
SELECT * FROM @T1
只用一个查询就可以做到这一点 - 您可以在 select 中使用子查询,如下所示:
select id
, name
, value as fk_value
, (select id from @table_b b
where a.value = b.fk_value
for xml path (''), root ('xml'))
from @table_a a
全部可以浓缩成几行,根本不需要游标。这将在视图中可用:
DECLARE @tblA TABLE(ID INT IDENTITY,NAME VARCHAR(100),VALUE INT);
INSERT INTO @tblA VALUES
('Sepehr',1000)
,('Sarah',1001);
DECLARE @tblB TABLE(ID INT IDENTITY,Value VARCHAR(100),FK_Value INT,[ORDER] INT,TITLE VARCHAR(100));
INSERT INTO @tblB VALUES
('A',1000,1,'t1')
,('B',1000,2,'t2')
,('C',1000,3,'t3');
SELECT a.*
,(SELECT ID FROM @tblB AS b WHERE b.FK_Value=a.VALUE FOR XML PATH(''),ROOT('XML'),TYPE) AS Attribs
FROM @tblA AS a
结果
ID NAME VALUE Attribs
1 Sepehr 1000 <XML><ID>1</ID><ID>2</ID><ID>3</ID></XML>
2 Sarah 1001 NULL
我有一个存储过程,它选择一些 1-n 关系和相关数据到引用列作为 XML 数据。
目的是 return 一条记录和它的 1-n 关系作为一个带有额外数据列的记录,这是通过将这些相关数据添加为 XML.
来完成的参考文献table:(TABLEA)
ID NAME VALUE
---------------------
1 Sepehr 1000
2 Sarah 1001
相关table: (TABLE B)
ID Value FK_Value ORDER TITLE
-------------------------------------
1 A 1000 1 t1
2 B 1000 2 t2
3 C 1000 3 t3
我想要得到这个输出:
ID NAME FK_Value Attribs
-----------------------------------------------------
1 Sepehr 1000 <XML><ID>1</ID><ID>2</ID><ID>3</ID></XML>
2 Sarah 1001 null
实际上我希望创建一个视图来执行此操作,但我做不到,有人告诉我使用视图是不可能的。
最后这是我写的存储过程 - 这是正确的方法还是有其他方法?
DECLARE @T1 table (A_ID int,Attribs XML)
DECLARE db_cursorLegendRowsValues CURSOR FOR
SELECT ID, VALUE
FROM A
OPEN db_cursorLegendRowsValues
FETCH NEXT FROM db_cursorLegendRowsValues INTO @loop_ID, @loop_VALUE
WHILE @@FETCH_STATUS = 0
BEGIN
DECLARE db_cursorInternal CURSOR FOR
SELECT TITLE, ORDER
FROM B
WHERE FK_Value = @loop_VALUE
OPEN db_cursorInternal
FETCH NEXT FROM db_cursorInternal INTO @tmpTitle, @ORDER
WHILE @@FETCH_STATUS = 0
BEGIN
SET @querySelect = @querySelect + ', MAX(CASE WHEN order = ' + cast(@ORDER as nvarchar(max)) + ' THEN value END) AS [' +REPLACE (@tmpTitle,' ','_') + '] '
FETCH NEXT FROM db_cursorInternal INTO @tmpTitle, @ORDER
END
CLOSE db_cursorInternal
DEALLOCATE db_cursorInternal
SET @query =
' SELECT ' + cast(@loop_ID as nvarchar(max)) +',(
SELECT A.Value,
'
SET @query = @query + STUFF(@querySelect,1,1,'') + ' FROM A
WHERE [A.Value] = ' + cast(@loop_VALUE as nvarchar(max)) + '
FOR XML RAW (''Item''), root (''Items'') , ELEMENTS XSINIL )'
SET @querySelect = ''
--PRINT(@query)
INSERT into @T1 execute (@query )
FETCH NEXT FROM db_cursorLegendRowsValues INTO @loop_ID, @loop_VALUE
END
CLOSE db_cursorLegendRowsValues
DEALLOCATE db_cursorLegendRowsValues
SELECT * FROM @T1
只用一个查询就可以做到这一点 - 您可以在 select 中使用子查询,如下所示:
select id
, name
, value as fk_value
, (select id from @table_b b
where a.value = b.fk_value
for xml path (''), root ('xml'))
from @table_a a
全部可以浓缩成几行,根本不需要游标。这将在视图中可用:
DECLARE @tblA TABLE(ID INT IDENTITY,NAME VARCHAR(100),VALUE INT);
INSERT INTO @tblA VALUES
('Sepehr',1000)
,('Sarah',1001);
DECLARE @tblB TABLE(ID INT IDENTITY,Value VARCHAR(100),FK_Value INT,[ORDER] INT,TITLE VARCHAR(100));
INSERT INTO @tblB VALUES
('A',1000,1,'t1')
,('B',1000,2,'t2')
,('C',1000,3,'t3');
SELECT a.*
,(SELECT ID FROM @tblB AS b WHERE b.FK_Value=a.VALUE FOR XML PATH(''),ROOT('XML'),TYPE) AS Attribs
FROM @tblA AS a
结果
ID NAME VALUE Attribs
1 Sepehr 1000 <XML><ID>1</ID><ID>2</ID><ID>3</ID></XML>
2 Sarah 1001 NULL