Oracle 9i: возможно отсутствует правая скобка - PullRequest
0 голосов
/ 16 января 2009

У меня есть простая функция, написанная на Oracle 9i (версия 9.2.0.4.0) для имитации встроенного IF. Для тех, кто заинтересован, вот код:

create or replace
FUNCTION IIF  
   (testExpression NUMBER,
    trueResult NUMBER,
    falseResult NUMBER)
RETURN NUMBER   
AS
BEGIN
   /*
      A simple in-line IF function for use with SQL queries. If the test
      expression evaluates to any non-zero value, it is considered to be 
      true, and the trueResult is returned. Otherwise, falseResult is
      returned.
   */   
   IF (testExpression is null) or (testExpression = 0) THEN
      return falseResult;
   ELSE
      return trueResult;
   END IF;
END IIF;

Это не ракетостроение. Теперь вот большая загадка: если я выполняю следующие операторы SQL, все в порядке и работает точно так, как я ожидаю:

SELECT IIF(1, 'true', 'false') FROM DUAL;
SELECT IIF(0, 'false', 'true') FROM DUAL;

Тем не менее, следующее генерирует действительно странную ошибку из Oracle:

SELECT IIF((0 = 1), 'false', 'true') FROM DUAL;

Эта ошибка выглядит следующим образом:

ORA-00907: missing right parenthesis.

Очевидно, что это не так. Может быть, у кого-нибудь есть объяснение этой маленькой странности?

В настоящий момент требуется много самоконтроля, чтобы удержаться от того, чтобы выкинуть сервер Oracle из окна. Оракул кажется распространенным с такими видами безумия.

РЕДАКТИРОВАТЬ: есть ли какой-то магический синтаксис, который я должен использовать, чтобы использовать оператор равенства в операторе выбора?

Ответы [ 5 ]

5 голосов
/ 16 января 2009

Может быть, вы можете объяснить, что вы пытаетесь сделать. Я думаю, что вы ищете функции CASE или DECODE, но я не уверен. Похоже, вы по какой-то причине работаете против структуры языка SQL.

Ошибка возникает из-за того, что Oracle не ожидает реляционного оператора в предложении select запроса:

SQL> SELECT IIF(1>7, 0, 1) FROM DUAL;
SELECT IIF(1>7, 0, 1) FROM DUAL
            *
ERROR at line 1:
ORA-00907: missing right parenthesis

SQL> SELECT 1=0 FROM DUAL;
SELECT 1=0 FROM DUAL
        *
ERROR at line 1:
ORA-00923: FROM keyword not found where expected

См. эту статью Ask Tom .

3 голосов
/ 16 января 2009

Вы хотите

SELECT CASE WHEN *expr* then 'true' else 'false' end col_alias FROM DUAL;

или для простого теста на равенство

SELECT DECODE(*val1*,*val2*,'true','false') col_alias FROM dual;

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

  1. Логические значения не относятся к типу данных Oracle.

  2. Это тип данных PL / SQL, но даже в этом случае неявное преобразование в числа (ноль ложных, ненулевое истина)

  3. Нет типа данных 'expression', поэтому движок SQL не может передать выражение в PL / SQL.

  4. Даже если вы передаете выражение в виде строки в PL / SQL, механизм PL / SQL не может динамически вычислять выражение в строке. Пришлось бы встроить строку в динамический оператор SQL и выполнить его динамически, возвращая результат (в допустимом типе данных SQL, например в строке или числе).

1 голос
/ 16 января 2009
  1. В базе данных Oracle нет типа BOOLEAN, поэтому нельзя использовать выражение типа "(1 = 0)".
  2. Даже если был тип BOOLEAN, вы объявили первый аргумент типа NUMBER. Вы должны передать ему число или что-то, что может быть неявно преобразовано в один.
  3. Наконец, я не понимаю, как какой-либо из ваших примеров на самом деле генерировал что-либо, кроме «недопустимого числа», поскольку ваши второй и третий аргументы также не могут быть преобразованы в числа.
0 голосов
/ 16 января 2009

Помимо декодирования и кейса, есть также nvl.

0 голосов
/ 16 января 2009

Никогда не работая с оракулом, я не могу напрямую дать здравый совет, но, глядя на утверждение, может быть, у оракула возникла проблема с выводом числа из логического числа? ..

Подпись IIF ожидает НОМЕР в качестве первого аргумента, и в вызове вы передаете оценку BOOL.

Это всего лишь мысль.

...