Passing date to Stored Procedure in Oracle SQL error : ORA-01858

Passing date to Stored Procedure in Oracle SQL error : 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。我在网上搜索过类似的错误,但 none 帮助了我。我正在使用 Oracle 数据库 11g 快捷版。我的代码中可能存在一些小错误,但我不明白是什么。

非常感谢任何帮助!

错误的直接原因是你有

  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 将 fudge it 足够接近),那么您仍然会收到错误,或者更糟的是,您可能不会注意到不正确的转换和无效结果。

因此删除多余且危险的转换:

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;
/

如果需要,您当然可以将日期名称分配给字符串变量。我已经使用 the FM format modifier 来阻止它向右填充日期名称,因此您不需要 trim 它 - 句号只是为了证明它有效。如果你想要混合大小写的日期名称,你可以使用 '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 might be passed in any format. I am just converting it into DD-MM-YYYY format and storing into 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;

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