Oracle REST POST 请求返回问题 sys_refcursor
Issue with Oracle REST POST request returning sys_refcursor
我们目前正在使用 Oracle APEX 云免费层对 REST API 进行原型设计。我在 Oracle REST POST 请求中返回 sys_refcursor 时遇到问题。这是细节(我是新来的,所以我希望格式是可读的:
TABLE
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,0), "DELETED_BY" NUMBER(10,0),
"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, name, 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 开发人员工作表编辑器的 SP 填写输入变量时,我得到了一个成功的结果(创建了新记录)并且它 returns 了预期的结果集在 p_out_rec 参数中。但是,当我 运行 在 HANDLER 编辑器中填写适当的变量时,我收到以下错误消息:
Error starting at line : 1 in command -
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;
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/,但我没有看出我的错误所在……非常感谢任何见解!!!
发现您的代码存在一些问题。
- 您没有为 table 的 ID 列提供值
- 你的 refcursor 正在填充一个几乎永远不会的查询
工作,您正在根据 ACCOUNT_ID 值
检查 ID
- 您将 p_out_rec 称为 p_rec -- 谢谢@andrew!
这是它的工作原理
-- 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 => 'Whosebug 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_pattern => 'accounts/:acct_id/ingredient_types',
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, account_id, name, 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
}'
我们目前正在使用 Oracle APEX 云免费层对 REST API 进行原型设计。我在 Oracle REST POST 请求中返回 sys_refcursor 时遇到问题。这是细节(我是新来的,所以我希望格式是可读的:
TABLE
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,0), "DELETED_BY" NUMBER(10,0),
"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, name, 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 开发人员工作表编辑器的 SP 填写输入变量时,我得到了一个成功的结果(创建了新记录)并且它 returns 了预期的结果集在 p_out_rec 参数中。但是,当我 运行 在 HANDLER 编辑器中填写适当的变量时,我收到以下错误消息:
Error starting at line : 1 in command -
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;
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/,但我没有看出我的错误所在……非常感谢任何见解!!!
发现您的代码存在一些问题。
- 您没有为 table 的 ID 列提供值
- 你的 refcursor 正在填充一个几乎永远不会的查询 工作,您正在根据 ACCOUNT_ID 值 检查 ID
- 您将 p_out_rec 称为 p_rec -- 谢谢@andrew!
这是它的工作原理
-- 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 => 'Whosebug 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_pattern => 'accounts/:acct_id/ingredient_types',
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, account_id, name, 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
}'