2015-03-26 2 views
3

У меня есть оператор обновления в динамическом SQL, как это:Использование связываемых переменных для динамического SQL Update

varDynQuery := 'UPDATE TABLE SET B0 = ' || A0; 

IF(A1 IS NOT NULL) THEN 
varDynQuery := varDynQuery || ', B1 = ' || A1; 
END IF; 

IF(A2 IS NOT NULL) THEN 
varDynQuery := varDynQuery || ', B2 = ' || A2; 
END IF; 

Я хотел бы изменить его, чтобы использовать переменные связывания вместо того, чтобы предотвратить SQL-инъекции

varDynQuery := 'UPDATE TABLE SET B0 = :A0'; 

IF(A1 IS NOT NULL) THEN 
varDynQuery := varDynQuery || ', B1 = :A1'; 
END IF; 

IF(A2 IS NOT NULL) THEN 
varDynQuery := varDynQuery || ', B2 = :A2'; 
END IF; 

EXECUTE IMMEDIATE varDynQuery USING 
A0, A1, A2; 

Однако из-за того, что A1 и A2 не всегда присутствуют, это может вызвать ошибку во время выполнения процедуры.

Есть ли способ сформировать инструкцию SQL, чтобы все переменные могли быть успешно связаны без обновления тех, которые необходимо исключить?

Примечание: хотелось бы избежать использования коалесценции.

+1

Я предполагаю, что 'A1! =" "' Вы имеете в виду 'A1 не null 'и' varDynQuery: 'вы имеете в виду' varDynQuery: = varDynQuery || '. –

ответ

3

Просто убедитесь, что все переменные связывания включены, например .:

varDynQuery := 'UPDATE TABLE SET B0 = :A0, 
    B1 = NVL(:A1,B1), 
    B2 = NVL(:A2,B2)'; 

EXECUTE IMMEDIATE varDynQuery USING 
A0, A1, A2; 

Преимущество этого подхода состоит в том, что существует только один запрос, который должен быть проанализирован, что означает меньшую нагрузку на общий бассейн.

Единственным недостатком является то, что если у вас есть триггеры, специфичные для столбца, они будут стрелять для B1 и B2, даже если они не будут изменены.

Если это проблема, вам нужно будет использовать другое выполнить немедленное для каждого из четырех сценариев обновления (например, B0, B0 + B1, B0 + B2, B0 + B1 + B2)

0

Другим решением является этот:

varDynQuery := 'UPDATE TABLE SET B0 = :A0'; 

IF(A1 IS NOT NULL) THEN 
varDynQuery := varDynQuery || ', B1 = :A1'; 
END IF; 

IF(A2 IS NOT NULL) THEN 
varDynQuery := varDynQuery || ', B2 = :A2'; 
END IF; 

IF A1 IS NOT NULL THEN 
    IF A2 IS NOT NULL THEN 
     EXECUTE IMMEDIATE varDynQuery USING A0, A1, A2; 
    ELSE 
     EXECUTE IMMEDIATE varDynQuery USING A0, A1; 
    END IF; 
ELSE 
    IF A2 IS NOT NULL THEN 
     EXECUTE IMMEDIATE varDynQuery USING A0, A2; 
    ELSE 
     EXECUTE IMMEDIATE varDynQuery USING A0; 
    END IF; 
END IF; 

Тем не менее, ваш код становится кричащим, если у вас больше переменных, чем всего 2-3.

Смежные вопросы