こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

CSV形式のファイルを読み込んでテーブルに格納するには?

VB6でCSV形式のファイルを読み込んで
それをデータベースに書き込みたいのですがどうやれば
いいか分かりません・・・。

1レコードが1行に書かれている固定長のレコードなら
1行ずつ読み込んでそれをループさせてEOFになるまで
という風に読みこんでいたのですが、
CSVの場合はどのようにすればよいのでしょうか?
基本的には同じような考えのような気がするのですが。

プログラミング初心者ですみません。
どなたか分かりやすいサンプルなど教えてもらえませんでしょうか?

投稿日時 - 2002-11-11 14:03:10

QNo.401933

すぐに回答ほしいです

質問者が選んだベストアンサー

100万件のデータをCSVで読み込むなんて、大変ですね・・・

私が伝えた方法でやるとしたら、

バイナリで開く
GETで取得
REPLACE関数でダブルコーテを変換(っていうかダブルコーテを削除してしまう)
バイナリで開く
PUTでファイルに出力

という方法で置き換えができますが。。。

しかし大きいファイルを一度に行うとパフォーマンスが下がる気がします。
ですので、何分割かで読み込む必要があるかもしれません。
要は重要なのは件数ではなく、カラム数やファイルサイズの方です。

それではがんばってください。

投稿日時 - 2002-11-18 22:32:32

このQ&Aは役に立ちましたか?

1人が「このQ&Aが役に立った」と投票しています

回答(8)

ANo.7

バイナリで読み込む方法もあります。

参考URLは一度にファイルを取得する方法が出てきます。
イモガシさんの延長ですが、そのあと改行コードやカンマでSplit関数を使用するようにしてはいかがでしょうか。

参考URL先の「subTestRead」関数を使用して

dim varWk as variant
subTestRead "c:\test.csv",vbcrlf,varWk
とすると、行単位で配列にセットされます。

あとはUBOUNDとLBOUND関数を使用して、配列分のループをまわし、その中でSplit関数でカンマを区切ってあげると、できると思います。

参考URL:http://oshiete1.goo.ne.jp/kotaeru.php3?q=169686

投稿日時 - 2002-11-16 01:50:06

補足

いろいろ分かったことを補足します。

"aaa","bbb","ccc"のような区切りの
CSVファイルをサーバー上(SQLServer2000)のテーブルに格納するには
1.Bulk Insert
2.BCP
3.DTS
という方法もあるということが分かっていろいろ
調べたり質問した結果、

BULK INSERTで読込むことは可能だが、”を含んでロードしてしまうので、”を削除してからロードしないと駄目ということが分かりました。"を削除してから読込んでもいいのですが、例えば100万件のデータを読込む場合、"を削除する時間がどのくらいかかるのだろう?と思いました。
その問題はあるものの、一応選択肢は増えました。
(各項目が""で区切られているのが曲者のようです・・・)

100万件のデータを読込もうとしています。

総合的に見て少しでも早い方法を選択したいのですが、
ループさせて読込むのと
" を削除してからBULK INSERT で読込むのはどちらが早いのでしょう?
実際にやってみればいいのですが、感覚的な回答でいいのでみなさんの
考えを聞かせてもらえると大変助かります。

また、BCP や DTS を使えば各項目が " で区切られたファイルでも
スムーズに読込むことが実現可能なのかどうか(速度無視で)どなたか
分かる方教えてください。

投稿日時 - 2002-11-18 12:58:42

お礼

ありがとうございます!
少しずつできそうな気がしてきました。
やってみます!

投稿日時 - 2002-11-18 08:58:38

ANo.6

#5のものです。私の例が1レコード3項目(エクセルで言えば1行3列に当たる)を考えていたからなんで、3の倍数が出たのです。3に意味はありません。
それはそれとして、確信が持てないのですが、ファイルを読む時に、Input #1,a1,a2,a3の代わりに、Line Input #1,aとして、プログラムでaを、「,」でa1,a2,a3にSPLIT(分割)して、a1,a2,a3の処理をしたほうが、少し速くないですかね。

投稿日時 - 2002-11-15 19:09:44

補足

ありがとうございます!!
そういう少しでも速くなりそうなテクニックを探していたのです。
実際速くならなくても構いません。
なりそうじゃないかなー、程度のものでも教えて下さると助かります(他の方も)

投稿日時 - 2002-11-15 23:49:49

お礼

DTSパッケージなるものを使用すると
速そうなので、それについて今度は調べ始めました。

別に質問したので、もし何か少しでもわかることがあれば教えてくだされば
幸いです。よろしくお願いします。

投稿日時 - 2002-11-18 17:03:23

ANo.5

#2のものです。大変長い時間がかかるとのこと。
実感したことはないのですがパソコンで何十万件の
処理はむりなんですね。
原因はハッキリしていると思います。DISKのREAD
WRITEに時間がかかっているからなのです。
I/Oネック。DiskのREAD回数を減らすには
1回のREAD単位に、フィールドを1組でなく、多数組み入れることを、昔の大型コンピュターは工夫していました。しかしもう既にファイルが出来あがっているし、VBという言語ではそう言う考えもなく、無理でしょう。
APIレベルで高速READの方法があるかどうか私には判りません。改めてそれに絞ってご質問されて、専門家の
ご回答を待ってはとおもいます。
Input #1, a1, a2, a3をInput #1, a1, a2, a3 ,a4,
a5,a6・・・(3の倍数で)ふやしても少し短くなりませんでしょうかね。処理プログラムは少し変りますが。

投稿日時 - 2002-11-14 20:30:53

補足

再びの回答ありがとうございます!

そうなんですか。
今、Bulk Insert を使ってできないか検討中なのですが、うまくいきません。
うまくいかない場合は、少しでも速度が速くなる方法を模索したいと思います。

あと上記の3の倍数でというのはどういう意味なのか分からないです・・
すみません。

投稿日時 - 2002-11-15 09:22:54

ANo.4

失礼しました。
SQL鯖なのですね^^;
SQL文一発はADOかDAOのアクセスDBオンリーのようです。。。

実験してみたらできなかった。。。

実験した結果は、誰かが使ってくれるかも知れないので、一番後ろに載せておきます。


バルクは今まで使用したことがないので、ちょっと調べてみました。
ここの掲示板に思いっきりサンプル載ってました。
http://oshiete1.goo.ne.jp/kotaeru.php3?q=306391
http://oshiete1.goo.ne.jp/kotaeru.php3?q=262720
ストアドで書いておくといい感じかもしれませんね。




ってなわけで、無意味にADOでAccessDBに一発インポート
だれか使って!!

※CSVファイルは要ヘッダ
Private Sub Command1_Click()
  Dim adoCn  As ADODB.Connection
  Dim strSQL As String
  
  '接続
  Set adoCn = New ADODB.Connection
  adoCn.Open "Provider=Microsoft.Jet.OLEDB.4.0;" & "Data Source=D:\db1.mdb;"

  '実行
  strSQL = getImpSQL(IMPORT_TBL, CSV_FILE)
  adoCn.Execute strSQL

  '終了
  adoCn.Close
  Set adoCn = Nothing
End Sub

Private Function getImpSQL(inTblName As String, inFilePath As String)
  Dim varWk  As Variant
  Dim strPath As String
  Dim strFile As String
  Dim strSQL As String
  
  'ファイルパスとファイル名に分解
  varWk = Split(inFilePath, "\")
  strFile = varWk(UBound(varWk))
  varWk(UBound(varWk)) = ""
  strPath = Join(varWk, "\")
  
  'SQL文創生
  strSQL = "insert into " & inTblName & " select * "
  strSQL = strSQL & "from [Text;DATABASE=" & strPath & "].[" & strFile & "]"
      
  getImpSQL = strSQL
End Function

投稿日時 - 2002-11-12 22:56:44

補足

DTSパッケージなるものを使用すると
速そうなので、それについて今度は調べ始めました。

別に質問したので、もし何か少しでもわかることがあれば教えてくだされば
幸いです。よろしくお願いします。

投稿日時 - 2002-11-18 17:04:23

ANo.3

※DBの接続先
※DBの接続方法を書いてください。

もしADOやDAOならDBの種類を問わずに、1文のSQL文で可能です。
oo4oなら先に述べられた方々の言う通りのやり方がメジャーだと思います。

質問には環境を書くようにしましょう。

投稿日時 - 2002-11-12 09:53:48

補足

TAGOSAKU7様、すみません。
DBの接続先 SQLServer2000
DBの接続方法 RDO
これでOKでしょうか?

1文のSQLで可能ということですが、その方法がBESTのような
気がします。教えて頂けないでしょうか?

それとは関係ないかもしれませんが、
自力で調べたところ bulk copy? bulk Insert?
というのが何だか関係ありそうな気がするのですがどうでしょうか?

ご教授くださると大変助かります。

投稿日時 - 2002-11-12 19:54:02

お礼

TAGOSAKU7さんの
ユーザー情報のコメントのURLを見ました。

何か知らないけど気合が入りました。頑張ります。

投稿日時 - 2002-11-18 13:20:16

ANo.2

1レコード(1人分の記録項目など)が3項目(3フィールド)とした時の例をあげます。下記をテストして、納得してください。フィールド数はa1.a2・・・anと増やしてください。openのファイル名とパス名は適宜変更のこと。
Sub test01()
Dim a1, a2, a3 As String
Open "c:\My Documents\book1.csv" For Input As #1
readf:
If EOF(1) Then GoTo owari
Input #1, a1, a2, a3
MsgBox "レコード読みこみ"
MsgBox a1
MsgBox a2
MsgBox a3
GoTo readf
owari:
Close #1
End Sub
実行して、数レコード表示して、表示がうるさくなったら、CTRL+PAUSEで中止してください。
あとはMSGBOXのところを(置換えて)データベースのフィールドにセットして、レコードを書き出すことになります。
「データベース」は何ですか。MDBファイルですか?
「データベース」ファイルは1種類ではないですよ。

投稿日時 - 2002-11-11 18:00:48

補足

imogasi様回答ありがとうございます。
教えられた方法でやってみました。
うまくいったのですが、次の問題が出てきました。

例えば件数が少ない時は、いいのですが
100万件のデータを読込まなければいけなくなりました。

上記の方法だと時間がかかりすぎるので、42万件ほどで4時間・・
何か別の方法はないでしょうか?
どうかお願いします。

投稿日時 - 2002-11-14 18:39:41

ANo.1

1行でなく1項目ずつ読み込んでいけばいいだけです。

投稿日時 - 2002-11-11 14:49:17

あなたにオススメの質問