【发布时间】:2014-11-12 15:26:46
【问题描述】:
首先,我的背景是 SQL Server。使用 CTE(公用表表达式)是一件轻而易举的事,将其转换为带有变量的存储过程不需要对 SQL 的结构进行任何更改,只需将输入的值替换为变量名。
然而,在 Oracle PL/SQL 中,情况就完全不同了。我的 CTE 可以像直接 SQL 一样正常工作,但是一旦我尝试将它们包装为 PL/SQL,我就会遇到很多问题。据我了解,SELECT 现在需要一个 INTO,它只保存一条记录的结果。但是,我想要多个值的整个记录集。
如果我在这里遗漏了明显的内容,我深表歉意。我认为我 99% 的问题是我需要进行的范式转变。
举个例子:
注意:我在这里大大简化了 SQL。我知道下面的示例可以在单个 SQL 语句中完成。实际的 SQL 要复杂得多。这是我在这里寻找的基础知识。
WITH A as (SELECT * FROM EMPLOYEES WHERE DEPARTMENT = 200),
B as (SELECT * FROM A WHERE EMPLOYEE_START_DATE > date '2014-02-01'),
C as (SELECT * FROM B WHERE EMPLOYEE_TYPE = 'SALARY')
SELECT 'COUNTS' as Total,
(SELECT COUNT(*) FROM A) as 'DEPT_TOTAL',
(SELECT COUNT(*) FROM B) as 'NEW_EMPLOYEES',
(SELECT COUNT(*) FROM C) as 'NEW_SALARIED'
FROM A
WHERE rowcount = 1;
现在,如果我想使用传入或在顶部预定义的变量将其制成 PL/SQL,那么声明变量、将值弹出并将我的硬编码值更改为变量并不是一件简单的事情并运行它。 注意:我知道我可以简单地将硬编码的值更改为变量,例如 :Department、:StartDate 和 :Type,但我再次将示例过于简单化了。
我正在努力解决三个问题:
1) 使用带有声明变量的 PL/SQL 重写它的最佳方法是什么?现在,CTE 必须进入某些内容。但后来我一次处理一行,而不是整张桌子。所以 CTE 'A' 一次是一行,而 CTE B 只会看到一行,而不是 A 的所有数据结果,等等。我知道我很可能不得不使用 CURSORS 来遍历记录,不知何故,这似乎过于复杂了。
2) 输出现在必须使用 DBMS_OUTPUT。对于多条记录,我将不得不使用带有 FETCH 的 CURSOR(或 FOR...LOOP)。是的?
3) 在速度和使用的资源方面,此 SQL 与直接 SQL 相比是否存在很大的性能问题?
再次感谢您,如果我在这里遗漏了一些非常明显的东西,我深表歉意!
【问题讨论】:
-
请浏览例如转至stackoverflow.com/tags/plsql/info 并开始阅读 Steven Feuerstein 的 PL/SQL 101 系列(您可以在标签 wiki 中找到链接)。
标签: oracle plsql common-table-expression