在包 oracle 中创建存储过程

Posted

技术标签:

【中文标题】在包 oracle 中创建存储过程【英文标题】:Create a stored procedure in a package oracle 【发布时间】:2017-08-30 14:42:50 【问题描述】:

我在 Oracle 中创建了以下包:

CREATE OR REPLACE PACKAGE PackageName AS 

TYPE general_item
IS
  RECORD
  (
    item_no item_t.item_no%TYPE ,
    item_type item_t.item_type%TYPE,
    item_state item_t.item_state%TYPE,
    item_name item_t.item_name%TYPE,
    prodname_no item_t.prodname_no%TYPE,
    prod_name item_t.prod_name%TYPE,
    prodname_no2 item_t.prodname_no2%TYPE,
    prod_name2 item_t.prod_name2%TYPE,
    prodtype_no item_t.prodtype_no%TYPE,
    prodtype_name item_t.prodtype_name%TYPE,
    designer_no item_t.designer_no%TYPE,
    designer_name item_t.designer_name%TYPE,
    req_assembly item_t.req_assembly%TYPE,
    unit_name item_t.unit_name%TYPE,
    valid_designer item_t.valid_designer%TYPE,
    sale_start_date item_t.sale_start_date%TYPE,
    sale_end_date item_t.sale_end_date%TYPE,
    short_material_text item_t.short_material_text%TYPE,
    imeas_ref_imp item_t.imeas_ref_imp%TYPE,
    imeas_ref_met item_t.imeas_ref_met%TYPE,
    valid_design_text item_t.valid_design_text%TYPE,
    pe_no item_t.pe_no%TYPE,
    hfb_no item_t.hfb_no%TYPE,
    hfb_name item_t.hfb_name%TYPE,
    pra_no item_t.pra_no%TYPE,
    pra_name item_t.pra_name%TYPE,
    pa_no item_t.pa_no%TYPE,
    pa_name item_t.pa_name%TYPE,
    rec_sales_price item_t.rec_sales_price%TYPE,
    currency_code item_t.currency_code%TYPE,
    base_item_no item_cty_spec_t.item_no%TYPE, --YB added 2014-05-01
    comclass_name item_comclass_t.comclass_name%TYPE); --YB added 2014-05-01


         PROCEDURE general_get_item(
        p_item_no   IN item_t.item_no%TYPE,
        p_item_type IN item_t.item_type%TYPE,
        p_item OUT general_item);


END PackageName; 

这是我正在尝试创建的程序:

create or replace PACKAGE BODY PackageName
AS
PROCEDURE general_get_item(
    p_item_no   IN item_t.item_no%TYPE,
    p_item_type IN item_t.item_type%TYPE,
    p_item OUT general_item)
IS
BEGIN
  OPEN p_item FOR SELECT it.item_no, it.item_type, it.item_state, it.item_name, it.prodname_no , it.prod_name, it.prodname_no2, it.prod_name2, it.prodtype_no, it.prodtype_name, it.designer_no, it.designer_name, it.req_assembly, it.unit_name, it.valid_designer, it.sale_start_date, it.sale_end_date, it.short_material_text, it.imeas_ref_imp, it.imeas_ref_met, it.valid_design_text, it.pe_no, it.hfb_no, it.hfb_name, it.pra_no, it.pra_name, it.pa_no, it.pa_name, it.rec_sales_price, it.currency_code, icst.item_no as base_item_no, ict.comclass_name 
  FROM item_t it, item_cty_spec_t icst, 
  (SELECT item_no, item_type, comclass_name FROM item_comclass_t 
  WHERE valid_from < SYSDATE AND valid_to >= SYSDATE) ict
  WHERE it.item_no = icst.item_no_cty_spec (+) AND it.item_type = icst.item_type_cty_spec (+)  
  AND it.item_no = ict.item_no (+) AND it.item_type = ict.item_type (+)
  AND it.item_no = p_item_no 
  AND it.item_type = p_item_type;
END general_get_item;
END PackageName; 

当我尝试创建过程时,我收到以下消息:

错误(8,3):PL/SQL:SQL 语句被忽略错误(8,8):PLS-00456:项目 'P_ITEM' 不是游标

我不熟悉 Oracle 中的包和过程。

【问题讨论】:

错误信息很明显:general_item类型。您不能打开一个类型,也不能为该类型赋值。请解释一下您要使用 tis 代码解决什么问题? 如果我不得不猜测您要做什么,您希望将该 select 语句中的值加载到记录类型中。如果是这种情况,请查看 PL/SQL 中的 INTO 子句。 【参考方案1】:

您无法在 TYPE RECORD 上打开光标。它必须是CURSOR 类型。所以,只需替换整个语句 -

TYPE general_item
IS
RECORD
  (
    item_no item_t.item_no%TYPE ,
    item_type item_t.item_type%TYPE,
    item_state i
    .....


    .....
    comclass_name item_comclass_t.comclass_name%TYPE);

TYPE general_item IS REF CURSOR;

【讨论】:

【参考方案2】:

您无法将游标(可能是多行)提取到 TYPE。 没有表结构很难想象这个字段是什么类型。 无论如何,如果光标返回一行,更简单的方法是使用 item_t%ROWTYPE。

【讨论】:

【参考方案3】:

如果要在 Oracle 中返回结果,则不需要声明游标。 Oracle 已经将它作为 SYS_REFCURSOR 代表您。

所以你的代码可能看起来像 -

CREATE OR REPLACE PACKAGE PackageName AS
PROCEDURE general_get_item(
        p_item_no   IN item_t.item_no%TYPE,
        p_item_type IN item_t.item_type%TYPE,
        p_item OUT SYS_REFCURSOR);
END PackageName;

那么你的包体可能看起来像 -

create or replace PACKAGE BODY PackageName
AS
 PROCEDURE general_get_item(
     p_item_no   IN item_t.item_no%TYPE,
     p_item_type IN item_t.item_type%TYPE,
     p_item OUT SYS_REFCURSOR)
 IS
 BEGIN
  OPEN p_item FOR
                 SELECT it.item_no
                       ,it.item_type
                       ,it.item_state
                       ,it.item_name
                       ,it.prodname_no
                       ,it.prod_name
                       ,it.prodname_no2
                       ,it.prod_name2
                       ,it.prodtype_no
                       ,it.prodtype_name
                       ,it.designer_no
                       ,it.designer_name
                       ,it.req_assembly
                       ,it.unit_name
                       ,it.valid_designer
                       ,it.sale_start_date
                       ,it.sale_end_date
                       ,it.short_material_text
                       ,it.imeas_ref_imp
                       ,it.imeas_ref_met
                       ,it.valid_design_text
                       ,it.pe_no
                       ,it.hfb_no
                       ,it.hfb_name
                       ,it.pra_no
                       ,it.pra_name
                       ,it.pa_no
                       ,it.pa_name
                       ,it.rec_sales_price
                       ,it.currency_code
                       ,icst.item_no as base_item_no
                       ,ict.comclass_name 
  FROM item_t it
  LEFT JOIN item_cty_spec_t icst ON it.item_no = icst.item_no_cty_spec
                                 AND it.item_type = icst.item_type_cty_spec
  LEFT JOIN (SELECT item_no
                   ,item_type
                   ,comclass_name
             FROM item_comclass_t 
             WHERE valid_from < SYSDATE AND valid_to >= SYSDATE) ict ON it.item_no = ict.item_no
                                                                     AND it.item_type = ict.item_type
  WHERE it.item_no = p_item_no 
  AND it.item_type = p_item_type;
 END general_get_item;
END PackageName;

还始终使用正确的显式连接语法而不是 ANSI-92 语法。

【讨论】:

以上是关于在包 oracle 中创建存储过程的主要内容,如果未能解决你的问题,请参考以下文章

无法使用 oracle 存储过程在水晶报表 2013 中创建报表

在oracle存储过程中创建暂时表

在 Oracle -17110 中创建存储过程 - 警告:执行完成并出现警告

oracle 怎么在存储过程中创建一个临时表,在里面插入数据,再查找这个临时表的所有数据,最后drop这个表。

如何在存储过程中创建视图

在oracle中创建带参存储过程,传进去的参数可以为空么?在存储过程中要如何判断传进来的值是不是为空。