微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

sql – 为什么从存储过程中选择不支持关系数据库?

众所周知,您无法从Oracle或sql Server(以及大部分其他主流的RDBMS产品)中的存储过程执行SELECT.

一般来说,从存储过程中选择几个明显的“问题”,只需要考虑两个:

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?

解决方法

TL; DR:您可以从(表值)函数中选择,或从Postgresql中的任何类型的函数中进行选择.但不是存储过程.

这是一个“直观的”,有点数据库不可知的解释,因为我相信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

原文地址:https://www.jb51.cc/mssql/76074.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐