一般来说,从存储过程中选择几个明显的“问题”,只需要考虑两个:
a)存储过程产生的列是不确定的(直到运行时才知道)
b)由于存储过程的不确定性,建立数据库统计和制定高效的查询计划将会出现问题
由于用户经常希望使用此功能,因此随着时间的推移,已经开发了许多解决方法:
http://www.club-oracle.com/threads/select-from-stored-procedure-results.3147/
http://www.sommarskog.se/share_data.html
sql Server特别具有OPENROWSET功能,允许您加入或从几乎任何内容中进行选择:https://msdn.microsoft.com/en-us/library/ms190312.aspx
但是,DBA的安全原因往往很不情愿.
所以对我的问题:虽然有一些明显的问题或性能考虑涉及允许联接或选择存储过程,是否有一些基本的技术原因为什么这种能力不支持RDBMS平台?
编辑:
从初始反馈中可以更清楚一点….是的,您可以从存储过程返回结果集,是的,如果要加入(或选择),则可以使用(表值)函数而不是存储过程from)结果集 – 但是,这与加入/选择存储过程不同.如果您正在完全控制的数据库中工作,那么您可以选择使用TVF.但是,很常见的是,您发现自己在第三方数据库中工作,并且您被迫调用预先存在的存储过程;或者,您常常希望加入系统存储过程,例如:sp_execute_external_script(https://msdn.microsoft.com/en-us/library/mt604368.aspx).
编辑2:
关于Postgresql是否可以做到这一点,答案也不是:Can PostgreSQL perform a join between two SQL Server stored procedures?
解决方法
这是一个“直观的”,有点数据库不可知的解释,因为我相信sql及其许多方言是一个有机成长的语言/概念,因为这是一个基本的“科学”解释.
程序与功能,历史上
我没有真正看到从存储过程中选择的点,但是我受到多年的经验和接受现状的偏见,我当然看到程序和功能之间的区别如何混淆,以及他们希望如何更加多才多艺.特别在sql Server,Sybase或MysqL中,过程可以返回任意数量的结果集/更新计数,尽管这与返回定义良好的类型的函数不同.
将程序视为必要的例程(具有副作用)和函数作为纯粹的例程而没有副作用. SELECT语句本身也是“纯”而没有副作用(除了潜在的锁定效果之外),所以将函数看作可以在SELECT语句中使用的唯一的例程类型是有意义的.
实际上,将函数看作是对行为有很强限制的例程,而允许程序执行任意程序.
4GL与3GL语言
另一种看待这种情况的方法是从sql的角度来看是一个4th generation programming language (4GL).如果4GL在很大程度上受到限制,它只能合理地工作. Common Table Expressions made SQL turing-complete,但sql的声明性仍然阻碍了它从实用的每一天的角度来看是一种通用语言.
存储的程序是规避此限制的一种方式.有时,你想要完整和实用.因此,存储过程需要重视,具有副作用,事务性等.
存储的功能是将一些3GL /程序语言特性引入到更纯粹的4GL世界中的一种聪明的方法,其价格在于禁止其中的副作用(除非您想要打开潘多拉的盒子并具有完全不可预测的SELECT语句).
某些数据库允许其存储过程返回任意数量的结果集/游标的事实是它们允许任意行为(包括副作用)的特征.原则上说,我所说的都不会在存储的函数中阻止这种特定的行为,但如果允许在sql 4GL语言的上下文中这样做,这将是非常不实际和难以管理的.
从而:
程序可以调用程序,任何函数和sql
>“纯”函数可以调用“纯”函数和sql
> sql可以调用“纯”函数和sql
但:
和:
> sql无法调用过程
> sql不能调用“impure”函数
“纯”表值函数的示例:
以下是使用表值的“纯”函数的一些示例:
神谕
CREATE TYPE numbers AS TABLE OF number(10); / CREATE OR REPLACE FUNCTION my_function (a number,b number) RETURN numbers IS BEGIN return numbers(a,b); END my_function; /
接着:
SELECT * FROM TABLE (my_function(1,2))
sql Server
CREATE FUNCTION my_function(@v1 INTEGER,@v2 INTEGER) RETURNS @out_table TABLE ( column_value INTEGER ) AS BEGIN INSERT @out_table VALUES (@v1),(@v2) RETURN END
接着
SELECT * FROM my_function(1,2)
Postgresql的
让我在Postgresql上有一个字.
Postgresql是非常棒的,因此是一个例外.这也很奇怪,大概50%的功能不应该在生产中使用.它只支持“功能”而不是“程序”,但这些功能可以作为任何事情.查看以下内容:
CREATE OR REPLACE FUNCTION wow () RETURNS SETOF INT AS $$ BEGIN CREATE TABLE boom (i INT); RETURN QUERY INSERT INTO boom VALUES (1) RETURNING *; END; $$LANGUAGE plpgsql;
副作用:
>创建表
>插入一条记录
然而:
SELECT * FROM wow();
产量
wow --- 1