【发布时间】:2010-10-30 10:40:28
【问题描述】:
基本上我想要在我的存储过程中返回一个表列表,将这个列表存储在一个变量中;我需要遍历列表中的每个项目以递归调用此存储过程。最后,我需要一个由这个递归构建的整体 listOfTables。 任何帮助将不胜感激
【问题讨论】:
-
你能提供一个查询和/或输出的例子吗?
标签: tsql variables recursion list
基本上我想要在我的存储过程中返回一个表列表,将这个列表存储在一个变量中;我需要遍历列表中的每个项目以递归调用此存储过程。最后,我需要一个由这个递归构建的整体 listOfTables。 任何帮助将不胜感激
【问题讨论】:
标签: tsql variables recursion list
如果您使用的是 SQL2005 或更高版本,您应该查看Common Table Expressions(不确定它们是否可以帮助您解决特定情况,但它是大多数递归查询的重要替代方案)。递归过程的嵌套深度不能超过 32 层,而且不是很优雅。
【讨论】:
你可以使用CTE的:
WITH q (column1, column2) (
SELECT *
FROM table
UNION ALL
SELECT *
FROM table
JOIN q
ON …
)
SELECT *
FROM q
但是,有不同的限制:您不能使用聚合、分析函数、TOP 子句等。
【讨论】:
你是在递归之后还是只是在所有表中循环?如果您使用的是 Sql Server 2005 并且想要遍历所有表,您可以在 SP 中使用表变量,请尝试以下几行:
declare @TableList as table (
ID int identity (1,1),
TableName varchar(500)
)
insert into @TableList (TableName)
select name
from sys.tables
declare @count int
declare @limit int
declare @TableName varchar(500)
set @count = 1
select @limit = max(ID) from @TableList
while @count <= @limit
begin
select @TableName = TableName from @TableList where ID = @count
print @TableName --replace with call to SP
set @count = @count + 1
end
将 print @TableName 替换为对 SP 的调用,如果您不希望它在数据库中的每个表上运行,则将查询 select name from sys.tables 更改为仅返回您之后的表
【讨论】:
CTE 很可能会满足您的要求。
如果您确实必须使用存储过程而不是查询,那么您所要做的就是遍历表列表,然后您可以使用您选择的代码来遍历表列表并调用该过程。并且宏已经在我输入大声笑时发布了如何做到这一点。正如 Mehrdad 已经告诉您的,SQL Server 允许的嵌套调用级别的数量是有限的,而且相当浅。从您的解释中我不相信您需要递归调用,它看起来更像是对列表的简单迭代,但如果您确实需要递归,请记住 CS 101 类:any recursive algorithm can be transformed into a non-recursive one by using a loop iteration and a stack。
【讨论】:
存储过程非常有用。但是。
我最近不得不在一个严重依赖存储过程的系统上工作。这是一场噩梦。一半的业务逻辑使用一种语言(在本例中为 Java),另一半在数据库中的存储过程中。更糟糕的是,一半的应用程序处于源代码控制之下,而另一半是由于永久丢失而导致的数据库崩溃(糟糕的备份过程)。另外,我拥有的所有用于扫描、分析和维护源代码的可爱小工具都无法使用数据库中的源代码。
我并不是天生就反对存储过程,但是哦,它们怎么会被滥用。当您需要对来自多个来源的数据执行规则时,存储过程非常适合,并且没有更好的方法可以将繁重的记录访问从网络服务器(并转移到 DBMS 服务器上)卸载。但在大多数情况下,我宁愿使用视图而不是存储过程和业务逻辑的应用程序编程语言。我知道这会让一些事情变得更复杂一些。但它可以让生活变得更轻松。
【讨论】: