Oracle REST POST 请求返回 sys_refcursor

问题描述

我们目前正在使用 Oracle APEX 云免费层对 REST API 进行原型设计。我在 Oracle REST POST 请求中返回 sys_refcursor 时遇到问题。这是详细信息(我是在这里提问的新手,所以我希望格式是可读的:

表格

 CREATE TABLE "WF_PROTOTYPE"."INGREDIENT_TYPES"     
(   "ID" NUMBER(10,0)  NOT NULL ENABLE,"ACCOUNT_ID" NUMBER(10,0) NOT NULL ENABLE,"NAME"  VARCHAR2(100 CHAR) COLLATE "USING_NLS_COMP" NOT NULL ENABLE,"CREATED_AT" TIMESTAMP (6),"UPDATED_AT" TIMESTAMP (6),"DELETED_AT" TIMESTAMP (6),"CREATED_BY" NUMBER(10,0),"UPDATED_BY" NUMBER(10,"DELETED_BY" NUMBER(10,"DESCRIPTION" VARCHAR2(1000 BYTE) COLLATE "USING_NLS_COMP",CONSTRAINT "INGR_TYPE_PK" PRIMARY KEY ("ID"))

触发

create or replace TRIGGER ingredient_types_id_TRIG BEFORE INSERT OR UPDATE ON ingredient_types
FOR EACH ROW
DECLARE 
v_newVal NUMBER(12) := 0;
v_incval NUMBER(12) := 0;
BEGIN
  IF INSERTING AND :new.id IS NULL THEN
    SELECT  ingredient_types_id_SEQ.NEXTVAL INTO v_newVal FROM DUAL;
    -- If this is the first time this table have been inserted into (sequence == 1)
    IF v_newVal = 1 THEN 
      --get the max indentity value from the table
      SELECT NVL(max(id),0) INTO v_newVal FROM ingredient_types;
      v_newVal := v_newVal + 1;
      --set the sequence to that value
      LOOP
           EXIT WHEN v_incval>=v_newVal;
           SELECT ingredient_types_id_SEQ.nextval INTO v_incval FROM dual;
      END LOOP;
    END IF;
   -- assign the value from the sequence to emulate the identity column
   :new.id := v_newVal;
  END IF;
END;

存储过程

create or replace PROCEDURE ingredient_type_POST (
   p_account_id     IN  ingredient_types.account_id%TYPE,p_name           IN  ingredient_types.name%TYPE,p_description    in  ingredient_types.description%type,p_created_by     IN  ingredient_types.created_by%type,p_out_rec        OUT sys_refcursor
)
AS
    new_id ingredient_types.id%type;
BEGIN
   INSERT INTO ingredient_types (account_id,name,DESCRIPTION,created_at,created_by)
   VALUES (p_account_id,p_name,p_description,systimestamp,nvl(p_created_by,2))
   RETURN id INTO new_id;

   OPEN p_out_rec FOR
    SELECT id,account_id,description
    FROM   ingredient_types
    WHERE  ID = new_id;

EXCEPTION
   WHEN OTHERS
   THEN HTP.print(sqlERRM);
END ingredient_type_POST;

订单定义

ORDS.DEFINE_HANDLER(
      p_module_name    => 'wf_api.rest',p_pattern        => 'accounts/:acct_id/ingredient_types',p_method         => 'POST',p_source_type    => 'plsql/block',p_items_per_page =>  0,p_mimes_allowed  => '',p_comments       => 'CREATE an Ingredient Type',p_source         => 
'begin
    INGREDIENT_TYPE_POST(
                p_account_id    => :acct_id,p_name          => :name,p_description   => :description,p_created_by    => :APP_USER,p_rec           => :new_rec);
end;'
      );
  ORDS.DEFINE_ParaMETER(
      p_module_name        => 'wf_api.rest',p_pattern            => 'accounts/:acct_id/ingredient_types',p_method             => 'POST',p_name               => 'rec',p_bind_variable_name => 'new_rec',p_source_type        => 'RESPONSE',p_param_type         => 'RESULTSET',p_access_method      => 'OUT',p_comments           => NULL);      

当我从 sql Developer 工作表 EDITOR 运行 SP 时,填写输入变量我得到一个成功的结果(新记录创建),它在 p_out_rec 参数中返回预期的结果集。但是,当我在 HANDLER 编辑器中运行它并填写适当的变量时,我收到以下错误消息:

Error starting at line : 1 in command -
begin
    INGREDIENT_TYPE_POST(
                p_account_id    => :acct_id,p_rec           => :new_rec);
end;
Error report -
ORA-06550: line 2,column 5:
PLS-00306: wrong number or types of arguments in call to 'INGREDIENT_TYPE_POST'
ORA-06550: line 2,column 5:
PL/sql: Statement ignored
06550. 00000 -  "line %s,column %s:\n%s"
*Cause:    Usually a PL/sql compilation error.
*Action:

我已尝试尽可能地模仿 ThatJeffSmith 的教程 https://www.thatjeffsmith.com/archive/2017/03/parameters-and-binds-for-your-restful-services-resultsets/,但我没有发现我的错在哪里……非常感谢任何见解!!!

解决方法

发现您的代码存在一些问题。

  1. 您没有为表的 ID 列提供值
  2. 您的 refcursor 被填充了一个查询,该查询几乎永远不会 工作,您正在根据 ACCOUNT_ID 值检查 ID
  3. 您将 p_out_rec 称为 p_rec -- 谢谢@andrew!

这是它的工作原理

enter image description here

-- Generated by ORDS REST Data Services 20.4.1.r0131644
-- Schema: HR  Date: Wed Mar 17 05:24:17 2021 
--

BEGIN
  ORDS.ENABLE_SCHEMA(
      p_enabled             => TRUE,p_schema              => 'HR',p_url_mapping_type    => 'BASE_PATH',p_url_mapping_pattern => 'hr',p_auto_rest_auth      => FALSE);
    
  ORDS.DEFINE_MODULE(
      p_module_name    => 'wf_api.rest',p_base_path      => '/wf_api/',p_items_per_page => 25,p_status         => 'PUBLISHED',p_comments       => 'stackoverflow question');

  ORDS.DEFINE_TEMPLATE(
      p_module_name    => 'wf_api.rest',p_pattern        => 'accounts/:acct_id/ingredient_types',p_priority       => 0,p_etag_type      => 'HASH',p_etag_query     => NULL,p_comments       => NULL);

  ORDS.DEFINE_HANDLER(
      p_module_name    => 'wf_api.rest',p_method         => 'POST',p_source_type    => 'plsql/block',p_mimes_allowed  => '',p_comments       => NULL,p_source         => 
'begin
 INGREDIENT_TYPE_POST(
    P_ID             => :id,P_ACCOUNT_ID     => :acct_id,P_NAME           => :name,P_DESCRIPTION    => :description,P_CREATED_BY     => :APP_USER,P_OUT_REC        => :new_rec
  );
END;');

  ORDS.DEFINE_PARAMETER(
      p_module_name        => 'wf_api.rest',p_pattern            => 'accounts/:acct_id/ingredient_types',p_method             => 'POST',p_name               => 'rec',p_bind_variable_name => 'new_rec',p_source_type        => 'RESPONSE',p_param_type         => 'RESULTSET',p_access_method      => 'OUT',p_comments           => NULL);

    
        
COMMIT;

END;

还有 PL/SQL 过程...

create or replace PROCEDURE ingredient_type_POST (
   p_id             IN  ingredient_types.id%TYPE,p_account_id     IN  ingredient_types.account_id%TYPE,p_name           IN  ingredient_types.name%TYPE,p_description    in  ingredient_types.description%type,p_created_by     IN  ingredient_types.created_by%type,p_out_rec        OUT sys_refcursor
)
AS
    new_id ingredient_types.id%type;
BEGIN
   INSERT INTO ingredient_types (id,account_id,name,DESCRIPTION,created_at,created_by)
   VALUES (p_id,p_account_id,p_name,p_description,systimestamp,nvl(p_created_by,2))
   RETURN id INTO new_id;

   OPEN p_out_rec FOR
    SELECT id,description
    FROM   ingredient_types
    WHERE  account_ID = p_account_id;

EXCEPTION
   WHEN OTHERS
   THEN HTP.print(SQLERRM);
END ingredient_type_POST;

和请求 -

curl --request POST \
  --url http://localhost:8080/ords/hr/wf_api/accounts/42/ingredient_types \
  --header 'Content-Type: application/json' \
  --data '{
    "id".         : 55,"name"        : "heyYou","description" : "some words","APP_USER"    : 44
}'