看到 ORA-00905: 由于 WHERE 子句中的 CASE 语句导致缺少关键字错误
Seeing ORA-00905: missing keyword error due to CASE statement in WHERE clause
我在位置看到 ORA-00905: missing keyword at
错误:181,似乎无法弄清楚 SQL(Oracle PL/SQL)有什么问题。
SELECT *
FROM FOO
WHERE LOCATION = :LOCATION
AND SAVED_DATE >= CASE WHEN :BEGIN_D IS NULL THEN SAVED_DATE ELSE TIMESTAMP :BEGIN_D END
AND SAVED_DATE <= CASE WHEN :END_D IS NULL THEN SYSDATE ELSE TIMESTAMP :END_D END
ORDER BY SAVED_DATE;
我的假设是,如果用户输入是:
:LOCATION = 'new york'
:BEGIN_D = NULL
:END_D = NULL
则查询推导为:
SELECT *
FROM FOO
WHERE LOCATION = 'new york'
AND SAVED_DATE >= SAVED_DATE -- This line is ignored
AND SAVED_DATE <= SYSDATE
ORDER BY SAVED_DATE;
但是我看到了开头提到的错误。
当输入不是 NULL
(例如::BEGIN_D = '2015-12-01 00:01:44'
)时,我没有看到错误。如果 :BEGIN_D
和 :END_D
之一或两者都是 NULL
,则错误返回。
绑定变量不是替换变量;它们不会被您输入的文本替换,因此您不能使用 TIMESTAMP :BEGIN_D
。您只想使用 :BEGIN_D
并传入 TIMESTAMP
数据类型。
SELECT *
FROM FOO
WHERE LOCATION = :LOCATION
AND SAVED_DATE >= CASE WHEN :BEGIN_D IS NULL THEN SAVED_DATE ELSE :BEGIN_D END
AND SAVED_DATE <= CASE WHEN :END_D IS NULL THEN SYSDATE ELSE :END_D END
ORDER BY SAVED_DATE;
您也不需要使用 CASE
表达式:
SELECT *
FROM FOO
WHERE LOCATION = :LOCATION
AND (:BEGIN_D IS NULL OR SAVED_DATE >= :BEGIN_D)
AND ((:END_D IS NULL AND SAVED_DATE <= SYSDATE) OR SAVED_DATE <= :END_D)
ORDER BY SAVED_DATE;
如果您传递的是字符串值(而不是时间戳),则使用 TO_DATE
:
SELECT *
FROM FOO
WHERE LOCATION = :LOCATION
AND (:BEGIN_D IS NULL OR SAVED_DATE >= TO_DATE(:BEGIN_D, 'YYYY-MM-DD HH24:MI:SS'))
AND ((:END_D IS NULL AND SAVED_DATE <= SYSDATE) OR SAVED_DATE <= TO_DATE(:END_D, 'YYYY-MM-DD HH24:MI:SS'))
ORDER BY SAVED_DATE;
我在位置看到 ORA-00905: missing keyword at
错误:181,似乎无法弄清楚 SQL(Oracle PL/SQL)有什么问题。
SELECT *
FROM FOO
WHERE LOCATION = :LOCATION
AND SAVED_DATE >= CASE WHEN :BEGIN_D IS NULL THEN SAVED_DATE ELSE TIMESTAMP :BEGIN_D END
AND SAVED_DATE <= CASE WHEN :END_D IS NULL THEN SYSDATE ELSE TIMESTAMP :END_D END
ORDER BY SAVED_DATE;
我的假设是,如果用户输入是:
:LOCATION = 'new york'
:BEGIN_D = NULL
:END_D = NULL
则查询推导为:
SELECT *
FROM FOO
WHERE LOCATION = 'new york'
AND SAVED_DATE >= SAVED_DATE -- This line is ignored
AND SAVED_DATE <= SYSDATE
ORDER BY SAVED_DATE;
但是我看到了开头提到的错误。
当输入不是 NULL
(例如::BEGIN_D = '2015-12-01 00:01:44'
)时,我没有看到错误。如果 :BEGIN_D
和 :END_D
之一或两者都是 NULL
,则错误返回。
绑定变量不是替换变量;它们不会被您输入的文本替换,因此您不能使用 TIMESTAMP :BEGIN_D
。您只想使用 :BEGIN_D
并传入 TIMESTAMP
数据类型。
SELECT *
FROM FOO
WHERE LOCATION = :LOCATION
AND SAVED_DATE >= CASE WHEN :BEGIN_D IS NULL THEN SAVED_DATE ELSE :BEGIN_D END
AND SAVED_DATE <= CASE WHEN :END_D IS NULL THEN SYSDATE ELSE :END_D END
ORDER BY SAVED_DATE;
您也不需要使用 CASE
表达式:
SELECT *
FROM FOO
WHERE LOCATION = :LOCATION
AND (:BEGIN_D IS NULL OR SAVED_DATE >= :BEGIN_D)
AND ((:END_D IS NULL AND SAVED_DATE <= SYSDATE) OR SAVED_DATE <= :END_D)
ORDER BY SAVED_DATE;
如果您传递的是字符串值(而不是时间戳),则使用 TO_DATE
:
SELECT *
FROM FOO
WHERE LOCATION = :LOCATION
AND (:BEGIN_D IS NULL OR SAVED_DATE >= TO_DATE(:BEGIN_D, 'YYYY-MM-DD HH24:MI:SS'))
AND ((:END_D IS NULL AND SAVED_DATE <= SYSDATE) OR SAVED_DATE <= TO_DATE(:END_D, 'YYYY-MM-DD HH24:MI:SS'))
ORDER BY SAVED_DATE;