【问题标题】:How to get value of Oracle DATE column in C# code that matches SQL Developer's如何在 C# 代码中获取与 SQL Developer 匹配的 Oracle DATE 列的值
【发布时间】:2012-08-24 11:56:47
【问题描述】:

好的,我正在尝试获取 Oracle 11g 中 DATE 列的字符串值以传递给 C# 应用程序中的 UI(通过 WCF)。我想准确地显示我在 SQL Developer 中拉回 C# 中的字符串变量的内容。相反,当我有一个 Date 列时,我会得到一些非常古怪的解析 DateTime 值。

例子:

SQL Developer 中的值:26-AUG-75
VS 中来自 myDataRow[0].ToString() 的值:8/26/0975 12:00:00 AM

SQL Developer 中的价值:01-JUL-76
VS 中来自 myDataRow[0].ToString() 的值:7/1/1776 12:00:00 AM

Oracle 日期为look right。 VS 没有。谢谢,本富兰克林和Edward the Martyr。什么鬼?

SQL 很简单。我显然在更改字段名称,但就是这样:

SELECT DISTINCT(MyDate) FROM
User1.TableOfDates@DateTableLink 
WHERE MyDate IS NOT NULL ORDER BY
MyDate

向数据库抛出 SQL 的共享代码也很简单。我将在这里对它进行大量审查,但到目前为止它在其他任何地方都运行良好,而且我认为我已经掌握了重要的东西:

internal Oracle.DataAccess.Client.OracleConnection oracleConn;
...
DataTable dtReturn = new DataTable();
Oracle.DataAccess.Client.OracleCommand cmdTemp = null;
string strScrub = "";

// strScrub is magically loaded with SQL, which is, 
// if you grab it with a breakpoint here, after it's 
// scrubbed, equal to what I've written, above

cmdTemp = new Oracle.DataAccess.Client.OracleCommand(strScrub, this.oracleConn);
Oracle.DataAccess.Client.OracleDataReader dr = cmdTemp.ExecuteReader();
dtReturn.Load(dr);
dr.Dispose();
...
return dtReturn;

那部分有效。我只在此处包含它,以防我应该注意使用 Oracle.DataAccess 的某些东西。一切都打开和关闭并收集得很好。我们每天在开发中通过它发送数百条命令,在部署中至少有数千条。

以下是第一个值 (26-AUG-75) 的即时窗口中的一些信息,dr 现在代表从上面代码中提取的 DataTable 中的单个 DataRow

? DateTime.Parse(dr[0].ToString()) {8/26/0975 上午 12:00:00} 日期:{8/26/0975 12:00:00 AM} 天数:26 DayOfWeek: 星期六 日期:238 小时:0 种类:未指定 毫秒:0 分钟:0 月:8 第二:0 滴答声:307569312000000000 时间:{00:00:00} 年份:975

只用? dr[0]——它给出了同样的东西:

?dr[0]
{8/26/0975 上午 12:00:00}
    日期:{8/26/0975 12:00:00 AM}
    天数:26
    DayOfWeek: 星期六
    日期:238
    小时:0
    种类:未指定
    毫秒:0
    分钟:0
    月:8
    第二:0
    滴答声:307569312000000000
    时间:{00:00:00}
    年份:975

现在有趣的是,它是一个 DateTime,而它只是 Oracle 中的一个日期。也许我错过了有关 Oracle Dates 的一些东西...

?博士[0].GetType() {Name = "DateTime" FullName = "System.DateTime"}

无论如何,如果我能达到我在 SQL Developer 中看到的相同值(例如,26-AUG-75),我很好。我可以接受它并为所欲为。

隐式转换在哪里进行,我怎样才能早一点进入那里?

我应该补充一点,我无法使用 SELECT 语句和TO_CHAR 获得创意。这是一个相当复杂的自动化过程,它根据用户标准构建查询。因此,更改此 SELECT 将是“给机器一条鱼”而不是“教机器钓鱼”的答案。任何字段都可以是这种格式的日期,因此打开 GetType 值并在 C# 中解析一些创造性的方式是可以的,但更改 SQL 则不行。

编辑使用来自here的建议:

select dump(sysdate)today from dual; 

在上面的 SQL 中使用dump,从 SQL Developer 运行,我得到: Typ=12 Len=7: 119,175,8,26,1,1,1 用于 26-AUG-75 的行。所以甲骨文得到了正确的日期。

按照找到的转换说明here...

119 - 100 "excess" = 19 centuries == 1900
175 - 100 "excess" = 75     years ==   75

那是 1975 年。

【问题讨论】:

  • 原始值不是 26-AUG-75。这只是在某处应用的字符串转换 - 可能由 SQL Developer 应用,也可能由数据库本身应用。我确信甲骨文不会像这样存储它的Date 值。请注意,DateTime 是 .NET 中甚至用于“仅日期”的典型数据类型。 (我有一个日期/时间库可以纠正这个问题,但在这里对你没有帮助。)
  • 我是说你的“无论如何,如果我能得到原始值”是不正确的......
  • 好吧,我也会对“原始”值感到满意,不管它是什么。 ;^) 谢谢;固定。
  • 我怀疑你得到原始值 - 这不是你期望的值。
  • 在您的即时窗口中,您将从 Oracle 获得的日期时间(“原始”值)转换为字符串,然后将其解析回日期时间。我认为这就是事情出错的地方。尝试(在即时窗口中)输入“?dr[0]”,看看这是不是你想要的。

标签: c# .net oracle oracle11g


【解决方案1】:

从您的问题中不清楚,但我假设您实际上想要 1975 年和 1976 年?

我强烈怀疑值 0975 和 1776 是实际上数据库中的值。您在 SQL Developer 中的值只是 2 位数年份的表示。我怀疑如果您执行另一种使用 4 位数年份表示的字符串转换,您会看到相同的值。

所以,验证以上内容正确后的选项:

  • 找出坏数据是如何进入系统的,修复它(这样您就不会再收到任何坏数据),然后修复现有数据。
  • 通过忽略除年份的最后两位数字之外的所有数字,并强制它们进入适当的世纪来解决此问题。请注意,2 月 29 日前后可能有一些“有趣”的数据在某些年份有效,但在其他年份无效...

顺便说一句,我强烈建议转换为 DateTime 而不是转换为字符串然后解析它。

【讨论】:

  • 基本正确。更清楚地说,我希望我可以将 WHERE 子句中的值放入该原始表,并从它最初提取的数据库中获取相同的行。现在,如果我在 SQL Developer 中添加WHERE MyDate = '26-AUG-75',我会得到我想要的行。 '8/26/0975 12:00:00 AM' 我无法(有效地)做任何事情
  • @ruffin:我怀疑 Oracle 正在某个地方执行字符串转换……但弄清楚你真正得到了什么数据是绝对重要的。您应该尽可能避免使用 2 位数年份格式。
  • 是否有一种简单的方法可以查看 Oracle 认为“原始”值是什么?如果字面上是“26-AUG-75”,我希望甲骨文默认为 1975 年,对吗?同意两位数年份;担心系统早于我的参与。但是如果你问我“26-AUG-75”是否是坏数据,我可能会说它不是很好,但不,不是“坏”,可以这么说。正如您所说,somewhere. 正在进行古怪的字符串转换
  • 我认为,上面的dump 测试以及 to_char() 似乎表明它正在发生在 .NET 方面。我现在可能不得不接受建议 2。
  • 尽管数据库中似乎确实有 1975 和 1976,但究竟在哪里解析不正确仍然是个谜。从长远来看,我想跟进选项 1,但我想现在选项 2 是正确的答案。感谢您的帮助。
猜你喜欢
  • 2016-10-25
  • 2018-02-21
  • 2021-03-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-08
  • 1970-01-01
  • 2019-01-30
相关资源
最近更新 更多