#sql #oracle #dynamic
Вопрос:
Мне нужно выполнить инструкцию по обновлению, и я не уверен в том, какие столбцы необходимо обновить, пока не будет отправлен запрос на исправление http. Мне нужно изменить записи сотрудников, и мне нужно создать инструкцию по обновлению только с теми столбцами, которые имеют обновленные значения.
В таблице есть столбцы записей сотрудников(идентификатор,имя,дата рождения,начало года,конец года,компания). и пример ответа:
{
"name":"Jim"
}
Обновление: Я указываю идентификатор с помощью параметра URI при отправке запроса на исправление. Я также внедряю в Mule 4. Я не уверен, как выполнить следующее.
ОБНОВИТЬ НАБОР записей сотрудника-неизвестно — ГДЕ ID =:ID;
Комментарии:
1. Вообще говоря, приложение всегда должно предоставлять серверной части все значения полей — полную запись, а не только измененные значения. В вашем примере данные даже не включают ключевое поле записи: как вы вообще узнаете, какую запись обновлять, не говоря уже о том, какие значения задавать… Это не очень хороший дизайн.
2. @pmdba, я предоставил более подробную информацию выше. Я предоставляю PK с помощью параметра URI.
3. Это все еще не очень хороший дизайн. API должен принимать все параметры — полную запись — в качестве входных данных и выдавать один заранее определенный оператор обновления. В качестве альтернативы различные вызовы API могут принимать определенное подмножество полей в качестве входных данных, но SQL все равно должен быть статическим, а не динамическим. Построение динамического SQL для команд DML-это рецепт для внедрения SQL или других проблем.
4. Здесь я согласен с @pmdba. Технически говоря, вы можете протестировать каждый отдельный столбец после получения запроса, а затем создать динамический sql, который будет включать столбцы, которые вы пытаетесь обновить.
Ответ №1:
На самом деле вам не нужно использовать динамический SQL для решения этой проблемы. Предполагая , что вы используете версию Oracle, которая поддерживает JSON_TABLE
, следующего запроса должно быть достаточно:
UPDATE employee e
SET (name, dateofbirth, startyear, endyear, company) =
(SELECT NVL(j.name, e.name), NVL(j.dateofBirth, e.dateofBirth),
NVL(j.startyear, e.startyear), NVL(j.endyear, e.endyear),
NVL(j.company, e.company)
FROM JSON_TABLE('{"name":"Jim"}' --REPLACE WITH ACTUAL REQUEST
COLUMNS(name, dateOfBirth DATE, startyear, endyear, company)) j)
WHERE e.id = 1; --REPLACE WITH ACTUAL ID
Предпочтительно, я бы использовал переменные привязки как часть процедуры вместо жесткого кодирования JSON и идентификатора.
Я создал DBFiddle, чтобы показать эффективность запроса: (Ссылка)
ПРАВКА 1: Добавлена NULL
ПРОВЕРКА
Как было указано в комментариях, мой исходный запрос не работает, если пользователь вводит NULL
значение в запросе. Я изменил свой запрос для работы с использованием EXISTS
функциональности:
UPDATE employee e
SET (name, dateofbirth, startyear, endyear, company) =
(SELECT DECODE(j.name_chk, 1, j.name, e.name),
DECODE(j.dob_chk, 1, j.dateofbirth, e.dateofBirth),
DECODE(j.start_chk, 1, j.startyear, e.startyear),
DECODE(j.end_chk, 1, j.endyear, e.endyear),
DECODE(j.co_chk, 1, j.company, e.company)
FROM JSON_TABLE('{"name":"Jim","endyear":null}'
COLUMNS(name, name_chk NUMBER EXISTS PATH '$.name',
dateOfBirth DATE, dob_chk NUMBER EXISTS PATH '$.dateofbirth',
startyear, start_chk NUMBER EXISTS PATH '$.startyear',
endyear, end_chk NUMBER EXISTS PATH '$.endyear',
company, co_chk NUMBER EXISTS PATH '$.company')) j)
WHERE e.id = 1;
Я также обновил DBFiddle (Ссылка)
Комментарии:
1. Этот метод не работал бы, если бы пользователь, вызывающий API, хотел присвоить одному из столбцов значение null. Например, тело с запросом
{"name":"Jim","endyear":null}
не установитendyear
столбцу значение null, оно сохранит старое значение.2. @EJEgyed Спасибо вам за ваш комментарий. Вы были абсолютно правы. Я добавил некоторые функции для проверки явного
NULL
.