我有一个status
表,我必须找到未使用的状态
状态代码可以在活动模板中使用,活动模板具有带有自定义公式的actionlist
xml列。
到目前为止,我已经写过这个有效,但速度非常慢(超过一分钟就能获得5000行),我需要加快速度。
select *
from [status] s
where not exists (
select top 1 1
from Wf_ActivityTemplate at
where at.actionlist.value('.', 'nvarchar(max)') like '%@GetStatusId("' + s.code + '")%'
)
actionlist
列看起来像这样(删除了不相关的节点)
如您所见,我需要在//ActionTriplet/Argument
节点中搜索,该节点本身是存储在文本中的xml节点。
<ArrayOfActionTriplet xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<ActionTriplet>
<Priority>1</Priority>
<Argument><?xml version="1.0" encoding="UTF-8" standalone="yes"?><string>@SetProp("STATUS",@GetStatusId("INTERNAL DESIGN REVIEW"));True</string></Argument>
<ActionCode>APPLY_FORMULA</ActionCode>
<TriggerTaskCode />
<TriggerTaskIsSecondary>false</TriggerTaskIsSecondary>
<TriggerTaskConditionFormula />
</ActionTriplet>
<ActionTriplet>
<Priority>2</Priority>
<Argument><?xml version="1.0" encoding="UTF-8" standalone="yes"?><string>@SetProp("STATUS",@GetStatusId("VALID"));True</string></Argument>
<ActionCode>APPLY_FORMULA</ActionCode>
<TriggerTaskCode />
<TriggerTaskIsSecondary>false</TriggerTaskIsSecondary>
<TriggerTaskConditionFormula />
</ActionTriplet>
</ArrayOfActionTriplet>
答案 0 :(得分:2)
您的代码正在获取XML的全部内容,将其转换为nvarchar
并执行%x%-like-search
,这总是很慢。文字越大,越慢......
为了展示另一种方法,我宣布一个表变量,它用两行来模拟你的表(参见ID)。我搜索@YourCode
中给出的代码:
DECLARE @YourCode NVARCHAR(100)=N'INTERNAL DESIGN REVIEW';
DECLARE @YourTable TABLE(ID INT IDENTITY, actionList XML);
INSERT INTO @YourTable(actionList) VALUES(
'<ArrayOfActionTriplet xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<ActionTriplet>
<Priority>1</Priority>
<Argument><?xml version="1.0" encoding="UTF-8" standalone="yes"?><string>@SetProp("STATUS",@GetStatusId("INTERNAL DESIGN REVIEW"));True</string></Argument>
<ActionCode>APPLY_FORMULA</ActionCode>
<TriggerTaskCode />
<TriggerTaskIsSecondary>false</TriggerTaskIsSecondary>
<TriggerTaskConditionFormula />
</ActionTriplet>
<ActionTriplet>
<Priority>2</Priority>
<Argument><?xml version="1.0" encoding="UTF-8" standalone="yes"?><string>@SetProp("STATUS",@GetStatusId("VALID"));True</string></Argument>
<ActionCode>APPLY_FORMULA</ActionCode>
<TriggerTaskCode />
<TriggerTaskIsSecondary>false</TriggerTaskIsSecondary>
<TriggerTaskConditionFormula />
</ActionTriplet>
</ArrayOfActionTriplet>')
,(
'<ArrayOfActionTriplet xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<ActionTriplet>
<Priority>1</Priority>
<Argument><?xml version="1.0" encoding="UTF-8" standalone="yes"?><string>@SetProp("STATUS",@GetStatusId("INTERNAL DESIGN REVIEW"));True</string></Argument>
<ActionCode>APPLY_FORMULA</ActionCode>
<TriggerTaskCode />
<TriggerTaskIsSecondary>false</TriggerTaskIsSecondary>
<TriggerTaskConditionFormula />
</ActionTriplet>
<ActionTriplet>
<Priority>2</Priority>
<Argument><?xml version="1.0" encoding="UTF-8" standalone="yes"?><string>@SetProp("STATUS",@GetStatusId("VALID"));True</string></Argument>
<ActionCode>APPLY_FORMULA</ActionCode>
<TriggerTaskCode />
<TriggerTaskIsSecondary>false</TriggerTaskIsSecondary>
<TriggerTaskConditionFormula />
</ActionTriplet>
</ArrayOfActionTriplet>');
- 这是查询:您将返回所有Argument
- 元素,此元素中的文字包含GetStatusId("TheCode")
。
SELECT s.ID
,arg.query('.')
FROM @YourTable AS s
CROSS APPLY actionList.nodes('/*:ArrayOfActionTriplet/*:ActionTriplet/*:Argument[fn:contains(.,fn:concat("GetStatusId("",sql:variable("@YourCode"),"")"))]') AS A(arg)
使用此查询,您可以将内部XML从编码形式转换为实际XML并获取完整的字符串可读:
SELECT s.ID
,arg.query('.')
,InnerXml.value('string[1]','nvarchar(max)')
FROM @YourTable AS s
CROSS APPLY actionList.nodes('/*:ArrayOfActionTriplet/*:ActionTriplet/*:Argument[fn:contains(.,fn:concat("GetStatusId("",sql:variable("@YourCode"),"")"))]') AS A(arg)
CROSS APPLY (SELECT CAST(arg.value('.','varchar(max)') AS XML)) AS Casted(InnerXml)
如果你想要的不仅仅是检查,还是有<Argument>
包含你的代码,你可能会这样做:
SELECT s.ID
FROM @YourTable AS s
WHERE actionList.exist('/*:ArrayOfActionTriplet/*:ActionTriplet/*:Argument[fn:contains(.,fn:concat("GetStatusId("",sql:variable("@YourCode"),"")"))]') =1
最终=1
表示:字符串包含在内。使用=0
,您将获得所有行,其中不包含此字符串