Запрос Cognos с двумя выражениями фильтра ИЛИ что может быть выполнено не по порядку? - PullRequest
2 голосов
/ 02 декабря 2011

Это из отчета Cognos, он имеет интерактивное многозначное приглашение (P_prompt_param).

Запрос написан с использованием табличного SQL.Чтобы сделать его необязательным фильтром для столбца (someval), создатель отчета записал его следующим образом в предложении where запроса:

( 
       'NO INPUT' IN (#promptmany('P_prompt_param', 'String', sq('NO INPUT'))#)
       or
       table.somval IN (#promptmany('P_prompt_param', 'String', sq('NO INPUT'))#)
      )

В этом случае table.somval имеет тип NUMBER.Если вы не выбрали значение в приглашении на странице ввода.Отчет вернется в 4 средах с идентичными схемами БД, но есть одна среда, в которой это не будет работать.

Вместо одного выброса это приводит к ORA-01722: недействительное число

Это на Oracle 10.2.0.4.

Я играл в SQL, чтобы посмотреть, смогу ли я воспроизвести его в «рабочей» среде, если я представляю, как будет оцениваться макрос # promptmany #, когда не выбран ни один вход (значение defaultText'NO INPUT').

Запрос, подобный этому, получит ORA-01722

select * from mytable where ( someval in ('NO INPUT'));

Где, так как этот запрос, как и в приведенном выше предложении where в моем отчете, не будет

select * from mytable where ('NO INPUT' in ('NO INPUT') or someval in ('NO INPUT'));

Есть ли способ, чтобы выражения OR могли быть вычислены обоими, даже после того, как первое из них вернет true?Или возможно, что порядок оценки может «переключаться»?

Есть ли в Cognos или Oracle какой-либо параметр, который может определять порядок, или можно ли вычислять оба выражения?может ли это как-то зависеть от оптимизатора?

Это на Cognos ReportNet 1.1, Oracle 10g

1 Ответ

1 голос
/ 02 декабря 2011

Оптимизатор может оценивать предикаты в любом порядке по своему выбору. Таким образом, можно свободно оценить предикат someval in ('NO INPUT') перед предикатом 'NO INPUT' in ('NO INPUT'), и в этом случае вы получите ошибку.

Если someval - это NUMBER, его следует сравнивать с числом, а не строкой, поэтому я ожидаю, что подсказка должна быть определена как число, а параметр «Нет ввода» должен быть недействительным числом, т.е. -1. Кроме того, вы можете преобразовать someval в строку перед выполнением сравнения

to_char( someval ) IN ('NO INPUT')

будет допустимым синтаксисом, который не выдаст ошибку времени выполнения. Однако, если вы полагаетесь на индекс someval, добавление TO_CHAR не позволит использовать этот индекс. Вы можете обойти эту проблему, создав индекс на основе функций

CREATE INDEX fbi_tbl_someval
    ON mytable( to_char( someval ) );

Но тогда у вас есть потенциально два разных индекса, которые нужно поддерживать при изменении данных в таблицах, два индекса, занимающих дисковое пространство и т. Д.

...