在 Oracle SQL 中将日期传递到存储过程错误:ORA-01858



我知道这个问题以前已经回答过了,我已经尝试了他们给出的解决方案,但没有成功。

我有一个存储过程如下(我删除了不必要的部分(:

CREATE OR REPLACE PROCEDURE get_days(dt date)
IS
given_date DATE := TO_DATE('dt', 'DD-MON-YYYY');
BEGIN
get_day := RTRIM(TO_CHAR(dt1, 'DAY'));
DBMS_OUTPUT.PUT_LINE ('The day of the given date is '||get_day||);
DBMS_OUTPUT.PUT_LINE ('Execution  done successfully.');
END get_days;

我在将日期传递给程序get_days时遇到问题。我尝试了以下方法:

BEGIN
--Below I have listed all ways I have tried 
get_days('12/12/12');
get_days('12-12-12');
get_days(date '2012-12-12');  
get_days(TO_DATE( '01/01/2018', 'MM/DD/YYYY' ));
END;

我不知道出了什么问题,但我收到此错误 -ORA-01858: a non-numeric character was found where a numeric was expected.我在网上搜索过类似的错误,但没有帮助。我使用的是Oracle Database 11g Express 版。我的代码中可能存在一些小错误,但我不明白它是什么。

任何帮助都非常感谢!

错误的直接原因是你有

given_date DATE := TO_DATE('dt', 'DD-MON-YYYY');

而不是

given_date DATE := TO_DATE(dt, 'DD-MON-YYYY');

在您的版本中,您尝试将字符串文字'dt'转换为日期;该文字与您的dt参数没有任何关系。

但是,这仍然是错误的,因为dt已经声明为日期数据类型。如果你这样做,那么你真的在做:

given_date DATE := TO_DATE(TO_CHAR(dt), 'DD-MON-YYYY');

它将使用您当前的会话NLS_DATE_FORMAT将日期转换为字符串; 如果这也不是"DD-MON-YYYY"(或者足够接近 Oracle 会捏造它的东西(,那么您仍然会收到错误,或者更糟糕的是,不正确的转换和您可能没有注意到的无效结果。

因此,请删除冗余和危险的转换:

CREATE OR REPLACE PROCEDURE get_days(dt date)
IS
BEGIN
DBMS_OUTPUT.PUT_LINE ('The day of the given date is ' || TO_CHAR(dt, 'FMDAY') || '.');
DBMS_OUTPUT.PUT_LINE ('Execution  done successfully.');
END get_days;
/

当然,如果需要,您可以将日期名称分配给字符串变量。我使用了FM格式修饰符来阻止它右填充日期名称,因此您无需修剪它 - 句号只是为了证明它有效。如果您希望日期名称混合大小写,您可以使用'FMDay'而不是'FMDAY'

您应该始终传入日期,而不是字符串:

set serveroutput on;
BEGIN
get_days(date '2012-12-12');  
get_days(TO_DATE( '01/01/2018', 'MM/DD/YYYY' ));
END;
/
The day of the given date is WEDNESDAY.
Execution  done successfully.
The day of the given date is MONDAY.
Execution  done successfully.

PL/SQL procedure successfully completed.

DT 可以以任何格式传递。我只是将其转换为 DD-MM-YYYY 格式并存储为given_date

日期没有格式;它有一个内部表示,你很少需要知道或关心。当您查询日期值而不将其显式转换为字符串时,客户端会将其转换为人类可读的形式,通常使用NLS_DATE_FORMAT来决定以哪种格式显示它。因此,dt没有格式,即使调用方使用字符串进行调用(如前两个示例所示(,这些格式也会在调用之前隐式转换为日期(假设可能(;该过程永远不会看到这些字符串,它只会看到转换后的日期值。

我提供了解决有关该程序的查询的最佳答案。 您也可以通过自己运行来检查它

DECLARE
dt1 DATE := TO_DATE(TO_CHAR('19/03/2021'), 'DD-MM-YYYY');
get_day VARCHAR2(15);
BEGIN
get_day := RTRIM(TO_CHAR(dt1, 'DAY'));
IF get_day IN ('SATURDAY', 'SUNDAY') THEN
dbms_output.new_line;
DBMS_OUTPUT.PUT_LINE 
('The day of the given date is '||get_day||' and it falls on weekend');
ELSE
dbms_output.new_line;
DBMS_OUTPUT.PUT_LINE ('The day of the given date is '||get_day||' and it does not fall 
on the weekend');
END IF;
DBMS_OUTPUT.PUT_LINE ('Execution  done successfully.');
END;

如果您有任何与此相关的进一步查询,请问我,我会尽快解决您的查询。如果有人想按用户输入日期,请问我....我也有这方面的代码。

最新更新