1

さて、Oracle 11gのDATE列の文字列値を取得してC#アプリのUIに(WCF経由で)渡そうとしています。SQL DeveloperでプルバックしているものをC#の文字列変数に正確に表示したいと思います。代わりに、Date列があると、代わりに非常に奇抜な解析済みのDateTime値が表示されます。

例:

SQL Developerの値:75年8月26日
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の日付は正しく見えます。VSはしません。ありがとう、ベン・フランクリンとエドワード殉教者。一体何?

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の使用から注意すべきことがある場合にのみ、ここに含めます。すべてが開閉され、正常に収集されます。devでは毎日数百のコマンドをスローし、デプロイでは少なくとも数千のコマンドをスローしています。

これが最初の値(26-AUG-75)のイミディエイトウィンドウからの情報で、上記のコードからプルされたdrシングルを表しています。DataRowDataTable

?DateTime.Parse(dr [0] .ToString())
{8/26/0975 12:00:00 AM}
    日付:{8/26/0975 12:00:00 AM}
    日:26
    DayOfWeek:土曜日
    DayOfYear:238
    時間:0
    種類:詳細不明
    ミリ秒:0
    分:0
    月:8
    2番目:0
    ダニ:307569312000000000
    TimeOfDay:{00:00:00}
    年:975

そしてちょうど? dr[0]-と同じことを与える:

?dr [0]
{8/26/0975 12:00:00 AM}
    日付:{8/26/0975 12:00:00 AM}
    日:26
    DayOfWeek:土曜日
    DayOfYear:238
    時間:0
    種類:詳細不明
    ミリ秒:0
    分:0
    月:8
    2番目:0
    ダニ:307569312000000000
    TimeOfDay:{00:00:00}
    年:975

興味深いことに、これは、Oracleの単なる日付である場合はDateTimeであることを示しています。たぶん私はOracleDatesについて何かが足りない...

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

とにかく、SQL Developerで表示されるのと同じ値(たとえば、26-AUG-75)に到達できれば、問題ありません。私はそれを取り、やりたいことが何でもできます。

暗黙の変換はどこで行われていますか?少し早くそこに入るにはどうすればよいですか?

SELECTステートメント&でクリエイティブになれないことを付け加えておきTO_CHARます。これはすべて、ユーザーの基準に基づいてクエリを作成する、かなり複雑な自動化されたプロセスです。したがって、このSELECTを変更すると、「マシンに魚を教える」ではなく、「マシンに魚を与える」という答えになります。この形式ではどのフィールドも日付になる可能性があるため、GetType値をオンにして、C#でクリエイティブな方法で解析することは問題ありませんが、SQLを変更することはできません。

ここからの提案を使用して編集

select dump(sysdate)today from dual; 

上記のSQLを使用dumpして、SQL Developerから実行すると、次のようになります Typ=12 Len=7: 119,175,8,26,1,1,1。26-AUG-75の行。したがって、オラクルは正しい日付を持っています。

ここにある変換手順に従って...

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

それは1975年です。

4

1 に答える 1

3

あなたの質問からは明らかではありませんが、あなたは実際に1975年と1976年を望んでいたと思いますか?

値0975と1776が実際にデータベースにあるものであると強く疑っています。SQL Developerでの値は、その2桁の年の表現にすぎません。4桁の年表現を使用する別の種類の文字列変換を実行すると、同じ値が表示されると思います。

したがって、上記が正しいことを検証した後のオプション:

  • 不良データがシステムにどのように取り込まれたかを調べ、それを修正して(これ以上不良データを取得しないように)、既存のデータを修正します。
  • 年の最後の2桁を除くすべてを無視し、適切な世紀に強制することで、この問題を回避します。2月29日が有効な年もあれば、そうでない年もあるという点で、いくつかの「興味深い」データが存在する可能性があることに注意してください...

DateTimeちなみに、文字列に変換してから解析するのではなく、にキャストすることを強くお勧めします。

于 2012-08-29T19:39:26.140 に答える