使用oracle在日期字段中插入时间段

时间:2013-04-05 11:43:52

标签: oracle datetime stored-procedures

我在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) - 它失败。

如果开始日期和结束日期的格式为05-apr-2013,则似乎只能起作用。但是我如何在那里和输入中获得时间?

如果我更换

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

使用

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

这样可行,但是从c#调用过程后它就失败了。

此外,如果我从数据库客户端手动运行该过程,我仍然需要输入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

2 个答案:

答案 0 :(得分:2)

由于您的列在oracle中的类型为DATE,因此插入错误。

你不应该做

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(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

答案 1 :(得分: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在注释中解释(错误的返回类型)。无论如何,这是客户端的错误...