Передача приглашения пользователя в качестве даты (или даже строки) в Oracle SQL

Я использую бизнес-объекты, которые работают поверх базы данных Oracle SQL. У меня нет доступа к PL или какой-либо командной строке SQL, и у меня нет доступа на запись в базу данных. Я могу запускать запросы только как отдельные команды, требующие вывода определенного набора столбцов.

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

@variable('Prompt1')

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

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

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

проблема в том, что пользователи будут использовать систему "Infoview" бизнес-объектов для запуска запросов, а система подсказок представляет собой средство выбора даты, которое по умолчанию включает временную часть даты ("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'))

... однако это вызывает ошибку компиляции: "несогласованные типы данных: ожидаемая дата получила номер". Я не знаю, почему Oracle будет рассматривать приглашение как тип данных числа до его компиляции.

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

поэтому я пытаюсь найти способ обойти это. Одна вещь, которую я имел в виду, если бы я мог взять переменную prompt и явно преобразовать ее в дату, используя TO_DATE

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

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

3 ответов


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

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

The + 1 использует арифметика даты Oracle чтобы дать вам на следующий день после переменной величины, поэтому, если пользователь выбрал "01/01/2016 12:00:00 АМ" для дат начала и окончания они будут оценивать как 2016-01-01 00:00:00 и 2016-01-02 00:00:00 соответственно. Вы можете использовать interval синтаксис, если хотите.

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

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

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.


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

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

во-первых, ваша проблема не исходит из значения времени в значении приглашения, а скорее значение времени в 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 между 8/16/2016 в 00:00:00 и 8/16/2016 23:59: 59.

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

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

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

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

причина ошибки "недопустимое число", которую вы получали, заключается в том, как webi форматирует даты для SQL. Если у вас есть эта строка в запросе:

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

тогда WebI заменит переменную @(...) с датой строка, и визуализируйте его следующим образом перед отправкой в 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')

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


*еще лучше, переименовать SomeDate to SomeDateTime, и назовите новый объект SomeDate

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