Oracle timestamp数据类型缺少时间信息

时间:2011-03-29 18:17:54

标签: oracle datetime timestamp

我正在尝试在.net中将日期时间值存储在oracle中,当日期时间持续到db时,时间信息丢失。

db是11g,我正在使用Oracle.DataAccess程序集版本2.111.6.20中的OracleCommand和OracleConnection类。

我在.net中有一个调用oracle存储过程的数据层。有问题的日期字段的参数是IN参数,它是标记为TimeStamp数据类型。表中的字段也定义为TimeStamp。

// Add the parameter to the OracleCommand
var dt = new DateTime(2011,07,07,10,0,0);
cmd.Parameters.Add("RECEIVED", OracleDbType.TimeStamp, 6, dt, System.Data.ParameterDirection.Input);
cmd.ExecuteNonQuery();

参数的值确实包含时间信息(上午10点),但当它持久保存到数据库时,时间信息丢失。

我的存储过程看起来像这样...

create or replace
PROCEDURE DATA_INSERT 
(
  ID OUT NUMBER
, RECEIVED IN TIMESTAMP
) AS 
BEGIN

  ID := MY_SEQUENCE.nextval;
  INSERT INTO DATA (ID, RECEIVED) VALUES (ID, RECEIVED);

END DATA_INSERT;

知道为什么时间戳会丢失时间信息吗?

4 个答案:

答案 0 :(得分:2)

好的,我想我已经弄清楚问题是什么了。在上面的例子中,我从存储的proc中省略了一些额外的参数以用于berevity。我在查询中有其他参数,其中一些是数据类型DATE。所以,请考虑下表...

  CREATE TABLE TEST (DATE_FIELD DATE, TIMESTAMP_FIELD TIMESTAMP);

存储过程......

CREATE OR REPLACE PROCEDURE TEST_INSERT ( P_DATE IN DATE, P_TIMESTAMP IN TIMESTAMP ) AS 
BEGIN
  INSERT INTO TEST(DATE_FIELD, TIMESTAMP_FIELD) VALUES(P_DATE, P_TIMESTAMP);
END TEST_INSERT;

以下c#...

using (var cmd = new OracleCommand("TEST_INSERT", conn))
{
    cmd.CommandType = System.Data.CommandType.StoredProcedure;
    cmd.Parameters.Add("P_TIMESTAMP", OracleDbType.TimeStamp
        , new DateTime(2011, 07, 07, 10, 0, 0), System.Data.ParameterDirection.Input);
    cmd.Parameters.Add("P_DATE", OracleDbType.Date
        , new DateTime(2011, 07, 08), System.Data.ParameterDirection.Input);

    cmd.ExecuteNonQuery();
}

结果将是......

DATE_FIELD: 11-07-07 
TIMESTAMP_FIELD: 11-07-08 00:00:00.000000000

因此,即使参数被命名,似乎参数的名称无关紧要,并且参数被添加到.net中的Parameters集合的顺序将决定存储过程中参数的值

所以,在c#片段中,如果你颠倒了将参数添加到集合中的顺序......

cmd.Parameters.Add("P_DATE", OracleDbType.Date
     , new DateTime(2011, 07, 08), System.Data.ParameterDirection.Input);
cmd.Parameters.Add("P_TIMESTAMP", OracleDbType.TimeStamp
     , new DateTime(2011, 07, 07, 10, 0, 0), System.Data.ParameterDirection.Input);

然后结果将是......

DATE_FIELD: 11-07-08 
TIMESTAMP_FIELD: 11-07-07 10:00:000000000

答案 1 :(得分:0)

当你发出这个选择时,你看到了什么:

SELECT TO_CHAR(RECEIVED, 'MM/DD/YYYY HH24:MI:SS') FROM data WHERE ID = <value>;

答案 2 :(得分:0)

我将您的代码运行到一个表中,我的结果是(07-JUL-11 10.00.00.000000000 AM),这是预期的。我看到您对列和参数使用相同的名称,尝试预先挂起变量名称的“p_”前面并查看它是否有效

这就是我跑的: 在Oracle中:

 create table t_data(received timestamp);

在c#

  Oracle.DataAccess.Client.OracleCommand cmd = new Oracle.DataAccess.Client.OracleCommand("BEGIN INSERT INTO t_DATA (RECEIVED) VALUES (:RECEIVED); END;",con);
        // Add the parameter to the OracleCommand
        DateTime dt = new DateTime(2011,07,07,10,0,0);
        cmd.Parameters.Add("RECEIVED", OracleDbType.TimeStamp, 6, dt, System.Data.ParameterDirection.Input);
        cmd.ExecuteNonQuery();

回到Oracle

   select * from t_data            

RECEIVED                  
------------------------- 
07-JUL-11 10.00.00.000000000 AM 

如果有的话,试试这样的东西,看它是否有效,然后回去检查你的程序,看看是否有什么东西看起来不合适(像一个任性的截断)

答案 3 :(得分:0)

如果使用的是Oracle提供的dll,则默认情况下它通常绑定变量。在执行以绑定到名称之前,添加以下代码行。

cmd.BindByName = true;