在数据库

时间:2016-11-28 16:29:49

标签: c# oracle oracle-manageddataaccess

我正在尝试更新一个类型为TIMESTAMP(0) WITH TIMEZONE的列的表。

我已经尝试了几种方法但没有成功,因为TIMESTAMP写入数据库的方式没有美国东部时间的-05:00等偏移格式。它使用AMERICA/NEW_YORK作为时区进行保存,这会导致另一个无法正确处理此问题的应用程序出现问题。

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

希望: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 个答案:

答案 0 :(得分: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();

OracleDbType不是Varchar2,必须是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值时,Oracle会使用时区TIMESTAMP WITH TIME ZONE隐式转换为-05:00

注意,America / New_York有夏令时,即您必须使这些命令更具动态,并且每年在-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无法处理jQuery(function() { $('.abc').datetimepicker({ minDate: 0 }); });等时区名称。