如何在SQL函数中重写SQL游标?

如何在SQL函数中重写SQL游标?,sql,sql-server,tsql,Sql,Sql Server,Tsql,我必须支持现有的sql函数,该函数根据多个表中的项目计算学生活动。这个函数经常被调用!它用于日历显示、输出时间表,当学生参与活动时,他们将签入由函数确定的活动。(我也在使用VB.Net和ASP.Net。)当然这个函数有4个游标,所以性能非常差,我做了一个sql分析器。出于测试目的,我注释掉了函数部分,并使用#temp tables和while循环重写了它们。现在尝试作为函数安装和测试时,我收到了可怕的错误消息“无法从函数中访问临时表”。哦,还有更多好消息:这个函数有18个打印页面,非常庞大。(不

我必须支持现有的sql函数,该函数根据多个表中的项目计算学生活动。这个函数经常被调用!它用于日历显示、输出时间表,当学生参与活动时,他们将签入由函数确定的活动。(我也在使用VB.Net和ASP.Net。)当然这个函数有4个游标,所以性能非常差,我做了一个sql分析器。出于测试目的,我注释掉了函数部分,并使用#temp tables和while循环重写了它们。现在尝试作为函数安装和测试时,我收到了可怕的错误消息“无法从函数中访问临时表”。哦,还有更多好消息:这个函数有18个打印页面,非常庞大。(不是我对函数的定义。)我现在真的无法重写整个过程,那么我的选择是什么?

如果不知道函数试图解决什么问题以及问题背后的模式的任何细节,很难给出答案。作为一般规则,假设基础模型相对可靠,在SQL中使用游标、
循环和条件逻辑(
if-then-else
)是一种代码气味,表明作者未能以基于集合的方式构建问题;相反,她是按程序进行的

通常,当有人从命令式编程(C/C++、Cobol、VB等)的背景中接触SQL时,您会看到这一点。它们用于一次处理一个项目的集合(集合)

在该函数中的某个地方,几乎可以肯定是一个[可能很复杂]的select语句,其中包含试图退出的连接、虚拟表和嵌套的子select,但如果不知道实际的细节,就不可能给出任何明确的指导

FWIW,大约我唯一一次发现有必要使用
循环或游标是在我需要手动生成键值或针对结果集中的每一行分别执行存储过程时。这通常是由于系统设计或实现中的其他一些失败

SQL的关键是集合论和关系代数。SQL本质上是一种描述性语言,它有着优雅的数学基础,可以让你用集合运算来描述你想要的东西。试图强加过程语义(正如您所注意到的)会导致性能低下和不必要的复杂性。

这里有两种方法:

  • 尝试使用四表联接将问题重新表述为简单SQL。您可能需要一些“CASE”语句来实现“Function”中的一些逻辑
  • 检查函数并查找可在更新时计算和存储的数据元素。也就是说,将一些计算负担转移到更新/插入过程中,并存储结果,以使查询过程更加容易

  • 你能将临时表转换成表变量吗?如果你能使用表变量,你应该能够使用
    函数
    ,或者,如果可行的话,将函数转换成存储过程。这可能有助于替换一些CUSOR(并缩短代码)好主意。桌上的变量起作用了。还可以查看网站。谢谢你的帮助!另外,您可能需要考虑的是将函数更改为存储过程。UDF速度慢且效率低&当然不是为18页代码设计的,在这里使用SPs可能更有意义,不管实际代码做什么。