Skip to Main Content

SQL & PL/SQL

Announcement

For appeals, questions and feedback about Oracle Forums, please email oracle-forums-moderators_us@oracle.com. Technical questions should be asked in the appropriate category. Thank you!

How to generate JSON format data from table

user525840Jun 7 2022

I am planning to use json format data via REST API to Oracle JET web component. However the data is not coming as per expected format.
Expected format is:
{
"january": [
{
"date": 1,
"value": 39
},
{
"date": 2,
"value": 42
},
{
"date": 3,
"value": 42
}
],
"february": [
{
"date": 1,
"value": 36
},
{
"date": 2,
"value": 34
},
{
"date": 3,
"value": 26
},
{
"date": 4,
"value": 43
}
],
"march": [
{
"date": 1,
"value": 31
},
{
"date": 2,
"value": 39
},
{
"date": 3,
"value": 37
},
{
"date": 4,
"value": 45
}
]
};

Sample table and data preparation:
CREATE TABLE PATIENT_APPOINTMENTS
(APPOINTMENT_ID NUMBER,
APPOINTMENT_COMPANY_ID NUMBER,
APPOINTMENT_CLINIC_ID NUMBER,
APPOINTMENT_PATIENT_ID NUMBER,
APPOINTMENT_DATE DATE,
APPOINTMENT_TIME DATE,
APPOINTMENT_PATIENT_COMPLAINT VARCHAR2(100)
);

INSERT INTO PATIENT_APPOINTMENTS(APPOINTMENT_ID, APPOINTMENT_COMPANY_ID, APPOINTMENT_CLINIC_ID, APPOINTMENT_PATIENT_ID,
APPOINTMENT_DATE, APPOINTMENT_TIME, APPOINTMENT_PATIENT_COMPLAINT)
VALUES(1,1,1,1,SYSDATE, SYSDATE, 'TOOTH PAIN');

INSERT INTO PATIENT_APPOINTMENTS(APPOINTMENT_ID, APPOINTMENT_COMPANY_ID, APPOINTMENT_CLINIC_ID, APPOINTMENT_PATIENT_ID,
APPOINTMENT_DATE, APPOINTMENT_TIME, APPOINTMENT_PATIENT_COMPLAINT)
VALUES(2,1,1,1,SYSDATE+2, SYSDATE+2, 'TOOTH PAIN');

INSERT INTO PATIENT_APPOINTMENTS(APPOINTMENT_ID, APPOINTMENT_COMPANY_ID, APPOINTMENT_CLINIC_ID, APPOINTMENT_PATIENT_ID,
APPOINTMENT_DATE, APPOINTMENT_TIME, APPOINTMENT_PATIENT_COMPLAINT)
VALUES(3,1,1,1,SYSDATE+3, SYSDATE+3, 'TOOTH PAIN');

My SQL Query is:
WITH CAL_DATA AS (
SELECT FIRST_DATE + LEVEL -1 AS CAL_DATES
FROM (
SELECT NEXT_DAY ( TRUNC(SYSDATE,'MONTH') -15 , 'SUNDAY') AS FIRST_DATE,
NEXT_DAY ( LAST_DAY(SYSDATE) -1 , 'SATURDAY') AS LAST_DATE
FROM DUAL
)
CONNECT BY LEVEL <= LAST_DATE + 1 - FIRST_DATE
), GET_JSON AS (
SELECT TO_CHAR(C.CAL_DATES,'MON') CAL_MON, C.CAL_DATES, A.*
FROM CAL_DATA C
LEFT JOIN PATIENT_APPOINTMENTS A
ON ( TRUNC(C.CAL_DATES) = TRUNC(A.APPOINTMENT_DATE) )
)
--SELECT * FROM GET_JSON
SELECT JSON_OBJECT( cal_mon
VALUE
JSON_ARRAY(JSON_OBJECT(KEY 'date:' VALUE TO_CHAR(CAL_DATES,'DD-MON-YYYY'), KEY 'val:' VALUE NVL(APPOINTMENT_ID,0)))
) Final_output
FROM GET_JSON
--GROUP BY CAL_MON
ORDER BY CAL_DATES;

Current output (subset of output):
{"MAY":[{"date:":"30-MAY-2022","val:":0}]}
{"MAY":[{"date:":"31-MAY-2022","val:":0}]}
{"JUN":[{"date:":"01-JUN-2022","val:":0}]}
{"JUN":[{"date:":"02-JUN-2022","val:":0}]}
{"JUN":[{"date:":"03-JUN-2022","val:":0}]}
{"JUN":[{"date:":"04-JUN-2022","val:":0}]}
{"JUN":[{"date:":"05-JUN-2022","val:":0}]}
{"JUN":[{"date:":"06-JUN-2022","val:":0}]}
{"JUN":[{"date:":"07-JUN-2022","val:":1}]}
{"JUN":[{"date:":"08-JUN-2022","val:":0}]}
{"JUN":[{"date:":"09-JUN-2022","val:":2}]}
{"JUN":[{"date:":"10-JUN-2022","val:":3}]}

I have to display output which is grouped based on month and its corresponding array values as json_ojbect.

Can you please help with query correction?

This post has been answered by Solomon Yakobson on Jun 7 2022
Jump to Answer

Comments

odie_63
PS: I don't want to use an hardcoding
Why?

Do you have such a scenario that you don't know the procedure name you're trying to compile?

Edited by: odie_63 on 11 janv. 2013 10:45
padders
Simple answer is you can't - without generating some additional metadata for the package.

One way to generate the metadata would appear to be PL/Scope in 11g but I haven't actually tried that to see how it pans out.
odie_63
There's $$PLSQL_UNIT compiler directive but it doesn't reference subprograms in a package, only the package itself :
SQL> create or replace package mypck is
  2    procedure myprc;
  3  end;
  4  /
 
Package created
 
SQL> 
SQL> create or replace package body mypck is
  2    procedure myprc is
  3    begin
  4      dbms_output.put_line('I''m in '||$$PLSQL_UNIT);
  5    end;
  6  end;
  7  /
 
Package body created
 
SQL> exec mypck.myprc;
 
I'm in MYPCK
 
PL/SQL procedure successfully completed
 
bencol
This might help you understand the problem:
http://tkyte.blogspot.co.uk/2009/10/httpasktomoraclecomtkytewhocalledme.html

Buit I usually hardcode the proc name into a variable and use that for logging.
unknown-7404
You've posted enough to know that you need to provide your 4 digit Oracle version (result of SELECT * FROM V$VERSION).
>
is it possible to obtain a called procedure/function name within package?

For a measuring and tracing purpose, I would like to store an info at the beginning of each procedure/function in package with timestamp + additional details if needed.
>
I usually use this method

1. Create a SQL type for logging information
2. Put the package name into a constant in the package spec
3. Add a line to each procedure/function for the name.

Sample package spec
	/******************************************************************************
	 * Constants and package variables
	 ******************************************************************************/
		gc_pk_name			CONSTANT VARCHAR2(30) := 'PK_TEST';
Sample procedure code in package
	 PROCEDURE P_TEST_INIT
	 IS
	   c_proc_name CONSTANT VARCHAR2(80)  := 'P_TEST_INIT';
	   v_log_info  TYPE_LOG_INFO := TYPE_LOG_INFO(gc_pk_name, c_proc_name); -- create the log type instance

	 BEGIN
		NULL; -- code goes here
	 EXCEPTION
	 WHEN ??? THEN
		v_log_info.log_code := SQLCODE;  -- add info to the log type
		v_log_info.log_message := SQLERRM;
		v_log_info.log_time    := SYSDATE;
		pk_log.p_log_error(v_log_info);
                                raise;
	 END P_PK_TEST_INIT;
Sample SQL type
DROP TYPE TYPE_LOG_INFO;

CREATE OR REPLACE TYPE TYPE_LOG_INFO AUTHID DEFINER AS OBJECT (
/* *****************************************************************************
 *  NAME:      TYPE_LOG_INFO
 *  PURPOSE:   Holds info used by PK_LOG package to log errors.
 *
 *             Using a TYPE instance keeps the procedures and functions
 *             independent of the logging mechanism.
 *
 *             If new logging features are needed a SUB TYPE can be derived
 *             from this base type to add the new functionality without
 *             breaking any existing code.
 *
 *  REVISIONS:
 *  Ver        Date        Author           Description
 *
 *   1.00      mm/dd/yyyy  me               Initial Version.
 ******************************************************************************/
    PACKAGE_NAME  VARCHAR2(80),
    PROC_NAME     VARCHAR2(80),
    STEP_NUMBER   NUMBER,
    LOG_LEVEL   VARCHAR2(10),
    LOG_CODE    NUMBER,
    LOG_MESSAGE VARCHAR2(1024),
    LOG_TIME    TIMESTAMP,
    CONSTRUCTOR FUNCTION type_log_info (p_package_name IN VARCHAR2 DEFAULT 'Uninitialized',
                                        p_proc_name IN VARCHAR2 DEFAULT 'Uninitialized',
                                        p_step_number IN NUMBER DEFAULT 1,
                                        p_LOG_level IN VARCHAR2 DEFAULT 'Uninit',
                                        p_LOG_code IN NUMBER DEFAULT -1,
                                        p_LOG_message IN VARCHAR2 DEFAULT 'Uninitialized',
                                        p_LOG_time IN DATE DEFAULT SYSDATE)
                RETURN SELF AS RESULT
  ) NOT FINAL;
/

DROP TYPE BODY TYPE_LOG_INFO;

CREATE OR REPLACE TYPE BODY TYPE_LOG_INFO IS
    CONSTRUCTOR FUNCTION type_log_info (p_package_name IN VARCHAR2 DEFAULT 'Uninitialized',
                                        p_proc_name IN VARCHAR2 DEFAULT 'Uninitialized',
                                        p_step_number IN NUMBER DEFAULT 1,
                                        p_LOG_level IN VARCHAR2 DEFAULT 'Uninit',
                                        p_LOG_code IN NUMBER DEFAULT -1,
                                        p_LOG_message IN VARCHAR2 DEFAULT 'Uninitialized',
                                        p_LOG_time IN DATE DEFAULT SYSDATE)
     RETURN SELF AS RESULT IS
    BEGIN
      self.package_name  := p_package_name;
      self.proc_name     := p_proc_name;
      self.step_number   := p_step_number;
      self.LOG_level   := p_LOG_level;
      self.LOG_code    := p_LOG_code;
      self.LOG_message := p_LOG_message;
      self.LOG_time    := p_LOG_time;
      RETURN;
    END;
END;
/
SHO ERR
Edited by: rp0428 on Jan 11, 2013 10:35 AM after 1st cup of coffee ;)
odie_63
rp0428 wrote:
You would want the $$PLSQL_UNIT directive.
And as shown in my post, this doesn't apply to subprograms in a package, which seems to be precisely what OP is after.
unknown-7404
Thanks - brain f*** - didn't even see your post somehow. I update my post with the old method.
1 - 7

Post Details

Added on Jun 7 2022
5 comments
780 views