Reputation: 99
I'm trying to build one PL/SQL stored procedure to insert update delete data into the table using below procedure but it is failing with the error Error Code:
-40573 - ORA-40573: Invalid use of PL/SQL JSON object type.
Please help me
CREATE OR REPLACE PACKAGE XX_MESSAGE_PKG1
IS
PROCEDURE generic_service( p_request IN json_object_t,
p_response OUT json_object_t );
END XX_MESSAGE_PKG1;
CREATE OR REPLACE PACKAGE BODY XX_MESSAGE_PKG1
IS
PROCEDURE generic_service ( p_request IN json_object_t,
p_response OUT json_object_t )
AS
l_po_header_id NUMBER;
l_resp_obj JSON_OBJECT_T := JSON_OBJECT_T();
BEGIN
-- Processing Header based on operation
CASE LOWER(p_request.get_string('operation'))
WHEN 'add' THEN
INSERT INTO PO_HEADER (PO_NUMBER, VENDOR_NAME, ORDER_DATE, TOTAL_AMOUNT, STATUS, CREATED_BY, CREATED_DATE)
VALUES (
p_request.get_string('poNumber'),
p_request.get_string('vendorName'),
TO_DATE(p_request.get_string('orderDate'), 'YYYY-MM-DD'),
p_request.get_number('totalAmount'),
p_request.get_string('status'),
p_request.get_string('createdBy'),
SYSDATE
)
RETURNING PO_HEADER_ID INTO l_po_header_id;
WHEN 'update' THEN
UPDATE PO_HEADER
SET VENDOR_NAME = p_request.get_string('vendorName'),
ORDER_DATE = TO_DATE(p_request.get_string('orderDate'), 'YYYY-MM-DD'),
TOTAL_AMOUNT = p_request.get_number('totalAmount'),
STATUS = p_request.get_string('status'),
UPDATED_BY = p_request.get_string('createdBy'),
UPDATED_DATE = SYSDATE
WHERE PO_NUMBER = p_request.get_string('poNumber')
RETURNING PO_HEADER_ID INTO l_po_header_id;
WHEN 'remove' THEN
DELETE FROM PO_HEADER WHERE PO_NUMBER = p_request.get_string('poNumber');
l_resp_obj.put('status', 'SUCCESS');
l_resp_obj.put('message', 'PO_HEADER deleted');
p_response := l_resp_obj;
RETURN;
ELSE
RAISE_APPLICATION_ERROR(-20001, 'Invalid operation for PO_HEADER');
END CASE;
-- Processing PO Lines
FOR i IN 0 .. p_request.get_array('poLines').get_size - 1 LOOP
DECLARE
l_line_obj JSON_OBJECT_T := TREAT(p_request.get_array('poLines').get(i) AS JSON_OBJECT_T);
BEGIN
CASE LOWER(l_line_obj.get_string('operation'))
WHEN 'add' THEN
INSERT INTO PO_LINES (PO_HEADER_ID, LINE_NUMBER, ITEM_CODE, ITEM_DESCRIPTION,
QUANTITY, UNIT_PRICE, CREATED_BY, CREATED_DATE)
VALUES (
l_po_header_id,
l_line_obj.get_number('lineNumber'),
l_line_obj.get_string('itemCode'),
l_line_obj.get_string('itemDescription'),
l_line_obj.get_number('quantity'),
l_line_obj.get_number('unitPrice'),
l_line_obj.get_string('createdBy'),
SYSDATE
);
WHEN 'update' THEN
UPDATE PO_LINES
SET ITEM_CODE = l_line_obj.get_string('itemCode'),
ITEM_DESCRIPTION = l_line_obj.get_string('itemDescription'),
QUANTITY = l_line_obj.get_number('quantity'),
UNIT_PRICE = l_line_obj.get_number('unitPrice'),
UPDATED_BY = l_line_obj.get_string('createdBy'),
UPDATED_DATE = SYSDATE
WHERE PO_HEADER_ID = l_po_header_id
AND LINE_NUMBER = l_line_obj.get_number('lineNumber');
WHEN 'remove' THEN
DELETE FROM PO_LINES
WHERE PO_HEADER_ID = l_po_header_id
AND LINE_NUMBER = l_line_obj.get_number('lineNumber');
ELSE
RAISE_APPLICATION_ERROR(-20002, 'Invalid operation for PO_LINES');
END CASE;
END;
END LOOP;
-- Success response
l_resp_obj.put('status', 'SUCCESS');
l_resp_obj.put('po_header_id', l_po_header_id);
p_response := l_resp_obj;
EXCEPTION
WHEN OTHERS THEN
l_resp_obj.put('status', 'ERROR');
l_resp_obj.put('description', 'Error Code: ' || SQLCODE || ' - ' || SQLERRM);
p_response := l_resp_obj;
END generic_service;
END XX_MESSAGE_PKG1;
input will be like below which is passed to to this procedure:
{
"poNumber": "PO1004",
"vendorName": "Tech Solutions",
"orderDate": "2025-03-01",
"totalAmount": 800.75,
"status": "APPROVED",
"createdBy": "User3",
"operation": "add",
"poLines": [
{
"operation": "Add",
"lineNumber": 1,
"itemCode": "ITEM005",
"itemDescription": "Keyboard",
"quantity": 4,
"unitPrice": 50.00,
"createdBy": "User3"
},
{
"operation": "Remove",
"lineNumber": 2,
"itemCode": "ITEM006",
"itemDescription": "Mouse Pad",
"quantity": 10,
"unitPrice": 8.50,
"createdBy": "User3"
},
{
"operation": "update",
"lineNumber": 2,
"itemCode": "ITEM006",
"itemDescription": "Mouse Pad",
"quantity": 10,
"unitPrice": 8.50,
"createdBy": "User3"
}
]
}
my tables as below:
-- Creating the PO_HEADER table
CREATE TABLE PO_HEADER (
PO_HEADER_ID NUMBER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
PO_NUMBER VARCHAR2(50) UNIQUE,
VENDOR_NAME VARCHAR2(100),
ORDER_DATE DATE DEFAULT SYSDATE,
TOTAL_AMOUNT NUMBER(15,2) DEFAULT 0,
STATUS VARCHAR2(20) DEFAULT 'DRAFT',
CREATED_BY VARCHAR2(50),
CREATED_DATE DATE DEFAULT SYSDATE,
UPDATED_BY VARCHAR2(50),
UPDATED_DATE DATE
);
-- Creating the PO_LINES table without NOT NULL constraints
CREATE TABLE PO_LINES (
PO_LINE_ID NUMBER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
PO_HEADER_ID NUMBER, -- No FK constraint
LINE_NUMBER NUMBER, -- Sequential line number
ITEM_CODE VARCHAR2(50),
ITEM_DESCRIPTION VARCHAR2(200),
QUANTITY NUMBER(10,2) DEFAULT 1 CHECK (QUANTITY > 0),
UNIT_PRICE NUMBER(10,2) DEFAULT 0 CHECK (UNIT_PRICE >= 0),
LINE_TOTAL NUMBER(15,2) GENERATED ALWAYS AS (QUANTITY * UNIT_PRICE) VIRTUAL,
CREATED_BY VARCHAR2(50),
CREATED_DATE DATE DEFAULT SYSDATE,
UPDATED_BY VARCHAR2(50),
UPDATED_DATE DATE
);
-- Creating indexes for performance
CREATE INDEX IDX_PO_HEADER_DATE ON PO_HEADER (ORDER_DATE);
CREATE INDEX IDX_PO_LINES_HEADER_ID ON PO_LINES (PO_HEADER_ID);
Upvotes: 0
Views: 39
Reputation: 168450
OTHERS
exception as it hides the stack trace. Instead, catch specific named exceptions that you are expecting and, if there are unexpected exceptions, let the code fail and use the stack trace to help you to debug the code.JSON_OBJECT_T
is a PL/SQL object and cannot be used in an SQL scope.To solve it, either:
JSON_TABLE
in SQL to parse the JSON string.For example:
CREATE OR REPLACE PACKAGE BODY XX_MESSAGE_PKG1
IS
PROCEDURE generic_service (
p_request IN json_object_t,
p_response OUT json_object_t
)
AS
l_po_header_id PO_HEADER.PO_HEADER_ID%TYPE;
l_po_number PO_HEADER.PO_NUMBER%TYPE;
l_po_vendorName PO_HEADER.VENDOR_NAME%TYPE;
BEGIN
-- Processing Header based on operation
p_response := JSON_OBJECT_T();
l_po_number := p_request.get_string('poNumber');
l_po_vendorName := p_request.get_string('vendorName');
CASE LOWER(p_request.get_string('operation'))
WHEN 'add' THEN
INSERT INTO PO_HEADER (
PO_NUMBER,
VENDOR_NAME
-- etc.
) VALUES (
l_po_number,
l_po_vendorName
-- etc.
)
RETURNING PO_HEADER_ID INTO l_po_header_id;
END CASE;
-- Success response
p_response.put('status', 'SUCCESS');
p_response.put('po_header_id', l_po_header_id);
END generic_service;
END XX_MESSAGE_PKG1;
/
or
CREATE OR REPLACE PACKAGE XX_MESSAGE_PKG1
IS
PROCEDURE generic_service(
p_request IN CLOB,
p_response OUT CLOB
);
END XX_MESSAGE_PKG1;
/
CREATE OR REPLACE PACKAGE BODY XX_MESSAGE_PKG1
IS
PROCEDURE generic_service (
p_request IN CLOB,
p_response OUT CLOB
)
AS
l_operation VARCHAR2(10);
l_po_header_id PO_HEADER.PO_HEADER_ID%TYPE;
l_po_number PO_HEADER.PO_NUMBER%TYPE;
l_po_vendorName PO_HEADER.VENDOR_NAME%TYPE;
BEGIN
-- Processing Header based on operation
SELECT operation,
poNumber,
vendorName
INTO l_operation,
l_po_number,
l_po_vendorName
FROM JSON_TABLE(
p_request,
'$'
COLUMNS (
operation VARCHAR2(10) PATH '$.operation',
poNumber VARCHAR2(50) PATH '$.poNumber',
vendorName VARCHAR2(100) PATH '$.vendorName'
)
);
CASE LOWER(l_operation)
WHEN 'add' THEN
INSERT INTO PO_HEADER (
PO_NUMBER,
VENDOR_NAME
-- etc.
) VALUES (
l_po_number,
l_po_vendorName
-- etc.
)
RETURNING PO_HEADER_ID INTO l_po_header_id;
END CASE;
-- Success response
SELECT JSON_SERIALIZE(
JSON_OBJECT(
KEY 'status' VALUE 'SUCCESS',
KEY 'po_header_id' VALUE l_po_header_id
)
)
INTO p_response
FROM DUAL;
END generic_service;
END XX_MESSAGE_PKG1;
/
Upvotes: 0