xquery 循环遍历列
我的任务是使用 Xquery 创建一个服务代理来处理对表集合的跟踪更改。我已经弄清楚如何传递消息(列名的 xml 以及语句的更新和删除表)。目的是获取列名称列表,然后比较每个更新/删除的行而不是更改的类似列。
下面是 XML 的示例:
<Update xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<TableName>
<ID>2414</ID>
<fkEvent>2664</fkEvent>
<fkType xsi:nil="true" />
<Description>Phil Test 3</Description>
<DTS>2011-04-04T14:01:36.533</DTS>
<uID>192204FA-612F-46F4-A6CB-1B4D53769A81</uID>
<VersionID xsi:nil="true" />
<UpdateDateTime>2011-04-04T14:04:31.013</UpdateDateTime>
<DeleteFlag>0</DeleteFlag>
<Updated>0</Updated>
<Owner>42</Owner>
<CreatedBy>42</CreatedBy>
</TableName>
</Update>
生成者:
SET @xml1 = (SELECT * FROM TableName ORDER BY ID DESC FOR XML AUTO, ELEMENTS XSINIL, ROOT('MsgEnv'))
我有以下代码:
WHILE @cnt <= @totCnt BEGIN
SELECT @child = @ColNames.query('/Columns/name[position()=sql:variable("@cnt")]')
SET @CurrentCol = REPLACE(REPLACE(CAST(@child AS VARCHAR(500)), '<name>', ''), '</name>', '')
PRINT @CurrentCol
WHILE @updateCnt <= @updateCntTotal BEGIN
SELECT @childUpdate = @xml1.query('/Update/TableName/sql:variable("@CurrentCol")')
PRINT CAST(@childUpdate AS VARCHAR(MAX))
WHILE @deleteCnt <= @deleteCntTotal BEGIN
SELECT @deleteCnt = @deleteCnt + 1
END
SET @deleteCnt = 1
SELECT @updateCnt = @updateCnt + 1
END
SET @updateCnt = 1
SELECT @cnt = @cnt + 1
END
我遇到的问题是动态设置此语句的列名:
SELECT @childUpdate = @xml1.query('/Update/TableName/sql:variable("@CurrentCol")')
我使用 sql:variable 尝试了几种不同的变体。难道不能这样做吗?我希望能够动态地执行此操作,因为我们需要“审核”许多表的更改。
编辑 1:
SELECT @childUpdate = @xml1.query('/Update/TableName/*[name() = sql:variable("@CurrentCol")]')
产生此错误(包括 () 中的 . 具有类似的效果。
Msg 2395, Level 16, State 1, Line 34
XQuery [query()]: There is no function '{http://www.w3.org/2004/07/xpath-functions}:name()'
I have been tasked with creating a service broker using Xquery to handle tracking changes on a collection of tables. I have figured out how to pass the messages (xml of column names and the updated and deleted tables for the statements). The aim is to get the list of column names and then compare the like column for each updated/deleted row and not a change.
Here is a sample of the XML:
<Update xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<TableName>
<ID>2414</ID>
<fkEvent>2664</fkEvent>
<fkType xsi:nil="true" />
<Description>Phil Test 3</Description>
<DTS>2011-04-04T14:01:36.533</DTS>
<uID>192204FA-612F-46F4-A6CB-1B4D53769A81</uID>
<VersionID xsi:nil="true" />
<UpdateDateTime>2011-04-04T14:04:31.013</UpdateDateTime>
<DeleteFlag>0</DeleteFlag>
<Updated>0</Updated>
<Owner>42</Owner>
<CreatedBy>42</CreatedBy>
</TableName>
</Update>
Generated by:
SET @xml1 = (SELECT * FROM TableName ORDER BY ID DESC FOR XML AUTO, ELEMENTS XSINIL, ROOT('MsgEnv'))
I have the following code:
WHILE @cnt <= @totCnt BEGIN
SELECT @child = @ColNames.query('/Columns/name[position()=sql:variable("@cnt")]')
SET @CurrentCol = REPLACE(REPLACE(CAST(@child AS VARCHAR(500)), '<name>', ''), '</name>', '')
PRINT @CurrentCol
WHILE @updateCnt <= @updateCntTotal BEGIN
SELECT @childUpdate = @xml1.query('/Update/TableName/sql:variable("@CurrentCol")')
PRINT CAST(@childUpdate AS VARCHAR(MAX))
WHILE @deleteCnt <= @deleteCntTotal BEGIN
SELECT @deleteCnt = @deleteCnt + 1
END
SET @deleteCnt = 1
SELECT @updateCnt = @updateCnt + 1
END
SET @updateCnt = 1
SELECT @cnt = @cnt + 1
END
The trouble I am having is dynamically setting the column name for this statement:
SELECT @childUpdate = @xml1.query('/Update/TableName/sql:variable("@CurrentCol")')
I have tried a few different variations using the sql:variable. Is it not possible to do this? I'd like to be able to do this dynamically as there are lots of tables we need to "audit" changes on.
Edit 1:
SELECT @childUpdate = @xml1.query('/Update/TableName/*[name() = sql:variable("@CurrentCol")]')
Yields this error (including the . in the () has a similar effect.
Msg 2395, Level 16, State 1, Line 34
XQuery [query()]: There is no function '{http://www.w3.org/2004/07/xpath-functions}:name()'
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您的 XQuery 表达式:
它将为每个
/Update/TableName
元素调用sql:variable()
扩展函数。如果您想选择
TableName
的子级与扩展函数的字符串结果同名,请使用:Your XQuery expression:
It will call
sql:variable()
extension function for each/Update/TableName
element.If you want to select
TableName
's child with the same name as the string result of your extension function, then use:前面的答案根本没有帮助,但这是我发现适用于这种情况的方法。触发器将传入 4 个 XML 字符串。第一个包含列信息,接下来两个是 INSERTED 和 DELETED 临时表的 XML 内容,最后一个是元字符串(架构名称、表名称、用户更新、时间戳等)。
列 XML 代码如下所示:
@ColNames 被传递到消息队列中。
这是处理排队消息的过程的基础:
然后将 @Changes 的内容插入到永久表中(该表现在位于与该数据库中的其余表不同的磁盘卷上)。
The previous answer didn't help at all but here is what I have found to work for this situation. The trigger will pass in 4 XML strings. The first contains the column information, the next two are the XML contents of the INSERTED and DELETED temporary tables, and the last is a Meta string (schema name, table name, updated by user, timestamp, etc).
Here is what the column XML code looks like:
@ColNames is passed into the message queue.
This is the basis for the procedure that processes the queued messages:
The contents of @Changes is then inserted into the permanent table (which is now on a separate disk volume from the rest of the tables in that database).