Привет. Учтите следующее:
SQL> DECLARE
2 b1 BOOLEAN;
3 b2 BOOLEAN;
4 FUNCTION checkit RETURN BOOLEAN IS
5 BEGIN
6 dbms_output.put_line('inside checkit');
7 RETURN TRUE;
8 END checkit;
9
10 PROCEDURE outp(n VARCHAR2, p BOOLEAN) IS
11 BEGIN
12 IF p THEN
13 dbms_output.put_line(n||' is true');
14 ELSE
15 dbms_output.put_line(n||' is false');
16 END IF;
17 END;
18 BEGIN
19 b1 := TRUE OR checkit;
20 outp('b1',b1);
21 b2 := checkit OR TRUE;
22 outp('b2',b2);
23 END;
24 /
b1 is true
inside checkit
b2 is true
PL/SQL procedure successfully completed
SQL>
Обратите внимание, что результаты операторов ИЛИ зависят от порядка. Если я помещаю вызов функции первым, функция выполняется независимо от значения другого члена. Похоже, что оператор ИЛИ оценивается слева направо, пока не будет получено ИСТИНА, после чего обработка останавливается, а результат - ИСТИНА.
Мой вопрос: могу ли я на это положиться? Или это поведение может измениться в будущих выпусках PL / SQL? Если бы это могло измениться, есть ли способ принудительно оценить функцию, на которую я могу положиться (без создания другой переменной и использования отдельного оператора присваивания)?





да. PL / SQL выполняет оценка короткого замыкания логических выражений слева направо.
Мой Google для "полной логической оценки pl / sql" дал мне точно такую же ссылку.
Это лучший поиск, чем то, что я пробовал: «Оценка силы PLSQL». Спасибо!
Это называется «оценкой короткого замыкания» и является нормой для большинства языков, включая PL / SQL.
If it could change, is there a way to force the function to be evaluated that I can rely on (without creating another variable and using a separate assignment statement)?
Если вы требуете, чтобы функция оценивалась даже тогда, когда это логически излишне, это означает, что она делает что-то иное, кроме простого возврата ИСТИНА или ЛОЖЬ, например возможно, он обновляет таблицу. Такие «побочные эффекты» не считаются хорошей практикой для функций PL / SQL.
Ряд функций редактирования. Каждая проблема редактирует сообщения и возвращает индикатор, если текущая запись должна быть пропущена. Флаг пропуска запускается как ЛОЖЬ и устанавливается в ИСТИНА, если проверка не проходит. Я не хочу, чтобы флаг пропуска сбрасывался на ЛОЖЬ, если он проходит какую-либо конкретную проверку.
Вы можете заменить эти функции процедурами с параметром IN OUT для флага. Процедуры установят флаг в TRUE, если какая-либо проверка не удалась, но оставят его в покое, если ни одна из проверок не прошла: l_flag: = FALSE; do_check1 (l_flag); do_check2 (l_flag); do_check3 (l_flag);
В документации говорится, что оценка короткого замыкания применяется к выражениям IF, CASE и CASE: я готов поспорить, что она также применяется в приведенном вами примере, но технически не задокументировано, что это так. Возможно, стоит обратиться в Oracle с просьбой о таком поведении, чтобы подтвердить его.
Он оценивает операторы ИЛИ слева направо и операторы И справа налево. Я не нашел для себя документации по этому поводу.
что именно вы имеете в виду под "..и операторы И справа налево"?
это из документации оракула =>
Обратите внимание, что в следующем примере, когда valid имеет значение FALSE, все выражение дает FALSE независимо от значения done:
действителен И сделано
вы можете проверить порядок в следующем примере:
ЗАЯВИТЬ
b1 BOOLEAN;
b2 БУЛЕВЫЙ;
ФУНКЦИЯ checkit (v НОМЕР)
ВОЗВРАТ BOOLEAN
IS
BEGIN
DBMS_OUTPUT.put_line ('внутренняя проверка:' || v);
ВОЗВРАТ ИСТИНА;
КОНЕЦ checkit;
ПРОЦЕДУРА outp (n VARCHAR2, p BOOLEAN)
IS
BEGIN
ЕСЛИ p
THEN
DBMS_OUTPUT.put_line (n || 'верно');
ELSE
DBMS_OUTPUT.put_line (n || 'ложно');
КОНЕЦ IF;
КОНЕЦ;
BEGIN
b1: = checkit (1) AND checkit (2);
outp ('b1', b1);
b2: = checkit (3) AND checkit (4);
outp ('b2', b2);
КОНЕЦ;
внутренний чекит: 1
внутренний чекит: 2
b1 верно
внутренний чекит: 3
внутренний чекит: 4
b2 верно
Perfecto. Именно то, что я искал!