2016-11-28 76 views
0

我正在嘗試使用TIMESTAMP(0) WITH TIMEZONE類型的列對錶進行更新。用數據庫中的TIME ZONE值更新Oracle TIMESTAMP(0)的正確方法

我已經嘗試了幾種不成功的方法,因爲TIMESTAMP寫入數據庫的方式沒有美國東部時間的偏移格式,例如-05:00。它使用AMERICA/NEW_YORK作爲時區保存,這會導致另一個無法正確處理此問題的應用程序出現問題。

CURRENT:28-NOV-16 10.51.43.000000000 AM AMERICA/NEW_YORK

DESIRED:28-NOV-16 10.51.43.000000000 AM -05:00

的很多帖子這裏主要講來格式化,當它從數據庫中檢索到的數據;其他示例用SqlPlus描述,而不用C#描述。

Using(OracleConnection conn = new OracleConnection(......)) 
{ 
     OracleCommand cmd = new OracleCommand(); 
     cmd.Connection = conn; 
     cmd.BindByName = true; 
     cmd.CommandText = "update customer set email_addr = :EMAIL, modified_date= SYSDATE 
    where cust_id = :CUSTID"; 

     conn.Open(); 
     cmd.Parameters.Add("EMAIL", OracleDbType.Varchar2).Value = txtEmail.Text; 
     cmd.Parameters.Add("MODIFIED_DATE", OracleDbType.Varchar2).Value = OracleDate.GetSysDate().ToOracleTimeStamp(); 
     cmd.Parameters.Add("CUSTID", OracleDbType.Decimal).Value =Convert.ToDecimal(Session["ID"]); 

    cmd.ExecuteNonQuery(); 
} 

我也試過modified_date=to_timestamp(:modified_date, 'MM/DD/YYYY HH:mi:ss')但這會產生異常,因爲沒有格式正確的時區。

在C#中完成此操作的正確方法是什麼?應該總是使用字符串轉換來編寫日期/時間戳列?

回答

1

看起來像你在你的代碼中犯了一個錯字。您指定了2個綁定變量,但您嘗試綁定3個值。

OracleCommand cmd = new OracleCommand(); 
cmd.Connection = conn; 
cmd.BindByName = true; 
cmd.CommandText = "update customer set email_addr = :EMAIL, modified_date= :MODIFIED_DATE 
where cust_id = :CUSTID"; 

conn.Open(); 
cmd.Parameters.Add("EMAIL", OracleDbType.Varchar2).Value = txtEmail.Text; 
cmd.Parameters.Add("MODIFIED_DATE", OracleDbType.TimeStampTZ).Value = OracleDate.GetSysDate().ToOracleTimeStamp(); 
cmd.Parameters.Add("CUSTID", OracleDbType.Decimal).Value =Convert.ToDecimal(Session["ID"]); 
cmd.ExecuteNonQuery(); 

OracleDbTypeVarchar2,它必須是TimeStampTZ

但是,看起來您正在使用DevArt的Oracle Data Provider。當我檢查documentation它看起來像他們不支持數據類型TIMESTAMP WITH TIME ZONE

我看到幾種解決方法。

設置你的SESSIONTIMEZONE-05:00您在數據庫運行之前,你的操作,例如,作爲這樣的:

cmd.CommandText = "ALTER SESSION SET TIME_ZONE = '-05:00'"; 
cmd.ExecuteNonQuery(); 

然後你的C#代碼可以是這樣的:

OracleCommand cmd = new OracleCommand(); 
cmd.Connection = conn; 
cmd.BindByName = true; 
cmd.CommandText = "update customer set email_addr = :EMAIL, modified_date= CURRENT_TIMESTAMP 
where cust_id = :CUSTID"; 

conn.Open(); 
cmd.Parameters.Add("EMAIL", OracleDbType.Varchar2).Value = txtEmail.Text; 
cmd.Parameters.Add("CUSTID", OracleDbType.Decimal).Value =Convert.ToDecimal(Session["ID"]); 
cmd.ExecuteNonQuery(); 

CURRENT_TIMESTAMP返回當前時間你的會話時區爲TIMESTAMP WITH TIME ZONE數據類型。

您還可以指定時間段在SQL,例如:

cmd.CommandText = "update customer set email_addr = :EMAIL, 
     modified_date= SYSTIMESTAMP AT TIME ZONE '-05:00' 
    where cust_id = :CUSTID"; 

當您更新TIMESTAMP WITH TIME ZONE值與TIMESTAMP甲骨文將隱式轉換到使用時區-05:00TIMESTAMP WITH TIME ZONE

注意,美國/紐約有夏令時,即你必須讓這些命令的更多動態,一年-05:00-04:00之間切換的兩倍(這將是一個巨大的合意,如果你會使用時差區域像America/New_York) 。

另一個解決方法可能是在您的應用程序中運行ALTER SESSION SET NLS_TIMESTAMP_TZ_FORMAT = 'DD-MON-YY HH.MI:SS.FF AM TZH:TZM',該應用程序無法處理像AMERICA/NEW_YORK這樣的時區名稱。

+0

這正是我需要的,它也回答了另一個問題,我有有關設置會話參數。謝謝!順便說一句,當我使用SYSTIMESTAMP我自動獲得正確的時區,所以我沒有真正需要使用'在時間ZONE'。再次感謝你。 – Mobilemike

相關問題