I have a query which fetches json format data from a column. i want to fetch the data of json by passing a field_name dynamically from the column.
for example
SELECT SUBJECT_MARKS
FROM STUDENT
WHERE STUDENT_ID = 101
result is:
{
"English": "70",
"Hindi": "80",
"Maths": "90",
"Science": "90",
"Social": "85"
}
If I want to get the particular subject marks, then the query is:
SELECT JSON_VALUE(SUBJECT_MARKS,'$.Maths')
FROM STUDENT
WHERE STUDENT_ID = 101
Now the result is:
90
Now my requirement is to get the SUBJECT MARKS dynamically while giving the subject name as parameter in the query
SELECT JSON_VALUE(SUBJECT_MARKS,:pSubjectMarks)
FROM STUDENT
WHERE STUDENT_ID = 101
while execute the query when we give the :pSubjectMarks
as '$.Science'
then it is throwing the error message
ORA-40454: path expression not a literal 40454. 00000 - "path expression not a literal" *Cause: The provided path expression was not a literal (a constant). *Action: Provide a constant path expression. Error at Line: 29 Column: 45
Can anyone help me to find the solution for the query Thanks in advance
You could build the subject you want to get info from into an EXECUTE IMMEDIATE
statement. Since all of your subjects are simple strings, you can use the DBMS_ASSERT
package to validate the input of the p_subject_name
parameter to prevent any SQL injection from happening.
Below is an example on how to build the procedure.
CREATE TABLE students
AS
SELECT 101 AS student_id,
EMPTY_CLOB ()
|| '{ "English": "70", "Hindi": "80", "Maths": "90", "Science": "90", "Social": "85" }' AS subject_marks
FROM DUAL;
DECLARE
PROCEDURE print_subject_score (p_student_id students.student_id%TYPE, p_subject_name VARCHAR2)
IS
l_sql VARCHAR2 (1000);
l_score VARCHAR2 (5);
BEGIN
l_sql :=
'select json_value(subject_marks, ''$.'
|| DBMS_ASSERT.SIMPLE_SQL_NAME (p_subject_name)
|| ''') from students where student_id = :p_student_id';
EXECUTE IMMEDIATE l_sql
INTO l_score
USING p_student_id;
DBMS_OUTPUT.put_line (l_score);
EXCEPTION
WHEN NO_DATA_FOUND
THEN
--Student ID does not exist
NULL;
END;
BEGIN
print_subject_score (p_student_id => 101, p_subject_name => 'English');
print_subject_score (p_student_id => 101, p_subject_name => 'Test');
print_subject_score (p_student_id => 102, p_subject_name => 'Maths');
END;
/