生成XML并在sql server中的表中更新它,而不使用游标

时间:2016-12-15 21:08:14

标签: sql-server xml

我使用游标为每一行生成一个XML文件。我从xml_temp_table中选择了一个ID列表。然后我必须在另一个表(LOCATION_TABLE_XML)中更新这些XML文件。我已经意识到如果我要更新超过20K的行,这个光标效率不高。谢谢,我真的很感激。

     DECLARE @xml_var XML;
     DECLARE @ID INT;
     DECLARE XML_CURSOR CURSOR FOR
     SELECT id
     FROM   xml_temp_table
     WHERE  id IS NOT NULL;

    OPEN XML_CURSOR;
    FETCH NEXT
    FROM  XML_CURSOR
    INTO  @ID;

 WHILE @@FETCH_STATUS = 0
 BEGIN
 SET @xml_var =
(
     SELECT
            (
                   SELECT 'Type'    AS ID,
                          'Initial' AS VALUE,
                          ''        AS TAG,
                          'true'    AS VISIBLE,
                          Getdate() AS HISTORY,
                          ''        AS DESCRIPTION,
                          ''        AS COMMENT
                   FROM   XML_TABLE d
                   WHERE  D.XML_ID = @ID FOR XML PATH('field'),
                          TYPE ) AS '[*]',
            (
                   SELECT 'OwnerName'   AS ID,
                          'Testing_XML' AS VALUE,
                          ''            AS TAG,
                          'true'        AS VISIBLE,
                          Getdate()     AS HISTORY,
                          ''            AS DESCRIPTION,
                          ''            AS COMMENT
                   FROM   XML_TABLE d
                   WHERE  D.XML_ID = @ID FOR XML PATH('field'),
                          TYPE ) AS '[*]'
     FROM   XML_TABLE p
     WHERE  P.XML_ID = @ID FOR XML PATH('Material'),
            ROOT('FormValue') );
 UPDATE S
 SET    S.XML_COL = @xml_var,
 FROM   LOCATION_TABLE_XML S
 WHERE  S.ID = @ID;

 FETCH NEXT
  FROM  XML_CURSOR
  INTO  @ID;

  END; 

必需输出

<FormValue>
 <Material>
  <field>
  <id>Type</id>
  <value>Initial</value>
  <tag />
  <visible>true</visible>
<history>2016-11-08</history>
<description />
<comment />
</field>
<field>
  <id>OwnerName</id>
  <value>Testing_XML</value>
  <tag />
  <visible>true</visible>
  <history>2016-11-08</history>
<description />
<comment />
</field>
</Material>
</FormValue>

1 个答案:

答案 0 :(得分:2)

有一件事是肯定的:你这里不需要CURSOR ......

游标是坏的和邪恶的...它们是由数据魔鬼发明的,导致我们的穷人开发人员远离基于集合的思维。它会把你拉到黑暗的程序性痛苦 ......(好吧,在某些情况下,CURSOR是正确的选择,但这些很少见。 ..)

我从John Cappeletti那里偷走了测试场景(约翰! + d 你......)并认为这可以简化:

不需要CROSS APPLY ...由于XML是标量值,因此可以直接使用。并且无需将CTE加入@YourTable,因为CTE本身可以更新:

Declare @YourTable table (ID int,Active bit,First_Name varchar(50),Last_Name varchar(50),EMail varchar(50),XMLData xml)
Insert into @YourTable values
(1,1,'John','Smith','john.smith@email.com',null),
(2,0,'Jane','Doe'  ,'jane.doe@email.com',null)

;with cte as 
(
    Select A.ID
          ,A.XMLData
          ,( 
                    -- This would be your XML generation
                    -- Notice the reference to A.ID
                    Select XMLData = (Select * From @YourTable Where ID=A.ID For XML Path('root')) 
           ) AS NewXML
     From  @YourTable A
) 
Update cte Set XMLData = NewXML;

Select * from @YourTable 

但这可以更简单:我现在需要在物理上创建表格,因为我们需要一个表格的别名,否则......

CREATE TABLE YourTable(ID int,Active bit,First_Name varchar(50),Last_Name varchar(50),EMail varchar(50),XMLData xml);
Insert into YourTable values
(1,1,'John','Smith','john.smith@email.com',null),
(2,0,'Jane','Doe'  ,'jane.doe@email.com',null);

UPDATE YourTable SET XMLData= ( 
                                -- This would be your XML generation
                                Select x.* From YourTable AS x Where x.ID=YourTable.ID For XML Path('root')
                               )

Select * from YourTable
GO

DROP TABLE YourTable; 

注意1 :我理解您的句子我选择了xml_temp_table 中的ID列表,您需要将此流程过滤为ID列表。如果是这样,只需添加

WHERE YourTable.ID IN(SELECT filter.ID FROM SomeWhere AS filter)

注意2 :句子然后我必须更新另一个表中的这些XML文件对我来说还不清楚...如果你想创建< / strong>在另一个表中的这些行,只需使用

INSERT INTO OtherTable(col1,col2,...) SELECT col1,col2, ... FROM ...

如果另一个表具有给定ID的相应行,则可以轻松更改与此对应的语句。如果您需要帮助,请回来......