Sql server 递归过程中@vars、#表和#表的可用性

Sql server 递归过程中@vars、#表和#表的可用性,sql-server,tsql,recursion,stored-procedures,Sql Server,Tsql,Recursion,Stored Procedures,如果我调用一个递归调用自身的存储过程,我想知道@vars、#表和#表是否有不冲突的实例副本。我猜@vars和#tables是可以的,但是##应该会产生问题 我认为问题进一步扩展为:当sp调用自身时,它是否创建新会话? 所有递归都在同一批中 每个存储过程(递归)在批处理中都有自己的作用域 简单地说 连接有多个批次(一个接一个) 批处理有许多作用域(每个代码单元,如存储的过程、函数等) 所以 @变量的作用域是每个递归的代码单元=Ok #表的作用域为connection=NOT Ok,对递归可

如果我调用一个递归调用自身的存储过程,我想知道@vars、#表和#表是否有不冲突的实例副本。我猜@vars和#tables是可以的,但是##应该会产生问题

我认为问题进一步扩展为:当sp调用自身时,它是否创建新会话?

  • 所有递归都在同一批中
  • 每个存储过程(递归)在批处理中都有自己的作用域
简单地说

  • 连接有多个批次(一个接一个)
  • 批处理有许多作用域(每个代码单元,如存储的过程、函数等)
所以

  • @变量的作用域是每个递归的代码单元=Ok
  • #表的作用域为connection=NOT Ok,对递归可见
  • ##表的作用域为所有usingconnections=notok,对递归可见

    • 不,它没有。变量的作用域为一个级别(因此嵌套调用不可见),#临时表的作用域为会话,#临时表的作用域为全局。在T-SQL中甚至无法创建新会话(即使
      EXEC
      创建新批,但不能创建新会话)。嗯,您可以动态创建一个计划作业(或者在本地服务器上使用
      OPENROWSET
      ),但这是作弊

      不过,要小心在嵌套的存储过程中创建临时表:如果不小心,就会遇到麻烦。具体来说:

      在存储过程或触发器中创建的本地临时表 可以与以前创建的临时表同名 调用存储过程或触发器。但是,如果一个查询 引用一个临时表和两个具有相同属性的临时表 此时名称已存在,但未定义查询的表 决定反对。嵌套存储过程还可以创建临时 与由创建的临时表同名的表 调用它的存储过程。但是,需要进行修改才能解决 对于在嵌套过程中创建的表,该表必须 具有与表相同的结构和列名 在调用过程中创建

      这意味着“明显”的情况是,在嵌套的每个步骤中都创建“相同”的临时表,正如您所期望的那样:每个嵌套调用都有其“自己的”表,并且看不到父表。但是,如果不在嵌套调用中创建表,则会得到父表,如果创建一个具有不同结构的表(无论出于何种原因),当SQL Server检测到这组奇怪的情况时,实际上可能会出现编译错误


      因此,您既可以使用临时表作为跨调用保持状态的方法,也可以通过“重新创建”临时表来具体地不这样做,但要让事情保持正常,这取决于您。

      我的问题是,为什么您首先需要递归过程?引用如何支持您的声明“每个嵌套调用都有自己的”“table并且不会看到父表”?@philipxy:最后一句话意味着“如果表具有相同的结构和相同的列名”,那么“修改将解析到嵌套过程中创建的表”“,事实上,本段后面的文档中演示了这种情况。我承认文本可能会更清晰。(还有,我只是简单地测试了它,尽管你不能总是认为实际测试的结果在t-SQL中是100%可复制的,这是事实。)最后一句话并不意味着这一点。它表示要访问最里面的表,必须有一个匹配的标题。引文中没有说明什么是足够的。最后一句话的作者可能试图说这已经足够了,但他们写的不是这样说的。如果足够的话,就会与前面第二句话中所说的相矛盾。@philipxy:对不起,我没有写。请随意在页面上提出问题,或者用这些问题写出你自己的答案(或问题!)。从文本、观察到的行为以及实际有用的内容中,我可以非常自信地推断,如果存储过程递归地调用自己,并且在每次执行中,在创建某个特定的临时表之前不访问该临时表,那么这些表的作用域将以预期的方式嵌套。存在其他结果的更复杂情况,但与问题不直接相关。