2015-02-07 3 views
0

Вместо того чтобы делать:Корпус на основе оператора выбора?

select count(*) into l_count from mergetest where a = 1; 

case l_count 
    when 0 then 
    insert into mergetest (a,b) values (1,1); 
    when 1 then 
    update mergetest set b = b + 1 where a = 1; 
    else 
    NULL; 
    end case; 

Я хотел бы избавиться от локальной переменной l_count и вместо того, чтобы сделать:

case select count(*) from mergetest where a = 1; 
... 

Возможно ли это?

ответ

1

Нет, это невозможно. Это не относится к структуре управления CASE PL/SQL, а скорее к PL/SQL вообще. Вы не можете использовать его в инструкции IF.

Так что этот код не будет составлять либо:

IF (SELECT COUNT(*) FROM MY_TABLE) > 0 THEN ... 

Обратите внимание, что вы можете использовать подзапросы, если оператор случае является выражение в SELECT (или аналогичный SQL) заявление:

SEELCT 
    p.name, 
    CASE WHEN P.TYPE_ID = 1 THEN 
     (SELECT COUNT(*) FROM child c WHERE c.parent_id = p.id) 
    ELSE 0 
    END cnt 
FROM parent p; 

Но, конечно, в выражении вы не можете использовать такие выражения, как INSERT или UPDATE.

+0

Исправлено: can -> can not – Roland

+0

@Roland: Спасибо, что сообщили об этом. Это исправлено. – Codo

0

Похоже, что это не представляется возможным с помощью PL/SQL

из док

Значение CASE-операнда и когда операнды в простом случае заявление может быть любой PL/тип SQL, кроме BLOB, BFILE, объект , запись PL/SQL, индексную таблицу, varray или вложенную таблицу.

http://docs.oracle.com/cd/B19306_01/appdev.102/b14261/case_statement.htm

Однако, вы можете использовать scalar subquery

select case when dummy = 'X' then (select count(*) from all_users) 
else (select count(*) from dual) 
end cnt from dual 

Который, вероятно, решить вашу проблему.

+0

Я получаю сообщение об ошибке: PLS-00103: Обнаружен символ «SELECT», когда ожидает одно из следующих действий: (- + корпус мод новый не нулевой <Идентификатор,> <двойных кавычках delimited- идентификатор> continue avg count current exists max min before sql stddev – Roland

+0

Нет, все еще ошибка – Roland

+0

@Roland см. новое редактирование. –

1

Можно избавиться от локальной переменной с помощью merge, не case:

merge into mergetest 
    using (select 1 a from dual) ins 
    on (mergetest.a = ins.a) 
    when matched then 
    update set mergetest.b = mergetest.b + 1 
     where (select count(1) from mergetest where mergetest.a = ins.a) = 1 
    when not matched then insert (mergetest.a, mergetest.b) 
    values (ins.a, 1) 

Line:

 where (select count(1) from mergetest where mergetest.a = ins.a) = 1 

предотвращает обновления, если a уже существует в таблице более чем один раз.

+0

Правда, но код становится сложнее понять.Вы ответили на мой другой вопрос: http://stackoverflow.com/questions/28382332/merge-statement-but-update-only-if-exactly-one-row-matches – Roland

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