0

我正在尝试更新具有 type 列的表TIMESTAMP(0) WITH TIMEZONE

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

当前的: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# 中完成此任务的正确方法是什么?日期/时间戳列是否应该始终使用字符串转换来写入?

4

1 回答 1

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 数据提供程序。当我检查文档时,它们似乎不支持数据类型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使用 Oracle 更新值时,TIMESTAMP将隐式转换为TIMESTAMP WITH TIME ZONEusing 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.

于 2016-11-29T07:48:29.043 回答