Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/72.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
跟踪SQL Server中XML节点的流_Sql_Sql Server_Xml - Fatal编程技术网

跟踪SQL Server中XML节点的流

跟踪SQL Server中XML节点的流,sql,sql-server,xml,Sql,Sql Server,Xml,我在SQL Server中有一个进程表,如下所示: workflowXML列具有如下值: 样本1: <process> <Event type="start" id="StartEvent_1"> <outgoing>SequenceFlow_0h5l5vu</outgoing> </Event> <Flow type="s

我在SQL Server中有一个
进程
表,如下所示:

workflowXML
列具有如下值:

样本1:

 <process>
      <Event type="start" id="StartEvent_1">
         <outgoing>SequenceFlow_0h5l5vu</outgoing>
      </Event>
      <Flow type="sequence"
            id="SequenceFlow_0h5l5vu"
            sourceRef="StartEvent_1"
            targetRef="Task_1qc93ha"/>
      <Flow type="sequence"
            id="SequenceFlow_120gi3p"
            sourceRef="Task_1qc93ha"
            targetRef="Task_0x1pjee"/>
      <Task type="service" id="Task_1qc93ha">
         <incoming>SequenceFlow_0h5l5vu</incoming>
         <outgoing>SequenceFlow_120gi3p</outgoing>
      </Task>
      <Task type="user" id="Task_0x1pjee">
         <incoming>SequenceFlow_120gi3p</incoming>
      </Task>
</process>
<process id="Process_1" isExecutable="false">
      <Event type="start" id="StartEvent_142xowk">
         <outgoing>SequenceFlow_03yocm5</outgoing>
      </Event>
      <Flow type="sequence"
            id="SequenceFlow_03yocm5"
            sourceRef="StartEvent_142xowk"
            targetRef="Task_12g1q69"/>
      <Task type="user" id="Task_0x1pjee">
             <incoming>SequenceFlow_120gi3p</incoming>
       </Task>
      <Task type="user" id="Task_12g1q69">
         <incoming>SequenceFlow_03yocm5</incoming>
      </Task>
</process>
如果有人能解释这个问题的解决方案,那将非常有帮助


谢谢。

我希望我没有弄错:

从type=“start”开始,沿着层次结构走下去,其中out数据是下一个节点的Id。此行深度未定义,应以type=“user”的节点结束

您的第二个示例有两个type=“user”的任务,但其中只有一个被引用为链上更高节点中的out数据

我的示例将使用额外的
EXISTS
子句过滤第二个

第一个CTE DerivedTable包含一个查询,您也可以使用它。它将以表格形式显示全部信息

第二个CTE是递归的,从start开始并沿链向下遍历。列秩是链的顺序

第三个CTE添加了反向排名,因为您似乎只对最后一项感兴趣。您可以通过
获取此信息,其中RevRank=1

DECLARE @process TABLE(ID INT IDENTITY, workflowXML XML);
INSERT INTO @process(workflowXML) VALUES
('<process>
      <Event type="start" id="StartEvent_1">
         <outgoing>SequenceFlow_0h5l5vu</outgoing>
      </Event>
      <Flow type="sequence"
            id="SequenceFlow_0h5l5vu"
            sourceRef="StartEvent_1"
            targetRef="Task_1qc93ha"/>
      <Flow type="sequence"
            id="SequenceFlow_120gi3p"
            sourceRef="Task_1qc93ha"
            targetRef="Task_0x1pjee"/>
      <Task type="service" id="Task_1qc93ha">
         <incoming>SequenceFlow_0h5l5vu</incoming>
         <outgoing>SequenceFlow_120gi3p</outgoing>
      </Task>
      <Task type="user" id="Task_0x1pjee">
         <incoming>SequenceFlow_120gi3p</incoming>
      </Task>
</process>')
,('<process id="Process_1" isExecutable="false">
      <Event type="start" id="StartEvent_142xowk">
         <outgoing>SequenceFlow_03yocm5</outgoing>
      </Event>
      <Flow type="sequence"
            id="SequenceFlow_03yocm5"
            sourceRef="StartEvent_142xowk"
            targetRef="Task_12g1q69"/>
      <Task type="user" id="Task_0x1pjee">
             <incoming>SequenceFlow_120gi3p</incoming>
       </Task>
      <Task type="user" id="Task_12g1q69">
         <incoming>SequenceFlow_03yocm5</incoming>
      </Task>
</process>');
结果(您的预期输出为RevRank=1):

更新:你的评论 我使用您评论中的XML测试了我的查询:

INSERT INTO @process(workflowXML) VALUES
('<process>
  <Event type="start" id="e1">
    <outgoing>s1</outgoing>
  </Event>
  <Flow type="sequence" id="s1" sourceRef="e1" targetRef="t1" />
  <Flow type="sequence" id="s3" sourceRef="t1" targetRef="t2" />
  <Task type="user" id="t3">
    <incoming>s2</incoming>
  </Task>
  <Task type="user" id="t1">
    <incoming>s1</incoming>
    <outgoing>s3</outgoing>
  </Task>
  <Flow type="sequence" id="s2" sourceRef="t2" targetRef="t3" />
  <Task type="service" id="t2">
    <incoming>s3</incoming>
    <outgoing>s2</outgoing>
  </Task>
</process>');
如果我正确理解了逻辑,我的查询就可以正常工作:

  • 事件id=e1指向s1
  • 流s1指向t1
  • 任务t1指向s3
  • 流s3指向t2
  • 任务t2指向s2
  • 流s2指向t3
  • 任务t3结束了
唯一不同的是,任务t1已经是type=“user”了。如果您想要(在任何情况下)排名最高的用户任务,您可以去掉
ReverseRank
-CTE,并将最后的
选择设置为like

SELECT t.* 
FROM recCTE AS t
WHERE t.[Rank]<=ISNULL((SELECT MIN(x.[Rank]) FROM recCTE AS x WHERE x.tblID=t.tblID AND x.[Type]='user' AND x.[Name]='Task'),999)
ORDER BY t.tblID,t.[Rank]
选择t.*
从记录为t

其中t.[Rank]我用这个查询解决了这个问题。如果有更好的问题,很乐意指出

--================== @tempProcess(result)=========================
declare @tempProcess table 
(
 ID int,
 FirstTaskID nvarchar(max)
 )
--===============================================================
declare @currentType nvarchar(max)
declare @FirstUserTaskID nvarchar(max)
declare @outgoing nvarchar(max)
declare @elementID nvarchar(max)
--================================================================
declare @ID int
declare @WorkflowXML xml
declare cur CURSOR LOCAL for
    select ID, WorkflowXML from Process 
open cur

fetch next from cur into @ID, @WorkflowXML

while @@FETCH_STATUS = 0 BEGIN    

set @currentType = '$$$$$'--defult value
set @elementID = '$$$$$'--defult value

select @outgoing = 
(
    select p.WorkflowXML.value('(process/Event[@type=''start'']/outgoing)[1]','nvarchar(max)')
    from Process as p
    where ID = @ID
)

--======================  while(Tracking flow) ========================
while (@currentType != 'user')
begin
    ------- Get target element with Flow Id (outgoing)----------------- 
    select @elementID = (
        select t.c.value('@id','nvarchar(max)')
        from Process as p
            cross apply p.WorkflowXML.nodes('process/*') AS t(c)
        where ID = @ID
        and 
        t.c.value('incoming[1]','nvarchar(max)') = @outgoing
    )
    -------------- Get Type of current element ------------------------ 
    select @currentType = 
    (
    select t.c.value('@type','nvarchar(max)')
        from Process as p
            cross apply p.WorkflowXML.nodes('process/*') AS t(c)
        where ID = @ID
        and 
        t.c.value('@id','nvarchar(max)') = @elementID
    )
    -------------- Get outgoing of current element ---------------------    
    select @outgoing = 
    (
     select t.c.value('(outgoing)[1]','nvarchar(max)')
        from Process as p
            cross apply p.WorkflowXML.nodes('process/*') AS t(c)
        where ID = @ID
        and 
        t.c.value('@id','nvarchar(max)') = @elementID
    )
    ---------------------------------------------------------------
end
--=========================  End while ========================   
if(@elementID != '$$$$$')
    begin
        set @FirstUserTaskID =  @elementID      
        -- Insert to @tempProcess
        INSERT INTO @tempProcess
        SELECT @ID,@FirstUserTaskID
    end

    --select @FirstUserTaskID
    fetch next from cur into @ID,@WorkflowXML
END

select * from @tempProcess

close cur
deallocate cur

您不想将数据存储在适当的表中而不是XML中吗?@EvaldasBuinauskas否,我需要以XML格式存储数据。根据所使用的方法,XML已经有了检索重复节点(
'/'
)的方法或在水平列中返回特定重复节点的方法(
'
),非常感谢您的回答,我贴出了答案。请看这个。@AliSoltani你试过我的方法吗?你的问题-如果它返回你需要的-是可以的,但是一个程序性的方法。对于SQL,建议始终遵循基于集合的路径。。。我的查询将返回整个流链,并且应该比您的查询快得多。您的方法的主要问题是,您一次又一次地从XML中提取一段数据,而我的方法是一次读取所有数据<代码>光标
,而
-如果可能,应该避免循环。。。我建议尝试一下我的方法,并决定什么对你更有利……我测试你的查询。我认为这样更好。但有一个问题。有时,节点中会有几个传入和传出节点。在这种情况下,您的代码是否正常工作?@AliSoltani请尝试一下。。。递归方法应该是一个完整的树。但是我不知道你的数据我已经用这个查询再次测试了你的查询。结果不正确。
INSERT INTO @process(workflowXML) VALUES
('<process>
  <Event type="start" id="e1">
    <outgoing>s1</outgoing>
  </Event>
  <Flow type="sequence" id="s1" sourceRef="e1" targetRef="t1" />
  <Flow type="sequence" id="s3" sourceRef="t1" targetRef="t2" />
  <Task type="user" id="t3">
    <incoming>s2</incoming>
  </Task>
  <Task type="user" id="t1">
    <incoming>s1</incoming>
    <outgoing>s3</outgoing>
  </Task>
  <Flow type="sequence" id="s2" sourceRef="t2" targetRef="t3" />
  <Task type="service" id="t2">
    <incoming>s3</incoming>
    <outgoing>s2</outgoing>
  </Task>
</process>');
+-------+-------+----------+----+------+------+------+---------+
| tblID | Name  | Type     | Id | In   | Out  | Rank | RevRank |
+-------+-------+----------+----+------+------+------+---------+
| 1     | Event | start    | e1 | NULL | s1   | 1    | 7       |
+-------+-------+----------+----+------+------+------+---------+
| 1     | Flow  | sequence | s1 | e1   | t1   | 2    | 6       |
+-------+-------+----------+----+------+------+------+---------+
| 1     | Task  | user     | t1 | s1   | s3   | 3    | 5       |
+-------+-------+----------+----+------+------+------+---------+
| 1     | Flow  | sequence | s3 | t1   | t2   | 4    | 4       |
+-------+-------+----------+----+------+------+------+---------+
| 1     | Task  | service  | t2 | s3   | s2   | 5    | 3       |
+-------+-------+----------+----+------+------+------+---------+
| 1     | Flow  | sequence | s2 | t2   | t3   | 6    | 2       |
+-------+-------+----------+----+------+------+------+---------+
| 1     | Task  | user     | t3 | s2   | NULL | 7    | 1       |
+-------+-------+----------+----+------+------+------+---------+
SELECT t.* 
FROM recCTE AS t
WHERE t.[Rank]<=ISNULL((SELECT MIN(x.[Rank]) FROM recCTE AS x WHERE x.tblID=t.tblID AND x.[Type]='user' AND x.[Name]='Task'),999)
ORDER BY t.tblID,t.[Rank]
--================== @tempProcess(result)=========================
declare @tempProcess table 
(
 ID int,
 FirstTaskID nvarchar(max)
 )
--===============================================================
declare @currentType nvarchar(max)
declare @FirstUserTaskID nvarchar(max)
declare @outgoing nvarchar(max)
declare @elementID nvarchar(max)
--================================================================
declare @ID int
declare @WorkflowXML xml
declare cur CURSOR LOCAL for
    select ID, WorkflowXML from Process 
open cur

fetch next from cur into @ID, @WorkflowXML

while @@FETCH_STATUS = 0 BEGIN    

set @currentType = '$$$$$'--defult value
set @elementID = '$$$$$'--defult value

select @outgoing = 
(
    select p.WorkflowXML.value('(process/Event[@type=''start'']/outgoing)[1]','nvarchar(max)')
    from Process as p
    where ID = @ID
)

--======================  while(Tracking flow) ========================
while (@currentType != 'user')
begin
    ------- Get target element with Flow Id (outgoing)----------------- 
    select @elementID = (
        select t.c.value('@id','nvarchar(max)')
        from Process as p
            cross apply p.WorkflowXML.nodes('process/*') AS t(c)
        where ID = @ID
        and 
        t.c.value('incoming[1]','nvarchar(max)') = @outgoing
    )
    -------------- Get Type of current element ------------------------ 
    select @currentType = 
    (
    select t.c.value('@type','nvarchar(max)')
        from Process as p
            cross apply p.WorkflowXML.nodes('process/*') AS t(c)
        where ID = @ID
        and 
        t.c.value('@id','nvarchar(max)') = @elementID
    )
    -------------- Get outgoing of current element ---------------------    
    select @outgoing = 
    (
     select t.c.value('(outgoing)[1]','nvarchar(max)')
        from Process as p
            cross apply p.WorkflowXML.nodes('process/*') AS t(c)
        where ID = @ID
        and 
        t.c.value('@id','nvarchar(max)') = @elementID
    )
    ---------------------------------------------------------------
end
--=========================  End while ========================   
if(@elementID != '$$$$$')
    begin
        set @FirstUserTaskID =  @elementID      
        -- Insert to @tempProcess
        INSERT INTO @tempProcess
        SELECT @ID,@FirstUserTaskID
    end

    --select @FirstUserTaskID
    fetch next from cur into @ID,@WorkflowXML
END

select * from @tempProcess

close cur
deallocate cur