Инструкция динамического обновления, содержащая только столбцы с обновленными значениями

#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 .