<!doctype HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html lang="ja">
<head>

<!--#include file="head_common.html" -->

	<title>JDBCでDBアクセス CSVファイルによるインポート・エクスポート</TITLE>
</head>
<body>
	<script LANGUAGE="JAVASCRIPT">
	<!--
	var ID="100258178-csv";
	var AD=0;
	var FRAME=0;
	// -->
	</script>
	<script LANGUAGE="JAVASCRIPT" SRC="http://j1.ax.xrea.com/l.j?id=100258178">
	</script>
	<noscript>
		<a HREF="http://w1.ax.xrea.com/c.f?id=100258178" TARGET="_blank"><IMG SRC="http://w1.ax.xrea.com/l.f?id=100258178-csv&url=X" BORDER="0"></A>
	</noscript>

<!--#include file="header.html" -->

	<h2>
		<a name=import>CSVインポート機能</a>
	</h2>
	<p>
		既存データがあった時の動作が特徴で、updateとinsertの自働判断も指定できます。
		<a href="#csv">具体例による機能紹介</A>
		も参考にして下さい。
		詳細なファイル仕様は
		<a href="#siyou">CSVファイルの仕様</A>
		にまとめてあります。
	</p>
	<p>
		<strong>”いまいち何が起こるのか分からない”　”本当に大丈夫か？”　と思う時は、迷わずＤＢＭＳ機能でバックアップしてから使用して下さい。</STRONG>
	</p>
	<p><IMG alt=TABWIN.GIF src="csvimport.gif"></P>
	<h3>データのインポート方法は、「重複データの扱い」で指示</H3>
	<p>既存データに対してどのようにＩＮＳＥＲＴするか？を切り替える事が出来ます。</P>
	<ul>
		<li>
			「常にINSERT」
			<p>データの存在チェックをせず、入力データを常にINSERTします。主キーの無いテーブルに対してインポートする時を想定してます。</P>
			<p>主キーのあるテーブル(一意性制約付きのテーブル)で一意性制約が発生した場合は、その時点でrollbackを発行し終了します。</P>
		</li>
		<li>
			「全件DELETE後INSERT」
			<p>最初に DELETE * FROM テーブル を行ってから、INSERTを行います。テーブル内容を全部入れ替える時を想定してます。</P>
		</li>
		<li>
		「UPDATE」
		<p>主キーで検索を行い、存在した場合はUPDATE、存在しない場合はINSERTを行います。WHERE句を自動生成する為制限があります。</P>
		<ul>
			<li>
			制限１&nbsp; CSVファイルの１行目にカラム名見出しが必要
			<li>
				制限２&nbsp; テーブル定義に主キーがある
				<li>制限３&nbsp; ＣＳＶファイルのカラムに主キーが含まれる。（主キー以外は省略されていてもＯＫ）</LI>
			</ul>
		</li>
		<li>
			「何もしない」
			<p>「UPDATE」の変形で、データが存在しない場合のみINSERTを行います。存在した場合は入力データを読み飛ばします。制限は「UPDATE」と同じです。</P>
		</li>
	</ul>
	<h3>カラムありのＳＱＬ文か？カラムなしＳＱＬ文か？　は、「項目見出し」で指示</H3>
	<ul>
		<li>
			「無し」
			<p>
				CSVの項目順が、テーブル定義のカラム順に完全一致している場合に使用します。過不足があっても駄目です。<br>
				発行されるＳＱＬ文は　　INSERT
				INTO テーブル名 VALUES(データ....); です。
			</p>
		</li>
		<li>
			「有り」
			<p>
				CSVの項目順と項目数が、テーブル定義と異なる場合に使用します。テーブルにカラム追加があって、もとりあえずインポート出来ます。					発行されるＳＱＬ文は　　INSERT
				INTO テーブル名 (カラム名...) VALUES(データ....);　です。
			</p>
		</li>
	</ul>
	<h3>組み合わせ</H3>
	<p>
		「重複データの扱い」と「項目見出し」を組み合わせれば、たぶんいろいろできると思うのですが、ややこしい気もします。
		機能はこのままでＧＵＩだけでも改善すれば、使いやすくなるかもしれません。
	</p>
	<p>ちなみに、自分が良く使うのは以下の組み合わせです。</p>
	<ul>
		<li>「項目見出し」＝「有り」</li>
		<li>「重複データの扱い」＝「UPDATE」</li>
		<li>「COMMIT方法」＝「最後に１回」</li>
	</ul>
	<p>時々”エラーが発生するまでとにかくインポート”という気分になるので、「COMMIT方法」＝「AutoCommit」でヤケッパチインポートもします。</p>
	<h3>カラム名見出し</H3>
	<p>最初にＣＳＶファイルを用意する時、カラム名を設定するのは面倒なのですが、以下のいずれかで簡単に作れます。</P>
	<p>
		<ul>
			<li>「項目見出し」＝「有り」のエクスポート</LI>
			<li>検索結果のクリップボードへコピー（見出しもつきます）</li>
		</ul>
	</p>
	<h2>
		<a name=siyou>
		CSVファイルの仕様
	</h2>
	<p>
		本ツールで認識するCSVファイルの形式を示します。
		<table>
		<tr>
			<th>　</th>
			<th>説明</th>
			<th>インポート(入力)</th>
			<th>エクスポート(出力)</th>
		</tr>
		<tr>
			<td>カラム名</td>
			<td>CSVなのでカラム名を持てないのですが、CSVファイルの１行目をカラム名行として扱えます。また、カラム行が存在せず１行目からデータが始まる指定も出来ます。</td>
			<td>実行画面で切替</td>
			<td>←</td>
		</tr>
		<tr>
			<td>項目区切り</td>
			<td>１行内の各項目の区切りは、タブ又はカンマを指定出来ます。</td>
			<td>実行画面で切替</td>
			<td>←</td>
		</tr>
		<tr>
			<td>文字コード</td>
			<td>ファイルの文字コードは、Java実行環境デフォルト UTF-8 EUC_JP Windows-31J Shift_JIS のいずれかを指定できます。ファイル入出力時にUNICODEとの変換で使用されます。DBへのアクセス時は一切影響しません。</td>
			<td>実行画面で切替</td>
			<td>←</td>
		</tr>
		<tr>
			<td>行区切り（改行コード）</td>
			<td>出力時改行コードは Java実行環境デフォルト \n \r\n \r のいずれかを指定できます。入力時は自働判定しますので指定しても無視されます。但し、クォートで括られた中の改行コードは行区切に認識されず、そのままデータとして扱われます。</td>
			<td>自働判定</td>
			<td>実行画面で切替</td>
		</tr>
		<tr>
			<td>クォート文字</td>
			<td>
				ダブルクォートのみです。データにタブ、カンマ、改行コードを含む時は文字列全体をダブルクォートで括ります。入力時に、先頭と終端のクォート文字は捨てられ、DBへは更新されません。
				ダブルクォート文字をデータとして扱う時はダブルクォートを連続させてください。
			</td>
			<td>自働判定</td>
			<td>自働付与</td>
		</tr>
		<tr>
			<td>SQLのヌル(NULL)値データ</td>
			<td>ヌル値は、#$%&NULL&%$# という文字列データとしてCSV上表現します。入出力時に、#$%&NULL&%$# と SQLのNull値は自動変換されます。なお、この文字列は設定画面で変更できます。</td>
			<td>デフォルトでは　#$%&NULL&%$#</td>
			<td>←</td>
		</tr>
		<tr>
			<td>空白</td>
			<td>空白は特別な意味を持ちません。また、自動的に切り捨てられる事もありません。例えば「△"あ"△」は「△あ△」として扱われます。</td>
			<td>特殊文字でない</td>
			<td>←</td>
		</tr>
		<tr>
			<td>数値項目</td>
			<td>
				入力時は、数値であっても全て文字列としてJDBCドライバに渡されます。文字列->
				数値変換は、JDBCドライバに任せています。<br>
				また、クォート文字で括られていても構いません。例えば「”１２３”」の場合、ツールで文字列の「１２３」になり、JDBCドライバが必要に応じて変換します。
			</td>
			<td>JDBCドライバが変換</td>
			<td>toString()で文字列化</td>
		</tr>
		<tr>
			<td>
				<a href="#bin">バイナリデータ</a>
			</td>
			<td>
				１６進表現文字列として扱います。例えば、バイナリデータの「X"0123"」は、CSVファイル上は「"0123"」（＝X"30313233"）となります。１６進文字列
				<->
				バイナリデータの変換はテーブル定義を参照し自動的に行われ、任意に指定する方法は現在ありません。
			</td>
			<td>自働変換</td>
			<td>自働変換</td>
		</tr>
		</table>
	</p>
	<p>ファイルの内容を先頭１００件迄プレビューする機能があり、ツールでどのように読み取られるかを確認できます。１００件以内でカラム数に不一致があるか？も検出できます。</p>
	<h2>
		<a name=csv>
		CSV入力の実行例
	</h2>
	<p>Importのいろいろな実行例を紹介します。</p>
	<ul>
		<li>
			<a href="#no1">入力ファイルのデータ行のみを置き換える</A>
		</li>
		<li>
			<a href="#no2">存在しない行だけ追加する</A>
		</li>
		<li>
			<a href="#no3">テーブルの内容を全部入れ替える／主キー定義が無いテーブルの更新</A>
		</li>
	</ul>
	<h3>
		<a name=no1>
		</a>
		入力ファイルのデータ行のみを置き換える
	</h3>
	<div>
		<p>
			以下のテーブルがあったとして、<br>
			<table border=3>
			<tr>
				<td>
					<strong>
						bookid<br>
						INTEGER
					</strong>
				</td>
				<td>
					title<br>
					VARCHAR(30)
				</td>
				<td>
					Murderer<br>
					VARCHAR(10)
				</td>
				<td>
					price<br>
					NUMERIC(8)
				</td>
			</tr>
			<tr>
				<td>1</TD>
				<td>そして誰もいなくなった</TD>
				<td>死んじゃったの？</TD>
				<td>600</TD>
			</tr>
			<tr>
				<td>2</TD>
				<td>アクロイド殺し</TD>
				<td>そんなの反則</TD>
				<td>650</TD>
			</tr>
			<tr>
				<td>3</TD>
				<td>オリエント急行の殺人</TD>
				<td>信じられん</TD>
				<td>700</TD>
			</tr>
			</table>
		</p>
		<p>
			色付き部分のように更新したいとします。bookidが主キーです。<br>
			<table border=3>
			<tr>
				<td>
					<strong>
						bookid<br>
						INTEGER
					</strong>
				</td>
				<td>
					title<br>
					VARCHAR(30)
				</td>
				<td>
					murderer<br>
					VARCHAR(10)
				</td>
				<td>
					price<br>
					NUMERIC(8)
				</td>
			</tr>
			<tr>
				<td>1</TD>
				<td>そして誰もいなくなった</TD>
				<td>死んじゃったの？</TD>
				<td>600</TD>
			</tr>
			<tr>
				<td>2</TD>
				<td>アクロイド殺し</TD>
				<td>そんなの反則</TD>
				<td class=update>750</TD>
			</tr>
			<tr>
				<td>3</TD>
				<td>オリエント急行の殺人</TD>
				<td>信じられん</TD>
				<td class=update>800</TD>
			</tr>
			<tr>
				<td class=update>4</TD>
				<td class=null>#null#</TD>
				<td class=null>#null#</TD>
				<td class=update>850</TD>
			</tr>
			</table>
		</p>
		<p>このようなCSVファイルを用意し、</P>
		<pre class=csv>
bookid,price<BR>2,750<BR>3,800<BR>4,850<BR>
</PRE>
		<p>
			CSV入力画面で、『項目見出し：
			<strong>有り</STRONG>
			、重複データの扱い：
			<strong>UPDATEする</STRONG>
			』を必ず指定します。<br>
			指定例はこんな感じ<br>
			<img alt="OPTION.GIF - 6,900BYTES" src="option.gif" border=1>
		</p>
		<p>
			テーブルに主キーが定義されている事と、ＣＳＶファイルの一行目がカラム名である事が必要です。これは実際に発行されるＳＱＬを考えれば、納得してもらえると思います。<br>
			以下のようなＳＱＬ文が実際に発行されます。
		</p>
		<ol>
			<li>
			<pre class=sql>
UPDATE xxxx SET bookid = 2 , price = 750 WHERE bookid = 2;　【auto commit;】
</PRE>
			<li>
			<pre class=sql>
UPDATE xxxx SET bookid = 3 , price = 800 WHERE bookid = 3;　【auto commit;】
</PRE>
			<li>
				<pre class=sql>
UPDATE xxxx SET bookid = 4 , price = 850 WHERE bookid = 4;　【auto commit;】<BR>但し、存在しないので引き続き<BR>INSERT xxxx ( bookid , price ) values (4 , 850 );　【auto commit;】
</PRE>
			</li>
		</ol>
	</div>
	<br>
	<h3>
		<a name=no2>
		</a>
		存在しない行だけ追加する
	</h3>
	<div>
		<p>
			先ほどの例はＣＳＶファイルの内容全てをテーブルに反映するのですが、一致したデータは更新せず、存在しないデータだけ追加したい事もあると思います。<br>
			このような時は入力ファイルからデータ事前にを除けば良いのですが、面倒です。<br>
		</p>
		<p>
			つまり、以下のテーブルがあったとして、<br>
			<table border=3>
			<tr>
				<td>
					<strong>
						bookid<br>
						INTEGER
					</strong>
				</td>
				<td>
					title<br>
					VARCHAR(30)
				</td>
				<td>
					Murderer<br>
					VARCHAR(10)
				</td>
				<td>
					price<br>
					NUMERIC(8)
				</td>
			</tr>
			<tr>
				<td>1</TD>
				<td>そして誰もいなくなった</TD>
				<td>死んじゃったの？</TD>
				<td>600</TD>
			</tr>
			<tr>
				<td>2</TD>
				<td>アクロイド殺し</TD>
				<td>そんなの反則</TD>
				<td>650</TD>
			</tr>
			<tr>
				<td>3</TD>
				<td>オリエント急行の殺人</TD>
				<td>信じられん</TD>
				<td>700</TD>
			</tr>
			</table>
		</p>
		<p>
			色付き部分を追加するとします。<br>
			<table border=3>
			<tr>
				<td>
					<strong>
						bookid<br>
						INTEGER
					</strong>
				</td>
				<td>
					title<br>
					VARCHAR(30)
				</td>
				<td>
					murderer<br>
					VARCHAR(10)
				</td>
				<td>
					price<br>
					NUMERIC(8)
				</td>
			</tr>
			<tr>
				<td>1</TD>
				<td>そして誰もいなくなった</TD>
				<td>死んじゃったの？</TD>
				<td>600</TD>
			</tr>
			<tr>
				<td>2</TD>
				<td>アクロイド殺し</TD>
				<td>そんなの反則</TD>
				<td>650</TD>
			</tr>
			<tr>
				<td>3</TD>
				<td>オリエント急行の殺人</TD>
				<td>信じられん</TD>
				<td>700</TD>
			</tr>
			<tr>
				<td class=update>4</TD>
				<td class=null>#null#</TD>
				<td class=null>#null#</TD>
				<td class=update>850</TD>
			</tr>
			</table>
		</p>
		<p>このようなCSVファイルしかないとします。（この場合、２行目と３行目を削除すればよいのですが、データ数が多ければ面倒です。）</P>
		<pre class=csv>
bookid,price<BR>2,750<BR>3,800<BR>4,850<BR>
</PRE>
		<p>
			CSV入力画面で、『項目見出し：
			<strong>有り</STRONG>
			、重複データの扱い：
			<strong>何もしない</STRONG>
			』を必ず指定します。<br>
			指定例はこんな感じ<br>
			<img alt="OPTION.GIF - 6,900BYTES" src="option2.gif" border=1>
		</p>
		<p>
			テーブルに主キーが定義されている事と、ＣＳＶファイルの一行目がカラム名である事が必要です。これは実際に発行されるＳＱＬを考えれば、納得してもらえると思います。<br>
			以下のようなＳＱＬ文が実際に発行されます。
		</p>
		<ol>
			<li>
			<pre class=sql>
SELECT COUNT(*) FROM xxxx WHERE bookid = 2;　【auto commit;】<BR>１件なので何もしない
</PRE>
			<li>
			<pre class=sql>
SELECT COUNT(*) FROM xxxx WHERE bookid = 3;　【auto commit;】<BR>１件なので何もしない
</PRE>
			<li>
				<pre class=sql>
SELECT COUNT(*) FROM xxxx WHERE bookid = 4;　【auto commit;】<BR>０件なので引き続き<BR>INSERT xxxx ( bookid , price ) values (4 , 850 );　【auto commit;】
</PRE>
			</li>
		</ol>
	</div>
	<br>
	<h3>
		<a name=no3>
		</a>
		テーブルの内容を全部入れ替える／主キー定義が無いテーブルの更新
	</h3>
	<div>
		<p>
			『既存の行を削除したい時はどうすれば良いか？』　残念ながら、特定の行を削除する機能は無いので、全件削除後に追加するしかありません。<br>
		</p>
		<p>
			つまり、以下のテーブルがあったとして、<br>
			<table border=3>
			<tr>
				<td>
					<strong>
						bookid<br>
						INTEGER
					</strong>
				</td>
				<td>
					title<br>
					VARCHAR(30)
				</td>
				<td>
					Murderer<br>
					VARCHAR(10)
				</td>
				<td>
					price<br>
					NUMERIC(8)
				</td>
			</tr>
			<tr>
				<td>1</TD>
				<td>そして誰もいなくなった</TD>
				<td>死んじゃったの？</TD>
				<td>600</TD>
			</tr>
			<tr>
				<td>2</TD>
				<td>アクロイド殺し</TD>
				<td>そんなの反則</TD>
				<td>650</TD>
			</tr>
			<tr>
				<td>3</TD>
				<td>オリエント急行の殺人</TD>
				<td>信じられん</TD>
				<td>700</TD>
			</tr>
			</table>
		</p>
		<p>
			色付き部分を追加するとします。<br>
			<table border=3>
			<tr>
				<td>
					<strong>
						bookid<br>
						INTEGER
					</strong>
				</td>
				<td>
					title<br>
					VARCHAR(30)
				</td>
				<td>
					murderer<br>
					VARCHAR(10)
				</td>
				<td>
					price<br>
					NUMERIC(8)
				</td>
			</tr>
			<tr>
				<td class=update>1</TD>
				<td class=update>そして誰もいなくなった</TD>
				<td class=null>#null#</TD>
				<td class=update>600</TD>
			</tr>
			<tr>
				<td class=update>5</TD>
				<td class=update>スタイルズ荘の怪事件</TD>
				<td class=null>#null#</TD>
				<td class=update>900</TD>
			</tr>
			<tr>
				<td class=update>6</TD>
				　　
				<td class=update>カーテン</TD>
				<td class=null>#null#</TD>
				<td class=update>950</TD>
			</tr>
			</table>
		</p>
		<p>
			このようなCSVファイルを用意します。カラム名を指定して処理されるので、項目の並びはどんな順番でも構いません。<br>
			&nbsp;また、mudererの値はCSVファイルに含まず、DEFAULT値で作成したいとします。
		</p>
		<pre class=csv>
bookid,price,title<BR>1,750,そして誰もいなくなった<BR>5,900,スタイルズ荘の怪事件<BR>6,950,カーテン<BR>
</PRE>
		<p>
			CSV入力画面で、『項目見出し：
			<strong>有り</STRONG>
			、重複データの扱い：
			<strong>全件DELETE後INSERT</STRONG>
			』を必ず指定します。<br>
			指定例はこんな感じ<br>
			<img alt="OPTION.GIF - 6,900BYTES" src="option3.gif" border=1>
		</p>
		<p>以下のようなＳＱＬ文が実際に発行されます。where句を必要としないので、主キーの有無に関係なく実行できます。</P>
		<ol>
			<li>
			<pre class=sql>
DELETE  FROM xxxx ;【auto commit;】
</PRE>
			<li>
			<pre class=sql>
INSERT xxxx ( bookid,price,title ) values (1,750,そして誰もいなくなった );　【auto commit;】
</PRE>
			<li>
				<pre class=sql>
INSERT xxxx ( bookid,price,title ) values (5,900,スタイルズ荘の怪事件 );　【auto commit;】
</PRE>
				<li>
					<pre class=sql>
INSERT xxxx ( bookid,price,title ) values (6,950,カーテン );　【auto commit;】
</PRE>
				</li>
			</ol>
		</div>
	</li>
	</ol>
	<h2>
		<a name=bin>
		バイナリデータの扱い
	</h2>
	<p>
		前述のＳＱＬ文中で、文字列を括るはずのクォートは、あえて記載しませんでした。値は、ＳＱＬ文全体をテキストとしてJDBCドライバに渡すのではなく、Stringオブジェクトの引数として渡しています。通常ＳＱＬ文をテキストとしてDBMSに渡す時は'
		'で括ると思いますが、引数として渡すのでそのような考慮は不要という方針です。
	</p>
	<p>これは『バイナリデータはオブジェクトで渡す』という処理を行う為です。</P>
	<p>
		基本的にはテーブル定義データ型とは無関係にStringオブジェクトをJDBCドライバに渡しており、Stringオブジェクト=&gt;テーブル定義データ型への変換はJDBCドライバに全て任しています。<br>
		例外はバイナリ系のデータ型です。Stringオブジェクトのままだと、文字コードの１６進文字列表現として格納されてしまいます。その為、テーブル定義データ型がバイナリの時は、入力ファイルの１６進文字列表現=&gt;バイト配列変換を自前で行い、JDBCドライバへはバイト配列(byte[])を渡しています。
	</p>
	<p>なお、バイナリとして扱うのは以下の時です。</P>
	<pre>
switch  (types) {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //typesはテーブル定義のSQLデータ型(java.sql.Types)
case Types.BINARY:
case Types.BLOB:
case Types.LONGVARBINARY:
case Types.VARBINARY:
&nbsp;&nbsp;&nbsp; return true;
</PRE>
	<h2>
		<a name=hist>
		</a>
		CSV入力履歴
	</h2>
	<p>
		一度実行したＣＳＶ入力条件は保存され、下記画面から繰返し実行できます。
		<img src="imphst.gif">
	</p>

<!--#include file="footer.html" -->

</body>
</html>
