如何获取存储过程以输出从 SQL*Plus 中的 select 语句返回的表?

Posted

技术标签:

【中文标题】如何获取存储过程以输出从 SQL*Plus 中的 select 语句返回的表?【英文标题】:How do I get a stored procedure to output the table that gets returned from a select statement in SQL*Plus? 【发布时间】:2017-02-27 20:21:43 【问题描述】:

我想在我的数据库中获取有关用户的信息。

这就是我所拥有的:

表:

create table Users(
userID int CHECK (userID > 0),
email varchar2(30) NOT NULL, 
age varchar2(30) NOT NULL,
numberBookedSoFar int,
primary key(userID)
);

程序:

CREATE or REPLACE PROCEDURE user_info() AS 
BEGIN
SELECT age, COUNT(userid) AS numberofusers,
AVG(numberbookedsofar) AS avgbooked 
FROM users 
GROUP BY age;
END;

但是,什么都没有发生。

【问题讨论】:

那会得到一个编译错误,而不是什么都没有。您使用的是哪个版本的 Oracle? (为什么要使用子查询?) 请更清楚,你有什么来源,你需要实现什么 你的程序运行一个查询,但你没有要求它做更多的事情。 那么,我需要做什么才能输出结果表? 您可以在 Oracle 12c 中执行此操作(注意这需要 12c 客户端):***.com/a/40360471/230471 【参考方案1】:

编辑

据我了解,您需要从存储函数返回表

CREATE TYPE users_obj IS  OBJECT (age varchar2(30), numberofusers int, avgbooked numeric);

CREATE TYPE users_t IS TABLE OF users_obj;

CREATE or REPLACE FUNCTION  user_info  RETURN users_t
IS
      users_table users_t := users_t();
      n INT := 0;
BEGIN
      FOR i IN (SELECT age, COUNT(userid) AS numberofusers, AVG(numberbookedsofar) AS avgbooked  FROM users  GROUP BY age) -- < here is your query
      LOOP
           users_table.EXTEND;
           n := n + 1;
           users_table(n) := users_obj(i.age, i.numberofusers, i.avgbooked);
      END LOOP;
     RETURN users_table;
END;


-- So, now you can call function  which returns result as table
SELECT  *  FROM  TABLE (user_info);

【讨论】:

是的,确实如此。我自己运行了查询,但是当我尝试运行时没有任何反应。【参考方案2】:

我喜欢使用包中定义的类型。这允许我在一个紧凑的命名空间中将类型组合在一起。我不会比其他答案更好,只是不同。这是一个例子:

CREATE OR REPLACE PACKAGE deleteme_pkg
AS
    TYPE example_t IS RECORD
    (
        text         VARCHAR2 (10)
      , textlength   INTEGER
    );

    TYPE example_tt IS TABLE OF example_t;

    FUNCTION sample
        RETURN example_tt
        PIPELINED;
END deleteme_pkg;

CREATE OR REPLACE PACKAGE BODY deleteme_pkg
AS
    -- Very contrived, in practice, the rows will be from a select statement
    FUNCTION sample
        RETURN example_tt
        PIPELINED
    AS
        l_rec   example_t;
    BEGIN
        l_rec.text         := 'This';
        l_rec.textlength   := LENGTH (l_rec.text);
        PIPE ROW (l_rec);
        l_rec.text         := 'is';
        l_rec.textlength   := LENGTH (l_rec.text);
        PIPE ROW (l_rec);
        l_rec.text         := 'a';
        l_rec.textlength   := LENGTH (l_rec.text);
        PIPE ROW (l_rec);
        l_rec.text         := 'test';
        l_rec.textlength   := LENGTH (l_rec.text);
        PIPE ROW (l_rec);
    END sample;
END deleteme_pkg;

-- now select from the package function
select * from table(deleteme_pkg.sample);

【讨论】:

【参考方案3】:

只是上述答案的变体。使用批量收集。希望这会有所帮助。

CREATE OR REPLACE type CUSTOM_OBJ
IS
  object
  (
    AGE        NUMBER,
    USER_ID    NUMBER,
    AVG_BOOKED NUMBER
);

CREATE OR REPLACE TYPE custom_tab
IS
  TABLE OF CUSTOM_OBJ;


CREATE OR REPLACE
  FUNCTION USER_INFO
    RETURN CUSTOM_TAB
  AS
    tab custom_tab;
  BEGIN
    SELECT custom_obj(age,numberofusers,AVGBOOKED) BULK COLLECT
    INTO tab
    FROM
      (SELECT age,
        COUNT(userid)          AS numberofusers,
        AVG(NUMBERBOOKEDSOFAR) AS AVGBOOKED
      FROM users
      );
    RETURN TAB;
  END;

【讨论】:

以上是关于如何获取存储过程以输出从 SQL*Plus 中的 select 语句返回的表?的主要内容,如果未能解决你的问题,请参考以下文章

PL/SQL 打印出存储过程返回的引用游标

如何从 JDBC 中的存储过程中获取输出

如何从命令行调用 Oracle SQL 过程?

如何从存储过程的表中的列中获取输出参数

如何使用 simpleJdbcCall 在存储过程中获取 XML 输出参数

如何使用sqlplus在shell中存储存储过程返回的多个输出列