获取 ORA-01861 - 文字与仅 SQLPlus 上的格式字符串不匹配
Getting ORA-01861 - Literal does not match format string on SQLPlus Only
我有一个 PL/SQL 过程需要以下 arguments/parameters
Procedure create_test(mode_in in number, value1_in in number,
value2_in in number, value3_in in varchar2);
我正在使用以下 pl/sql 块来调用和执行过程
DECLARE
lv_mode NUMBER;
lv_value1_in NUMBER;
lv_value2_in NUMBER;
lv_value3 VARCHAR2(3);
BEGIN
lv_mode := 1;
lv_value1_in := 1;
lv_value2_in := 1;
lv_value3_in := 'ES';
CREATE_TEST(
mode_in => lv_mode ,
value1_in => lv_value1_in,
value2_in => lv_value2_in,
value3_in => lv_value3_in
);
--rollback;
END;
/
如果我将上面的 sql 块粘贴到 SQLDeveloper 中并执行它,它 运行 没有问题。
如果我把它放在一个文件中并通过 SQL plus 执行它,我会得到以下错误(如果 运行 直接在 SQLPLus 中也会出现同样的问题):
ORA-01861: literal does not match format string
通常当我收到此错误时,问题通常与日期有关。我不确定上面有什么问题,因为没有涉及日期 - 特别是考虑到相同的 SQL 块在 IDE 而不是 SQLPLus 中工作。
SQLPlus 处理文字的方式与 IDE 略有不同吗?
我的猜测是 SQLPlus 中的某些参数处理方式不同 - 但哪个参数?
您对语句“TO_DATE(SYSDATE, 'DD-MON-YYYY HH:MI:SS')”的使用存在根本性缺陷。 to_date 函数将字符串作为其第一个参数,但您传递的是 SYSDATE,这是一个日期。这会强制 oracle 首先使用 NLS_DATE_FORMAT 的会话级别设置将 SYSDATE 隐式转换为字符串。获得该字符串后,它会将其转换回 DATE,并且必须假定派生的字符串与您提供的 'DD-MON-YYYY HH:MI:SS' 格式匹配。它在 SQL Dev 中工作,因为您将其配置为将 NLS_DATE_FORAMT 设置为 'DD-MON-YYYY HH:MI:SS',但这不是数据库默认格式,因此它在 sqlplus 下失败。您需要解决将日期 (sysdate) 传递给 to_date 函数的基本缺陷,而不是随意使用 NLS 设置。
有趣的错误:TO_DATE(SYSDATE, 'DD-MON-YYYY HH:MI:SS')
只需在过程中将此表达式替换为 SYSDATE..
SYSDATE
函数返回的数据类型是DATE
:
https://docs.oracle.com/cd/B19306_01/server.102/b14200/functions172.htm
TO_DATE
函数需要 CHAR
、VARCHAR2
、NCHAR
或 NVARCHAR2
类型作为其第一个参数:
http://docs.oracle.com/cd/B19306_01/server.102/b14200/functions183.htm
该过程将 SYSDATE(DATE 类型)作为第一个参数传递,该参数应为字符串(VARCHAR、CHAR 等)。在这种情况下,Oracle 在内部使用 TO_CHAR 函数执行 DATE 到 CHHAR/VARCHAR2 的隐式转换。
可以说上面的表达式在内部被转换为:
TO_DATE( TO_CHAR( sysdate ) , 'DD-MON-YYYY HH:MI:SS' )
可以在此处找到有关隐式转换规则的更多信息(滚动到部分:“数据转换 - 隐式和显式数据转换”):
https://docs.oracle.com/cd/B19306_01/server.102/b14200/sql_elements002.htm
上面的一个重要片段link:
Implicit conversion depends on the context in which it occurs and may
not work the same way in every case. For example, implicit conversion
from a datetime value to a VARCHAR2 value may return an unexpected
year depending on the value of the NLS_DATE_FORMAT parameter.
换句话说 - TO_CHAR( some-date )
没有第二个参数(格式)使用从会话中获取的 NLS_DATE_FOMRAT 变量值。
如果在SQL-Developer上勾选这个参数,大概是:'DD-MON-YYYY HH:MI:SS'(在SQL-Developer中这个参数的值是在option中配置的:Tools/Preferences/Database/NLS
但是如果你检查 SQL-Plus 中的 NLS_DATE_FORMAT 值,它将与 'DD-MON-YYYY HH:MI:SS' 不同。 SQL-Plus 根据环境的语言设置(Windows、Linux 等)和 NLS_LANG 环境变量(如果存在)确定 NLS 设置的值。
您可以使用以下方法在您的会话中更改此参数:
ALTER SESSION SET NLS_DATE_FORMAT = 'DD-MON-YYYY HH:MI:SS';
并且(旧)程序将起作用。
我有一个 PL/SQL 过程需要以下 arguments/parameters
Procedure create_test(mode_in in number, value1_in in number,
value2_in in number, value3_in in varchar2);
我正在使用以下 pl/sql 块来调用和执行过程
DECLARE
lv_mode NUMBER;
lv_value1_in NUMBER;
lv_value2_in NUMBER;
lv_value3 VARCHAR2(3);
BEGIN
lv_mode := 1;
lv_value1_in := 1;
lv_value2_in := 1;
lv_value3_in := 'ES';
CREATE_TEST(
mode_in => lv_mode ,
value1_in => lv_value1_in,
value2_in => lv_value2_in,
value3_in => lv_value3_in
);
--rollback;
END;
/
如果我将上面的 sql 块粘贴到 SQLDeveloper 中并执行它,它 运行 没有问题。 如果我把它放在一个文件中并通过 SQL plus 执行它,我会得到以下错误(如果 运行 直接在 SQLPLus 中也会出现同样的问题):
ORA-01861: literal does not match format string
通常当我收到此错误时,问题通常与日期有关。我不确定上面有什么问题,因为没有涉及日期 - 特别是考虑到相同的 SQL 块在 IDE 而不是 SQLPLus 中工作。 SQLPlus 处理文字的方式与 IDE 略有不同吗?
我的猜测是 SQLPlus 中的某些参数处理方式不同 - 但哪个参数?
您对语句“TO_DATE(SYSDATE, 'DD-MON-YYYY HH:MI:SS')”的使用存在根本性缺陷。 to_date 函数将字符串作为其第一个参数,但您传递的是 SYSDATE,这是一个日期。这会强制 oracle 首先使用 NLS_DATE_FORMAT 的会话级别设置将 SYSDATE 隐式转换为字符串。获得该字符串后,它会将其转换回 DATE,并且必须假定派生的字符串与您提供的 'DD-MON-YYYY HH:MI:SS' 格式匹配。它在 SQL Dev 中工作,因为您将其配置为将 NLS_DATE_FORAMT 设置为 'DD-MON-YYYY HH:MI:SS',但这不是数据库默认格式,因此它在 sqlplus 下失败。您需要解决将日期 (sysdate) 传递给 to_date 函数的基本缺陷,而不是随意使用 NLS 设置。
有趣的错误:TO_DATE(SYSDATE, 'DD-MON-YYYY HH:MI:SS')
只需在过程中将此表达式替换为 SYSDATE..
SYSDATE
函数返回的数据类型是DATE
:
https://docs.oracle.com/cd/B19306_01/server.102/b14200/functions172.htm
TO_DATE
函数需要 CHAR
、VARCHAR2
、NCHAR
或 NVARCHAR2
类型作为其第一个参数:
http://docs.oracle.com/cd/B19306_01/server.102/b14200/functions183.htm
该过程将 SYSDATE(DATE 类型)作为第一个参数传递,该参数应为字符串(VARCHAR、CHAR 等)。在这种情况下,Oracle 在内部使用 TO_CHAR 函数执行 DATE 到 CHHAR/VARCHAR2 的隐式转换。
可以说上面的表达式在内部被转换为:
TO_DATE( TO_CHAR( sysdate ) , 'DD-MON-YYYY HH:MI:SS' )
可以在此处找到有关隐式转换规则的更多信息(滚动到部分:“数据转换 - 隐式和显式数据转换”):
https://docs.oracle.com/cd/B19306_01/server.102/b14200/sql_elements002.htm
上面的一个重要片段link:
Implicit conversion depends on the context in which it occurs and may not work the same way in every case. For example, implicit conversion from a datetime value to a VARCHAR2 value may return an unexpected year depending on the value of the NLS_DATE_FORMAT parameter.
换句话说 - TO_CHAR( some-date )
没有第二个参数(格式)使用从会话中获取的 NLS_DATE_FOMRAT 变量值。
如果在SQL-Developer上勾选这个参数,大概是:'DD-MON-YYYY HH:MI:SS'(在SQL-Developer中这个参数的值是在option中配置的:Tools/Preferences/Database/NLS
但是如果你检查 SQL-Plus 中的 NLS_DATE_FORMAT 值,它将与 'DD-MON-YYYY HH:MI:SS' 不同。 SQL-Plus 根据环境的语言设置(Windows、Linux 等)和 NLS_LANG 环境变量(如果存在)确定 NLS 设置的值。
您可以使用以下方法在您的会话中更改此参数:
ALTER SESSION SET NLS_DATE_FORMAT = 'DD-MON-YYYY HH:MI:SS';
并且(旧)程序将起作用。