(A)
という名前の列を含むテーブルがありますconfirmation_number
。として定義され、 のvarchar2(30)
ようなものが含まれていますSMITERI-2012-02-31-4567
。
(B)
という名前の列も含む別のテーブルがconfirmation_number
あり、それもvarchar2(30)
.
からデータを抽出しA
、それに何らかの変換を実行するストアド プロシージャがあり、確認番号列が含まれています。
C#
andを使用しODP.Net
てストアド プロシージャを実行し、それをロードDataTable
します。次に、いくつかの追加の変換を実行します。ただし、確認番号欄には一切触れません。
最後に、OracleBulkCopy
オブジェクトを作成し、列のマッピングを設定し、それをupdate
Tableに伝えてB
、 を呼び出しますloader.WriteToServer(dataTable)
。
次のエラーが表示されます。
Input string was not in a correct format.
at System.Number.StringToNumber(String str, NumberStyles options, NumberBuffer& number, NumberFormatInfo info, Boolean parseDecimal)
at System.Number.ParseInt64(String value, NumberStyles options, NumberFormatInfo numfmt)
at Oracle.DataAccess.Client.OracleBulkCopy.PerformBulkCopy()
confirmation_number
その列をロードしなければ、データロードは成功するため、列でエラーが発生することを確認しました。
BulkCopy
が を に変えようとする理由はvarchar(2)
ありNumber
ますか?
編集: 次の関連する問題を確認しました。
これは、確認番号以外にも発生しています。これは、文字列から文字列へ、または文字列から整数へのいずれであっても、文字列列でのみ問題になるようです。
これはすべての varchar2 列で発生するわけではありません - 姓と名には問題ありません。
これは、NULL 値を持たない列 (確認番号) と、NULL 値を持つ可能性がある列 (ストリート タイプ) の両方で発生します。
ローダーが開始される前の瞬間にデータテーブルの内容を調査すると、正常に入る列とそうでない列の間で列定義に違いは見られません。
BulkCopy 自体にバグがあるのではないか、別のユーティリティを使用してこの読み込みを行う必要があるのではないかと考え始めています。
編集:
以下は、トリミングされたコードです。
表 A
CREATE TABLE "APPS_UNPROCESSED"
( "LAST_NAME" VARCHAR2(30 BYTE),
"FIRST_NAME" VARCHAR2(30 BYTE),
"MIDDLE_NAME" VARCHAR2(30 BYTE),
"NAME_SUFFIX" VARCHAR2(30 BYTE),
"GENDER" VARCHAR2(1 BYTE),
"DATE_OF_BIRTH" VARCHAR2(10 BYTE),
"ID" NUMBER,
:
:
"CONFIRMATION_NUMBER" VARCHAR2(30 BYTE) NOT NULL ENABLE,
"IS_FBO" NUMBER(1,0),
:
:
CONSTRAINT "VR_APPS_UNPROCESSED_PK" PRIMARY KEY ("CONFIRMATION_NUMBER")
表 B
CREATE TABLE "APPS_PROCESSED"
( "LAST_NAME" VARCHAR2(30 BYTE),
"FIRST_NAME" VARCHAR2(30 BYTE),
"MIDDLE_NAME" VARCHAR2(30 BYTE),
"NAME_SUFFIX" VARCHAR2(30 BYTE),
"GENDER" NUMBER(1,0),
"DATE_OF_BIRTH" DATE,
:
:
"CONFIRMATION_NUMBER" VARCHAR2(30 BYTE),
"ID" NUMBER,
"IS_FBO" NUMBER(1,0),
:
:
"ID" NUMBER NOT NULL ENABLE,
:
:
CONSTRAINT "VR_APPLICATION_PK" PRIMARY KEY ("ID")
手順
procedure getUnprocessedApps(results OUT sys_refcursor)
as
BEGIN
open results for
select
a.last_name
,a.first_name
,a.middle_name
,a.name_suffix
,decode(a.gender, 'M', 1, 0) as gender_id
,a.gender as gender_code
,to_char(to_date(a.date_of_birth, 'MM-DD-YYYY'), 'DD-mon-YYYY') as date_of_birth
,cast(a.confirmation_number as varchar2(30)) as confirmation_number
,a.id
,0 as is_fbo
:
:
from vr_apps_unprocessed a
データの取得
DataSet data = new DataSet();
OracleConnection conn = null;
OracleCommand cmd = null;
OracleDataAdapter data_adapter = new OracleDataAdapter();
//fetch the data and load
using (conn = new OracleConnection(connString))
{
using (cmd = new OracleCommand())
{
cmd.Connection = conn;
cmd.CommandText = "APPS.getUnprocessedApps";
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("results", OracleDbType.RefCursor, ParameterDirection.Output);
conn.Open();
data_adapter.SelectCommand = cmd;
data_adapter.Fill(data, "results");
}
}
return data.Tables["results"];
列マッピングを設定する
private static Dictionary<string, string> ColumnMappings()
{
Dictionary<string, string> mapping = new Dictionary<string, string>();
mapping.Add("last_name", "last_name");
mapping.Add("first_name", "first_name");
mapping.Add("middle_name", "middle_name");
mapping.Add("name_suffix", "name_suffix");
mapping.Add("gender_id", "gender");
mapping.Add("date_of_birth", "date_of_birth");
mapping.Add("is_fbo", "is_fbo");
mapping.Add("confirmation_number", "confirmation_number");
mapping.Add("id", "id");
:
:
return mapping;
}
ファイルの読み込み
private static void loadFiles(DataTable dt, string connString)
{
OracleConnection orclconn = null;
OracleBulkCopy loader = null;
//now insert the data into Oracle
using (orclconn = new OracleConnection(connString))
{
orclconn.Open();
using (loader = new OracleBulkCopy(orclconn))
{
loader.DestinationTableName = "APPS_Processed"
foreach (KeyValuePair<string, string> k in ColumnMappings())
{
loader.ColumnMappings.Add(k.Key, k.Value);
}
loader.WriteToServer(dt);
} //end using oracle bulk loader
} //end using oracle connection
}
編集: 一括コピーを機能させることができませんでしたが、配列を使用して機能させる従来の方法を取得しました: http://www.oracle.com/technetwork/issue-archive/2009/09-sep/o59odpnet- 085168.html
一括読み込みが成功するよりも確実に遅くなりますが、少なくともデータを取得することはできます。ただし、一括コピー自体が失敗し続ける理由について何か考えがある人がいれば幸いです。