2011-03-29 83 views
0

我試圖從.net在oracle中存儲日期時間值,當日期時間被持久化到數據庫時,時間信息丟失。Oracle時間戳記數據類型缺少時間信息

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; 

任何想法,爲什麼時間戳正在失去的時間信息?

+0

什麼是列數據類型? – 2011-03-29 18:21:58

+0

@kevincline,列數據類型是時間戳 – vradenburg 2011-03-29 18:33:56

回答

2

好吧,我想我已經找出了問題是什麼。在上面的例子中,我從存儲過程中省略了一些額外的參數。我在查詢中有其他參數,其中一些參數是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 

因此,即使參數是nam ed,看起來好像參數的名稱是不相關的,並且參數以.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

DateField可以保留時間到SECOND,時間戳可以保存小數秒,所以您可能不需要時間戳,除非你需要提供的精度。 – Harrison 2011-03-30 11:41:10

+0

啊,非常瞭解@哈里森。我的假設是,它只是日期,但這是因爲我的參數是相反的,我期望時間信息的字段只有日期信息。謝謝你的幫助。 – vradenburg 2011-03-30 13:17:31

+0

關於參數順序問題,您需要設置'cmd.BindByName = true':https://docs.oracle.com/database/122/ODPNT/CommandBindByName.htm – 2017-10-04 23:36:20

0

當你發出這個選擇,你怎麼看:

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

該查詢的結果是07/07/2011 00:00:00 – vradenburg 2011-03-29 18:33:30

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 

如果anythi

ng,嘗試這樣的東西,看看它是否工作,然後回去檢查你的程序,看看有什麼東西看起來不錯(像一個任性的trunc)