8wDlpd.png
8wDFp9.png
8wDEOx.png
8wDMfH.png
8wDKte.png

如何在 SQL 中查询 XML 以通过部分 text() 匹配来查找元素

vardhan 2月前

59 0

假设表列中有以下 XML:用户名测试用户

假设表列中有以下 XML:

<UserFields>
  <UserField>
    <Name>UserName</Name>
    <Value>test_user</Value>
  </UserField>
  <UserField>
    <Name>Age</Name>
    <Value>24</Value>
  </UserField>
  <UserField>
    <Name>Password</Name>
    <Value>test1234!</Value>
  </UserField>
  <UserField>
    <Name>AgentPassword</Name>
    <Value>1234Test!</Value>
  </UserField>
</UserFields>
<ActionAttributes>
  <Action>
   <Name>LoginPassword</Name>
   <Value>Test123!</Value>
  </Action>
</ActionAttributes>

我想查询 XML 以查找任何具有 <Name> 包含该单词 text() 的节点 password ,并将节点的文本替换 <Value> 为星号。在示例中,将有三次替换,最终我会得到以下 XML。

<UserFields>
  <UserField>
    <Name>UserName</Name>
    <Value>test_user</Value>
  </UserField>
  <UserField>
    <Name>Age</Name>
    <Value>24</Value>
  </UserField>
  <UserField>
    <Name>Password</Name>
    <Value>********</Value>
  </UserField>
  <UserField>
    <Name>AgentPassword</Name>
    <Value>********</Value>
  </UserField>
</UserFields>
<ActionAttributes>
  <Action>
   <Name>LoginPassword</Name>
   <Value>********</Value>
  </Action>
</ActionAttributes>

我想出了这个:

SET @MyDoc.modify('
  replace value of (//UserField[Name="Password"]/Value/text())[1]
  with "********"
');

该代码的问题是:

  1. 它对父元素的名称 ('UserField') 进行硬编码。
  2. 它对值的名称进行硬编码, <Name> 因此它只能找到“密码”而不是其他变体。

如果用英语来说,我会说:

\'对于具有 <Name> <Value> 子节点的任何节点。 如果子节点 <Name> 包含单词“密码”,则 <Value> 用星号替换子节点的文本。\'

帖子版权声明 1、本帖标题:如何在 SQL 中查询 XML 以通过部分 text() 匹配来查找元素
    本站网址:http://xjnalaquan.com/
2、本网站的资源部分来源于网络,如有侵权,请联系站长进行删除处理。
3、会员发帖仅代表会员个人观点,并不代表本站赞同其观点和对其真实性负责。
4、本站一律禁止以任何方式发布或转载任何违法的相关信息,访客发现请向站长举报
5、站长邮箱:yeweds@126.com 除非注明,本帖由vardhan在本站《sql-server》版块原创发布, 转载请注明出处!
最新回复 (0)
  • XPath 表达式 必须定义单个节点

    表达式1

    标识要更新其值的节点。它必须仅标识单个节点。也就是说,Expression1 必须是静态单例。如果 XML 是类型化的,则节点的类型必须是简单类型。当选择多个节点时,会引发错误。

    使用 SQL 变量可以避免对表达式中的谓词进行硬编码。

    DECLARE @Name VARCHAR(50) = 'Password';
    DECLARE @NewValue VARCHAR(50) = '********';
    SET @MyDoc.modify('
    replace value of (//UserField[Name = sql:variable("@Name")]/Value/text())[1]
    with sql:variable("@NewValue")
    ');
    

    迭代可能的值

    DECLARE @myDoc XML;
    DECLARE @Name VARCHAR(50);
    DECLARE @parent VARCHAR(50);
    DECLARE @NewValue VARCHAR(50) = '********';
    DECLARE @rowid int;
    
    DECLARE @tnames TABLE(
    rowid iNT,
    names VARCHAR(50),
    parent VARCHAR(50)
    );
    
    SET @myDoc = '<root>
    <UserFields>
      <UserField>
        <Name>UserName</Name>
        <Value>test_user</Value>
      </UserField>
      <UserField>
        <Name>Age</Name>
        <Value>24</Value>
      </UserField>
      <UserField>
        <Name>Password</Name>
        <Value>test1234!</Value>
      </UserField>
      <UserField>
        <Name>AgentPassword</Name>
        <Value>1234Test!</Value>
      </UserField>
    </UserFields>
    <ActionAttributes>
      <Action>
       <Name>LoginPassword</Name>
       <Value>Test123!</Value>
      </Action>
    </ActionAttributes>
    </root>
    ';
    
    --SELECT @myDoc;
    
    INSERT INTO @tnames (rowid, names, parent)
    SELECT ROW_NUMBER() OVER (ORDER BY t.xname) AS ROWID, T.xname.value('(Name/text())[1]', 'varchar(max)') as names, T.xname.value('(local-name(.))[1]', 'varchar(max)') as parent
    FROM @myDoc.nodes('//*[Name[contains(., "Password")]]') T(xname); 
    
    SELECT * FROM @tnames;
    
    WHILE (SELECT COUNT(1) FROM @tnames) > 0
    BEGIN
        SELECT @rowid = rowid, @Name = names, @parent= parent FROM @tnames;
        
        SET @MyDoc.modify('
        replace value of (//*[local-name() = sql:variable("@parent")][Name = sql:variable("@Name")]/Value/text())[1]
        with sql:variable("@NewValue")
        ');
        
        DELETE FROM @tnames where rowid = @rowid;
    
        --SELECT ROW_NUMBER() OVER (ORDER BY t.xname) AS ROWID, T.xname.value('(Name/text())[1]', 'varchar(max)') as names, T.xname.value('(Value/text())[1]', 'varchar(max)') as value 
        --FROM @myDoc.nodes('//*[local-name() = sql:variable("@parent")][Name = sql:variable("@Name")]') T(xname);
        
    END
    
返回
作者最近主题: