1

我在oracle中有一个程序:

CREATE OR REPLACE 
PROCEDURE ONE
    (
    p_GUID IN ONE.GUID%TYPE,
    p_START_DATE IN ONE.START_DATE%TYPE,
    p_END_DATE IN ONE.END_DATE%TYPE,
    p_RETURN OUT INTEGER
    )
AS
BEGIN
    INSERT INTO ONETABLE (GUID, START_DATE, END_DATE)
  VALUES (p_GUID, to_date(p_START_DATE, 'YYYY-MM-DD HH24:MI:SS'), to_date(p_END_DATE, 'YYYY-MM-DD HH24:MI:SS'));
    COMMIT;
  EXCEPTION
        WHEN OTHERS THEN
        p_RETURN:= 1;
END;

编辑,因为人们似乎说要试试这个(这也不起作用,我尝试使用 to_date (上面的例子)来尝试解决问题):

CREATE OR REPLACE 
PROCEDURE ONE
    (
    p_GUID IN ONE.GUID%TYPE,
    p_START_DATE IN ONE.START_DATE%TYPE,
    p_END_DATE IN ONE.END_DATE%TYPE,
    p_RETURN OUT INTEGER
    )
AS
BEGIN
    INSERT INTO ONETABLE (GUID, START_DATE, END_DATE)
  VALUES (p_GUID, p_START_DATE, p_END_DATE);
    COMMIT;
  EXCEPTION
        WHEN OTHERS THEN
        p_RETURN:= 1;
END;

当从 c# 调用它时(例如使用 DateTime.NOW) - 它失败了。

仅当开始日期和结束日期的格式为 2013 年 4 月 5 日时,它似乎才有效。但是我如何在输入中获得时间呢?

如果我更换

p_START_DATE, 'YYYY-MM-DD HH24:MI:SS'

'2013-05-13 12:13:14', 'YYYY-MM-DD HH24:MI:SS'

这可行,但是在从 c# 调用该过程时它失败了。

此外,如果我从 db 客户端手动运行该过程,我仍然必须输入 05-apr-2013 并且只有这样才有效。如果我尝试,我无法输入时间,因为它会失败。

开始日期和结束日期是 oracle db 中的 DATE 类型。

--

根据我的尝试,我会收到不同的消息。

正如我调查的那样,这似乎与此有关:

SELECT value FROM v$nls_parameters WHERE parameter ='NLS_DATE_FORMAT';

返回:

DD-MON-RR

我不能改变它,因为我不是数据库所有者。

--

那么如何获得时间部分呢?

这是完整的SQL:

select parameter, value from nls_session_parameters;

返回:

NLS_LANGUAGE    AMERICAN
NLS_TERRITORY   AMERICA
NLS_CURRENCY    $
NLS_ISO_CURRENCY    AMERICA
NLS_NUMERIC_CHARACTERS  . 
NLS_CALENDAR    GREGORIAN
NLS_DATE_FORMAT DD-MON-RR
NLS_DATE_LANGUAGE   AMERICAN
NLS_SORT    BINARY
NLS_TIME_FORMAT HH.MI.SSXFF AM
NLS_TIMESTAMP_FORMAT    DD-MON-RR HH.MI.SSXFF AM
NLS_TIME_TZ_FORMAT  HH.MI.SSXFF AM TZR
NLS_TIMESTAMP_TZ_FORMAT DD-MON-RR HH.MI.SSXFF AM TZR
NLS_DUAL_CURRENCY   $
NLS_COMP    BINARY
NLS_LENGTH_SEMANTICS    BYTE
NLS_NCHAR_CONV_EXCP FALSE
4

2 回答 2

2

由于您的列是DATEoracle 类型,因此您的插入错误。

你不应该这样做

to_date(p_START_DATE, 'YYYY-MM-DD HH24:MI:SS')

而是插入

INSERT INTO ONETABLE (GUID, START_DATE, END_DATE)
  VALUES (p_GUID, p_START_DATE, p_END_DATE);

通过在日期上执行 to_Date ,您将强制从日期转换为字符并再次返回日期。换句话说,你的字符串:

to_date(p_START_DATE, 'YYYY-MM-DD HH24:MI:SS')

默默地转换为

to_date(to_char(p_START_DATE, NLS_DATE_FORMAT), 'YYYY-MM-DD HH24:MI:SS')

即在你的情况下,可能:

to_date(to_char(p_START_DATE, 'DD-MON-RR'), 'YYYY-MM-DD HH24:MI:SS')

由于您的函数输入是 %TYPE (这很好),它们也是日期:

p_START_DATE IN ONE.START_DATE%TYPE

所以请确保,当您将输入传递给函数时,您传递的是日期类型而不是字符串。

例子:

SQL> CREATE OR REPLACE  PROCEDURE ONE
  2      (
  3      p_GUID IN ONETABLE.GUID%TYPE,
  4      p_START_DATE IN ONETABLE.START_DATE%TYPE,
  5      p_END_DATE IN ONETABLE.END_DATE%TYPE,
  6      p_RETURN OUT INTEGER
  7      )
  8  AS
  9  BEGIN
 10      INSERT INTO ONETABLE (GUID, START_DATE, END_DATE)
 11    VALUES (p_GUID, p_START_DATE, p_END_DATE);
 12      COMMIT;
 13    EXCEPTION
 14          WHEN OTHERS THEN
 15          p_RETURN:= 1;
 16  END;
 17  /

Procedure created.

SQL> var r number
SQL> exec ONE('abc', to_date('2013-05-13 12:13:14', 'YYYY-MM-DD HH24:MI:SS'),  to_date('2013-05-14 01:13:14', 'YYYY-MM-DD HH24:MI:SS'), :r);

PL/SQL procedure successfully completed.

SQL> select * from onetable;

GUID                 START_DATE         END_DATE
-------------------- ------------------ ------------------
abc                  13-may-13 12:13:14 14-may-13 01:13:14
abc                  13-may-13 12:13:14 14-may-13 01:13:14

vs 你是隐式转换:

SQL> CREATE OR REPLACE  PROCEDURE ONE
  2      (
  3      p_GUID IN ONETABLE.GUID%TYPE,
  4      p_START_DATE IN ONETABLE.START_DATE%TYPE,
  5      p_END_DATE IN ONETABLE.END_DATE%TYPE,
  6      p_RETURN OUT INTEGER
  7      )
  8  AS
  9  BEGIN
 10      INSERT INTO ONETABLE (GUID, START_DATE, END_DATE)
 11    VALUES (p_GUID, to_date(p_START_DATE, 'YYYY-MM-DD HH24:MI:SS'), to_date(p_END_DATE, 'YYYY-MM-DD HH24:MI:SS'));
 12      COMMIT;
 13
 14  END;
 15  /

Procedure created.

SQL> alter session set nls_date_format='dd-mon-yy';

Session altered.

SQL> var r number
SQL> exec ONE('abc', to_date('2013-05-13 12:13:14', 'YYYY-MM-DD HH24:MI:SS'),  to_date('2013-05-14 01:13:14', 'YYYY-MM-DD HH24:MI:SS'), :r);

PL/SQL procedure successfully completed.

SQL> alter session set nls_date_format='dd-mon-rrrr hh24:mi:ss';

Session altered.

SQL> select * from onetable;

GUID                 START_DATE           END_DATE
-------------------- -------------------- --------------------
abc                  13-may-0013 00:00:00 13-may-0014 00:00:00

存储了错误的日期..或使用不同的 NLS 设置:

SQL> alter session set nls_date_format='dd-mon';

Session altered.

SQL> var r number
SQL> exec ONE('abc', to_date('2013-05-13 12:13:14', 'YYYY-MM-DD HH24:MI:SS'),  to_date('2013-05-14 01:13:14', 'YYYY-MM-DD HH24:MI:SS'), :r);
BEGIN ONE('abc', to_date('2013-05-13 12:13:14', 'YYYY-MM-DD HH24:MI:SS'),  to_date('2013-05-14 01:13:14', 'YYYY-MM-DD HH24:MI:SS'), :r); END;

*
ERROR at line 1:
ORA-01858: a non-numeric character was found where a numeric was expected
ORA-06512: at "TEST.ONE", line 10
ORA-06512: at line 1
于 2013-04-05T12:38:21.623 回答
1

无需将函数转换为DATE类型。已经约会了 只需插入传入参数的值:

    INSERT INTO ONETABLE (GUID, START_DATE, END_DATE)
  VALUES (p_GUID, p_START_DATE, p_END_DATE);

更新

但是,如果上面的变体不起作用并且您看到出现错误,则必须在客户端检查存储过程参数定义。您可以验证p_START_DATE客户端的参数是否具有 DateTime 类型?

更新 2

客户端有错误。尝试初始化日期参数,如下例所示:

OracleParameter p1 = new OracleParameter();
p1.DbType = DbType.DateTime;
p1.Value = System.DateTime.Now;

错误的原因可能是 C# 组件将参数视为字符串并将其转换为具有默认 OS 格式的字符串,然后通过查询将其传递给 Oracle。Oracle 试图将该字符串解析为ONE存储过程定义中指定的日期类型,但由于需要 NLS_DATE_FORMAT 参数的默认格式而失败。

更新 3

@b0x0rz 在评论中解释了错误的真正原因(错误的返回类型)。无论如何,这是客户端的错误...

于 2013-04-05T13:11:18.967 回答