【问题标题】:Returning a custom type in a PL/SQL Stored Procedure在 PL/SQL 存储过程中返回自定义类型
【发布时间】:2018-08-04 19:23:37
【问题描述】:

我的目标是在 PL/SQL 中编写一个函数或一个存储过程,它返回一个表供用户立即查看。我有几十个历史表,想给自己一个跨所有表的单个用户历史的快照。但我遇到了一个错误,我不确定这是否是最好的方法。

我目前的方法是将表格中的所有信息收集到自定义“汇总表”类型中,然后将其返回。但是,当使用我的自定义“userTable”作为我的输出参数的类型时,我遇到了错误

CREATE OR REPLACE PROCEDURE GetUserSnapShot(myid in Number, numdays in Number,
 myTable out userTable)
AS 
BEGIN
  /*maybe insert a row into the table here?*/
  myTable := null;
END;


DECLARE
   TYPE userChanges IS RECORD (
       historyTable VARCHAR(100),
       historyId NUMBER,
       changeType VARCHAR(6),
       changeDate DATE
     );
  TYPE userTable IS TABLE OF userChanges INDEX BY BINARY_INTEGER;
  myTable userTable;
 BEGIN
   GetUserSnapShot(5, 7, myTable);
END;

这是我在尝试运行时遇到的错误:必须声明标识符“USERTABLE”,这让我感到困惑,因为我已经声明了 userTable

【问题讨论】:

  • 为什么不能简单地返回选择查询的结果?
  • 编译器需要能够查找userTable 的定义才能编译过程。它不能只是在您桌面上的某个脚本中。

标签: sql oracle stored-procedures plsql oracle12c


【解决方案1】:

您已在匿名块中定义了类型 USERTABLE,但该过程不知道匿名块中的内容,因此看不到类型。

我建议您最好使用一个包,这样您就可以将记录类型、表类型和过程放在包中。一个例子是:

CREATE PACKAGE MY_PACKAGE AS  -- define the package spec
  TYPE userChanges IS RECORD
    (
    historyTable VARCHAR(100),
    historyId NUMBER,
    changeType VARCHAR(6),
    changeDate DATE
    );

  TYPE userTable IS TABLE OF userChanges
    INDEX BY BINARY_INTEGER;

  PROCEDURE GetUserSnapShot(myid    in     Number,
                            numdays in     Number,
                            myTable in out userTable);
END MY_PACKAGE;

CREATE PACKAGE BODY MY_PACKAGE AS  -- define the package body
  PROCEDURE GetUserSnapShot(myid    in     Number,
                            numdays in     Number,
                            myTable in out userTable)
  AS
    rec  userChanges; 
  BEGIN
    rec.historyTable := 'SOMEWHERE';
    rec.historyId    := 1;
    rec.changeType   := 'ABCDEF';
    rec.changeDate   := SYSDATE;

    myTable(1) := rec;
  END;
END MY_PACKAGE;

现在您可以引用打包过程并在您的匿名块中键入:

DECLARE
  MY_PACKAGE.myTable userTable;
BEGIN
  MY_PACKAGE.GetUserSnapShot(5, 7, myTable);
END;

祝你好运。

【讨论】:

  • 嗯,当我按照发布的方式一次运行所有这些时,我仍然得到:“ORA-06550:第 2 行,第 11 列:PLS-00201:必须声明标识符 'USERTABLE' ORA-06550:行2,第 11 列:PL/SQL:忽略项目 ORA-06550:第 4 行,第 25 列:PLS-00320:此表达式的类型声明不完整或格式错误 ORA-06550:第 4 行,第 3 列:PL/SQL : 语句被忽略”
  • @jdmneon - 在匿名块中使用包名。 (写:)声明myTable my_package.userTable;开始 my_package.GetUserSnapshot(5, 7, mytable) ;结束;
  • @Bob Jarvis - 我真的很喜欢你在这个解决方案中使用包的方式!另一个小问题:包体编译时出现错误。在规范中,对于 GetUserSnapShot,参数列表中有“myTable out userTable”,而在正文中,您将“myTable in out userTable”。 (因此,我得到:“PLS-00323:子程序或游标 'GETUSERSNAPSHOT' 在包规范中声明,并且必须在包主体中定义”。通过在包规范代码中添加单词“out”轻松修改)跨度>
  • 谢谢!我让它工作了!使用您和 stefan 的建议,我有没有办法轻松选择该表中存在的结果?像 DECLARE MY_PACKAGE.myTable userTable; BEGIN SELECT * FROM MY_PACKAGE.GetUserSnapShot(5, 7, myTable);结束;
  • @jdmneon -(在匿名块中)使用游标循环并从表中选择*(mytable),类似于第一个示例中的代码@oracle-base.com/articles/12c/…
猜你喜欢
  • 2018-12-17
  • 1970-01-01
  • 2019-05-07
  • 2018-01-31
  • 2020-04-24
  • 1970-01-01
  • 2018-08-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多