2016-08-17 3 views
6

Я использую Business Objects, который работает поверх базы данных Oracle SQL. У меня нет доступа к PL или любой командной строке SQL, и у меня нет доступа на запись в базу данных. Я могу запускать запросы только в виде одиночных команд, требуя вывода определенного набора столбцов.Передача пользовательского приглашения в виде даты (или даже строки) в Oracle SQL

Я могу принимать данные от пользователя подсказок, которые появляются в SQL, как:

@variable('Prompt1') 

Например, я могу сказать:

SELECT 
    A.SomeDate 
FROM 
    A 
WHERE 
    A.SomeDate BETWEEN @variable('Start') AND @variable('End Date') 

Это достаточно просто. Он работает; запрашивает у пользователя ввод некоторых дат; и затем возвращает все совпадения, которые находятся между ними (включительно).

Проблема заключается в том, что пользователи будут использовать систему «Infoview» Business Objects для запуска запросов, а система приглашений представляет собой сборщик дат, который по умолчанию включает временную часть даты («01/01/2016 12:00:00 AM ").

Если пользователь не удаляет временную часть, это может привести к пропущению записи записей, если значение SomeDate выходит за пределы выбранного времени. Например, если я хочу взять все записи СЕГОДНЯ, то я технически хочу все между 00:00:00 (полночь) и 23:59:59.

То, что я действительно хотел бы быть в состоянии сделать, это использовать TRUNC вокруг переменной запроса следующим образом:

WHERE 
    A.SomeDate BETWEEN TRUNC(@variable('Start')) AND TRUNC(@variable('End Date')) 

... Однако это вызывает ошибку компиляции: «несогласованные типы данных: ожидается DATE получил НОМЕР ». Я не знаю, почему Oracle будет обрабатывать приглашение как числовой тип данных до его компиляции.

Кто-нибудь знает, как я могу принять значение @variable и преобразовать его во что-то, что я смогу усечь до значения даты?

Поэтому я пытаюсь найти способ обойти это. Единственное, что я имел в виду, это то, что если бы я мог взять переменную приглашения и преобразовать ее явно в дату, используя TO_DATE

Редактировать: мне было указано, что TRUNC не будет иметь никакого эффекта, поскольку «12: 00:00 утра "уже полночь. Поэтому я думаю, что неправильно понял TRUNC. Похоже, что он усекает его до полуночи: в то время как я думал, что он просто удаляет временную часть даты вообще, что означает, что совпадения будут возвращены в любое время между 00:00:00 и 23:59:59.

Что я действительно хочу: если SomeDate имеет временную часть, например, 11:03, то как я могу убедиться, что это будет включено, когда приглашение в конце даты указывает только день?

+0

Если сборщик данных всегда проходит время как 12:00:00, тогда усечение его не будет иметь эффекта; уже в полночь. –

+0

@Alex Poole - хм, интересно знать. Что происходит, когда значение SomeDate имеет временную часть, например 11:02 и т. Д. Я упростил свой пример выше, но я действительно хочу посмотреть между датами. Например, если я хочу перечислить все события, происходящие СЕГОДНЯ, в том числе в 11:02, тогда поиск «полночь» не подберет их. Я думал, что усечение будет означать, что никакая часть времени не была обыскана. –

+0

Даты Oracle всегда имеют время, вы не можете удалить его - установите только до полуночи, что по умолчанию делает trunc. Итак, вы хотите совместить записи между 00:00:00 по дате начала и 23; 59: 59 на дату окончания? –

ответ

1

Если вы хотите, чтобы соответствовать SomeDate значения между 00:00:00 и 23:59:59 Начало дыбом вы можете установить дату окончания, чтобы иметь что время вместо полуночи по умолчанию, или использовать диапазон вместо between:

WHERE 
    A.SomeDate >= @variable('Start') 
AND 
    A.SomeDate < @variable('End Date') + 1 

+ 1 использует Oracle date arithmetic, чтобы дать вам на следующий день после значения переменного, так что если пользователь выбрал «01/01/2016 12:00:00 AM» для дат начала и окончания, которые они будут оценивать как 2016-01-01 00:00:00 и 2016-01-02 00:00:00 соответственно. Вы можете использовать синтаксис interval, если хотите.

При использовании менее чем для верхнего предела вы получите все записи, в которых SomeDate является больше или равна дата начала 2016-01-01 00:00:00 и менее скорректированный конечная дата 2016 -01-02 00:00:00 - это то же самое, что и до 2016-01-01 23:59:59. (Или, если у вас есть столбец временной отметки с точностью до второй секунды, до 23: 59: 59.999 ...).

Если анализатор принимает переменная будет строка, но это на самом деле дата - вызывает ошибку «непоследовательные Datatypes» - тогда вы могли бы бросить его на сегодняшний день, чтобы удовлетворить парсер:

WHERE 
    A.SomeDate >= CAST(@variable('Start') AS DATE) 
AND 
    A.SomeDate < CAST(@variable('End Date') AS DATE) + 1 

или если это на самом деле передается в виде строки в формате, который вы показали, вы можете явно преобразовать его:

WHERE 
    A.SomeDate >= TO_DATE(@variable('Start'), 'DD/MM/YYYY HH:MI:SS AM') 
AND 
    A.SomeDate < TO_DATE(@variable('End Date'), 'DD/MM/YYYY HH:MI:SS AM') + 1 

... убедившись, что у вас есть правильный формат; из вашего примера это может быть DD/MM/YYYY или MM/DD/YYYY.

+0

Решение отлично звучит и имеет прекрасный смысл. Однако, когда я только что попробовал, он не скомпилировался. Ошибка - это «непоследовательные типы данных: ожидаемый DATE получил NUMBER». Это вызвано привязкой второй строки, чтобы добавить 1 к значению подсказки. Итак, мы вернемся к исходному вопросу, который относится к быстрым типам данных. Мне нужно преобразовать приглашение в значение даты ... –

+0

Тогда вам может понадобиться 'to_date()' вокруг обеих переменных. Проблема заключается в том, что синтаксический анализатор SQL видит биты '@variable()' как переменные связывания и предполагает, что они являются строками (как они могут быть). Вы можете использовать 'cast (@variable ('Start') в качестве даты), но если они * переданы как строки, тогда лучше указать маску формата, если она исправлена ​​-' to_date (@variable ('Start') , 'DD/MM/YYYY HH: MI: SS AM') '.Ваш исходный запрос выполняет неявное преобразование, если они не переданы как даты, поэтому BO может устанавливать этот формат даты как значение по умолчанию для сеанса. –

1

Попробуйте использовать TO_CHAR() и TO_DATE() вместе:

WHERE 
A.SomeDate > TO_DATE(TO_CHAR(@variable('Prompt1'),'ddmmyyyy'),'ddmmyyyy') 
+0

Это компилируется, однако, когда он запускается, он возвращает «Ошибка при выполнении SQL: ORA-01722: недопустимый номер». Да, я печатал дату в формате ddmmyyyy. Любые другие мысли? –

0

Во-первых, ваша проблема не связана с значением времени в значении приглашения, а скорее значением времени в SomeDate. Избавиться от этого (чтобы сделать дату равной полуночи), решит проблему.

Лучше всего, если у вас есть возможность изменить юниверс, нужно создать другой объект. Я предполагаю, что у вас есть объект с именем SomeDate, SQL которого равен a.somedate. Создайте еще один объект, назовем его SomeDateOnly с определением trunc(a.somedate) * **.

Поскольку SomeDateOnly всегда будет значение полуночи, вы можете использовать, равным с подсказками, которые будут производить SQL, как:

trunc(a.somedate) = @variable('Prompt1') 

, который, когда оказываемая WebI, будет производить:

trunc(a.somedate) = '16-08-2016 00:00:00' 

Это вернет все записи с a.somedate между 16.08.2012 в 00:00:00 и 16.08.2013 23:59:59.

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

trunc(a.somedate) between @variable('Start Date') and @variable('End Date') 

Даже если у вас нет доступа к Вселенной, вы все еще можете использовать приведенные выше синтаксис, изменив сгенерированный SQL WebI в. (Я предполагаю, что это то, что вы делали, так или иначе).

Если вышеуказанные работы для вас, то следующие не имеют значения, но я хотел в любом случае для решения этой проблемы:

Причины ошибки «недействительный номер» вы получающая это из-за способом WebI форматирует даты для SQL. Если у вас есть эта строка в запросе:

A.SomeDate = TRUNC(@variable('Prompt1')) 

затем WebI заменит @variable (...) с датой строки, и вынести его в следующий перед отправкой в ​​Oracle:

A.SomeDate = TRUNC('16-08-2016 00:00:00') 

Это, конечно, не имеет смысла для функции TRUNC(), так как нет ничего, чтобы сказать, что это фактически значение даты.

Вы, , моглиto_date сначала сначала, но вы должны использовать правильный формат даты. WebI устанавливает nls_date_format для каждой сессии в формате не по умолчанию, так что вам придется использовать:

A.SomeDate = TRUNC(to_date(@variable('Prompt1')),'dd-mm-yyyy hh24:mi:ss') 

Но опять же, это не имеет никакого значения, так как вам нужно Trunc somedate, а не быстрые значения отклика.


* А еще лучше, переименовать SomeDate в SomeDateTime, и имя нового объекта SomeDate

** Это довольно часто - наличие нескольких объектов для одной и той же области источника. Иногда вам требуется значение даты/времени (для перечисления конкретных транзакций), но иногда вам просто нужна дата (для подсчета транзакций по дате). Поэтому наличие обоих доступных очень полезно.