1

我的表中有一个带有 XML 的列,如下所示:

<Notes> <Note>
    <Author>test</Author>
    <AuthorInitials>JJJ</AuthorInitials>
    <Contents>Test treatment notes 3</Contents>
    <DateCreated>2013-07-17T14:43:00</DateCreated>
    <DateModified>2013-07-17T14:43:00</DateModified>
</Note>
<Note>
    <Author>test</Author>
    <AuthorInitials>JJJ</AuthorInitials>
    <Contents>This is the intial notes test for tasks</Contents>
    <DateCreated>2013-07-17T14:36:00</DateCreated>
    <DateModified>2013-07-17T14:36:00</DateModified>
</Note>

<Notes> <Note>
    <Author>test</Author>
    <AuthorInitials>JJJ</AuthorInitials>
    <Contents>Test 4 of Task Notes</Contents>
    <DateCreated>2013-07-17T14:57:00</DateCreated>
    <DateModified>2013-07-17T14:57:00</DateModified>
</Note>
<Note>
    <Author>test</Author>
    <AuthorInitials>JJJ</AuthorInitials>
    <Contents>This is the second note test for tasks</Contents>
    <DateCreated>2013-07-17T14:37:00</DateCreated>
    <DateModified>2013-07-17T14:37:00</DateModified>
</Note>

我想解析并得到<Contents>它的一部分。有些字段有多个<Contents>,所以我需要能够拉出所有字段。

我的想法是使用游标并将结果存储在表中,但我还是 SQL Server 的新手,我认为我并不完全理解它们。

这是我目前拥有的:

  DECLARE @temptable TABLE
           (
               Category          varchar(5000),
               Notes             varchar(5000)
           )
  DECLARE @Contents     varchar(5000)



  DECLARE c CURSOR FOR SELECT COMMENTS
                    FROM EVENT
                   WHERE COMMENTS <> ''
                     AND COMMENTS IS NOT NULL
                     AND ID = 1171438

    OPEN c

   FETCH NEXT FROM c INTO @Contents

   WHILE (@@FETCH_STATUS = 0)
   BEGIN
      INSERT INTO @temptable (Category, Notes)
      SELECT 'Notes',
             SUBSTRING(COMMENTS,
                       (CHARINDEX('<Contents>',
                                  COMMENTS)+10),
                       (CHARINDEX('</Contents>',
                                  COMMENTS)-CHARINDEX('<Contents>',
                                                                                 COMMENTS)-10))
        FROM Event
       WHERE COMMENTS <> ''
         AND COMMENTS IS NOT NULL
         AND ID = 1171438
       FETCH NEXT FROM c INTO @Contents
   END

   CLOSE c
   DEALLOCATE c

  SELECT *
    FROM @temptable

但这仅返回:

Notes | Test treatment notes 3
Notes | Test 4 of Task Notes
Notes | Test treatment notes 3
Notes | Test 4 of Task Notes

知道我错过了什么吗?

编辑:有效的解决方案:

  DECLARE @temptable TABLE
               (
                   Category          varchar(5000),
                   Notes             XML
               )
   INSERT INTO @temptable (Category, Notes)
   SELECT 'Notes',
          COMMENTS
     FROM Event
    WHERE COMMENTS <> ''
      AND COMMENTS IS NOT NULL
      AND ID = 1171438

   SELECT Category,
          Content = XNote.value('(Contents)[1]', 'varchar(5000)')
     FROM @temptable
    CROSS APPLY Notes.nodes('/Notes/Note') AS Xtbl(Xnote)
4

3 回答 3

1

如果您的列是XMLSQL Server中的类型,您可以使用非常简单易用的 XQuery 。

试试这个(另请注意:您必须使用有效的结束标记关闭 XML!):

DECLARE @temptable TABLE (ID INT NOT NULL, Notes XML)

INSERT INTO @temptable VALUES(1, '<Notes> <Note>
    <Author>test</Author>
    <AuthorInitials>JJJ</AuthorInitials>
    <Contents>Test treatment notes 3</Contents>
    <DateCreated>2013-07-17T14:43:00</DateCreated>
    <DateModified>2013-07-17T14:43:00</DateModified>
</Note>
<Note>
    <Author>test</Author>
    <AuthorInitials>JJJ</AuthorInitials>
    <Contents>This is the intial notes test for tasks</Contents>
    <DateCreated>2013-07-17T14:36:00</DateCreated>
    <DateModified>2013-07-17T14:36:00</DateModified>
</Note></Notes>'), (2, '<Notes> <Note>
    <Author>test</Author>
    <AuthorInitials>JJJ</AuthorInitials>
    <Contents>Test 4 of Task Notes</Contents>
    <DateCreated>2013-07-17T14:57:00</DateCreated>
    <DateModified>2013-07-17T14:57:00</DateModified>
</Note>
<Note>
    <Author>test</Author>
    <AuthorInitials>JJJ</AuthorInitials>
    <Contents>This is the second note test for tasks</Contents>
    <DateCreated>2013-07-17T14:37:00</DateCreated>
    <DateModified>2013-07-17T14:37:00</DateModified>
</Note></Notes>')

SELECT
    ID,
    Content = XNote.value('(Contents)[1]', 'varchar(100)')
FROM 
    @temptable
CROSS APPLY
    notes.nodes('/Notes/Note') AS XTbl(XNote)

这给了我输出:

ID  Content
1   Test treatment notes 3
1   This is the intial notes test for tasks
2   Test 4 of Task Notes
2   This is the second note test for tasks

这里绝对不需要占用性能和内存的光标!

于 2013-08-09T13:29:03.377 回答
0
DECLARE @MyTable TABLE(
    Id INT IDENTITY(1,1) PRIMARY KEY,
    XmlCol XML NOT NULL
);
INSERT @MyTable(XmlCol)
VALUES(N'<Notes> <Note>
    <Author>test</Author>
    <AuthorInitials>JJJ</AuthorInitials>
    <Contents>Test treatment notes 3</Contents>
    <DateCreated>2013-07-17T14:43:00</DateCreated>
    <DateModified>2013-07-17T14:43:00</DateModified>
</Note>
<Note>
    <Author>test</Author>
    <AuthorInitials>JJJ</AuthorInitials>
    <Contents>This is the intial notes test for tasks</Contents>
    <DateCreated>2013-07-17T14:36:00</DateCreated>
    <DateModified>2013-07-17T14:36:00</DateModified>
</Note>
</Notes>');

SELECT  *,
        t.XmlCol.query('
            for $i in (/Notes/Note/Contents)
                return $i
        ') AS AllContent0, -- Only <Contents> elements
        t.XmlCol.query('
            for $i in (/Notes/Note/Contents/text())
                return $i
        ') AS AllContent1, -- Only text without separator
        STUFF(CONVERT(NVARCHAR(4000),t.XmlCol.query('
            for $i in (/Notes/Note/Contents/text())
                return concat(",",$i)
        ')),1,1,'') AS AllContent2 -- Only text with "," as separator
FROM    @MyTable t;
于 2013-08-09T13:37:29.683 回答
0

SQL Server 可以使用 XPath/XQuery 从 XML 中提取数据。这比你正在做的事情要好得多。

理想情况下,您会将数据存储为 XML 并运行这样的查询。

select 
    id,
    tc.contents.value('.', 'nvarchar(500)')
from yourtable t
    cross apply 
     comments.nodes('/Notes/Note/Contents') as tc(contents)

请参阅http://technet.microsoft.com/en-us/library/ms188282.aspx

如果你不能改变数据结构(我强烈建议你这样做),你总是可以这样做

select tc.contents.value('.', 'nvarchar(500)')
from (select CONVERT(xml, comments) c from yourtable) t
    cross apply 
     c.nodes('/Notes/Note/Contents') as tc(contents)     
于 2013-08-09T13:27:14.430 回答