У меня есть запрос, который извлекает данные формата json из столбца. я хочу получить данные json, динамически передавая field_name из столбца.
Например
SELECT SUBJECT_MARKS
FROM STUDENT
WHERE STUDENT_ID = 101
результат:
{
"English": "70",
"Hindi": "80",
"Maths": "90",
"Science": "90",
"Social": "85"
}
Если я хочу получить конкретные предметные оценки, то запрос будет таким:
SELECT JSON_VALUE(SUBJECT_MARKS,'$.Maths')
FROM STUDENT
WHERE STUDENT_ID = 101
Теперь результат:
90
Теперь мое требование состоит в том, чтобы динамически получать ТЕМАТИЧЕСКИЕ МАРКИ, указывая имя субъекта в качестве параметра в запросе.
SELECT JSON_VALUE(SUBJECT_MARKS,:pSubjectMarks)
FROM STUDENT
WHERE STUDENT_ID = 101
при выполнении запроса, когда мы даем :pSubjectMarks как '$.Science'
то выдает сообщение об ошибке
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
Может ли кто-нибудь помочь мне найти решение для запроса заранее спасибо
Опубликованная вами ошибка не может появиться в Oracle 11g и, более того, в древнем 10g, как указано выше. Пожалуйста, отредактируйте теги версии Oracle.





Начиная с Oracle 12 (когда была добавлена поддержка функций JSON), вы можете внести в белый список все возможные параметры в выражении CASE, используя:
SELECT CASE :pSubjectMarks
WHEN 'English' THEN JSON_VALUE(SUBJECT_MARKS,'$.English')
WHEN 'Hindi' THEN JSON_VALUE(SUBJECT_MARKS,'$.Hindi')
WHEN 'Maths' THEN JSON_VALUE(SUBJECT_MARKS,'$.Maths')
WHEN 'Science' THEN JSON_VALUE(SUBJECT_MARKS,'$.Science')
WHEN 'Social' THEN JSON_VALUE(SUBJECT_MARKS,'$.Social')
END as subject_marks
FROM STUDENT s
или:
SELECT CASE :pSubjectMarks
WHEN 'English' THEN english
WHEN 'Hindi' THEN hindi
WHEN 'Maths' THEN maths
WHEN 'Science' THEN science
WHEN 'Social' THEN social
END as subject_marks
FROM STUDENT s
CROSS APPLY JSON_TABLE(
s.subject_marks,
'$'
COLUMNS (
ENGLISH NUMBER PATH '$.English',
HINDI NUMBER PATH '$.Hindi',
MATHS NUMBER PATH '$.Maths',
SCIENCE NUMBER PATH '$.Science',
SOCIAL NUMBER PATH '$.Social'
)
) j
WHERE STUDENT_ID = 101;
дб <> рабочий пример здесь
Вы можете превратить тему, из которой хотите получить информацию, в утверждение EXECUTE IMMEDIATE. Поскольку все ваши темы представляют собой простые строки, вы можете использовать пакет DBMS_ASSERT для проверки ввода параметра p_subject_name, чтобы предотвратить внедрение SQL.
Ниже приведен пример построения процедуры.
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;
/
Поскольку у вас есть доступ к функции JSON_VALUE, ваша версия Oracle не ниже 12.1. Эта версия также обеспечивает доступ к локальным объявлениям PL/SQL в запросах SQL, где у вас есть полный динамический доступ к ключам JSON.
Таким образом, вы можете использовать для этого тип данных JSON_OBJECT_T. Как видите, путь передается как значение столбца (выражение, а не литерал), и вы можете использовать переменную связывания вместо выражения.
with function get_mark( p_marks in varchar2, p_subj in varchar2 ) return number as json JSON_OBJECT_T; begin json := JSON_OBJECT_T(p_marks); return json.get_String(p_subj); end; select t.column_value as subj, get_mark(SUBJECT_MARKS, t.column_value) as mark from students cross join sys.odcivarchar2list( 'English', 'Hindi', 'Maths', 'Science', 'Social', 'something' ) t where student_id = 101SUBJ | MARK :-------- | ---: English | 70 Hindi | 80 Maths | 90 Science | 90 Social | 85 something | null
дб <> рабочий пример здесь
Что-то не имеет смысла. Вы спрашиваете о JSON_VALUE, но вопрос конкретно помечен
oracle11gиoracle10g. Функции JSON были добавлены только в Oracle 12. Итак, что есть что?