Oracle где условие приоритет - PullRequest
2 голосов
/ 29 марта 2012

У меня есть таблица со столбцом varchar (A) и другим целочисленным столбцом (B), указывающим тип данных, присутствующих в A. Если B равно 0, то A всегда будет содержать числовые цифры.

Так что, когда я создаю sql, как это

SELECT COUNT(*) FROM TAB WHERE B = 0 AND TO_NUMBER(A) = 123;

Я получил недопустимый номер исключения.

Я ожидаю, что B = 0 будет оцениваться сначала, а затем TO_NUMBER (A), но из вышеприведенного сценария я подозреваю, что TO_NUMBER (A) оценивается первым. Правильно ли мое предположение?

Ответы [ 5 ]

2 голосов
/ 29 марта 2012

Вот простой способ заставить проверку B произойти первой.

SELECT COUNT(*) FROM TAB
WHERE 123 = DECODE(B, 0, TO_NUMBER(A), NULL);
2 голосов
/ 29 марта 2012

В отличие от языков программирования, таких как C, C #, Java и т. Д., В SQL нет так называемых условных логических операторов. Для условных логических операторов правый операнд оценивается только в том случае, если он может повлиять на результат. Таким образом, оценка && останавливается, если левый операнд возвращает false. Для || он останавливается, если левый операнд возвращает true.

В SQL оба операнда всегда вычисляются. И оптимизатор запросов должен выбрать, какой из них будет оценен первым.

Я предлагаю вам создать следующую функцию, которая полезна во многих случаях:

FUNCTION IS_NUMBER(P_NUMBER VARCHAR2)
RETURN NUMBER DETERMINISTIC
IS
  X NUMBER;
BEGIN
  X := TO_NUMBER(P_NUMBER);
  RETURN X;
EXCEPTION
  WHEN OTHERS THEN RETURN NULL;
END IS_NUMBER;

Тогда вы можете переписать ваш запрос как:

SELECT COUNT(*) FROM TAB WHERE B = 0 AND IS_NUMBER(A) = 123;

Вы также можете использовать функцию, чтобы проверить, является ли строка числом.

1 голос
/ 29 марта 2012

вы можете использовать подзапрос, чтобы быть уверенным в правильности результата

select /*+NO_MERGE(T)*/ count(*)
from (
    select *
    from TAB
    where B = 0
) T
where TO_NUMBER(A) = 123
0 голосов
/ 29 марта 2012

в вашем конкретном примере, вы можете сравнить varchars следующим образом:

SELECT COUNT(*) FROM TAB WHERE B = 0 AND A = '123';

или если вы доверяете oracle для выполнения неявных преобразований , это почти всегда должно работать (я не знаю, в каких случаях это не будет работать, но было бы сложно отлаживать если что-то пошло не так)

SELECT COUNT(*) FROM TAB WHERE B = 0 AND A = 123;
0 голосов
/ 29 марта 2012

Сначала он должен проверить B = 0.
Я не уверен, что ваше предположение верно или нет, хотя, не видя данных примера.

SELECT *
FROM DUAL
WHERE 1=0 AND 1/0=0

Вы можете попробовать добавить 1/0 = 0 в качестве последнего утверждениякак этот запрос)
на ваш запрос, чтобы узнать, если Oracle короткое замыкание логический оператор.

sqlfiddle здесь .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...