mdb内のデータをコピーするには?

解決


ピッツァ  2008-01-28 15:56:42  No: 144356  IP: 192.*.*.*

お世話になります。
開発環境ですが、WindowsXP,VB.NET2003になります。

<質問>
同名・同構成のmdbの片方(コピー元)の全データを
もう一方(コピー先)の空mdbへコピーする方法を検討中なのですが
どのような手法が良いかアドバイスいただければと思っています。

少し詳しく説明させていただきますと

レコードレイアウトの仕様変更で
データベースファイルとなる test.mdb の主要全テーブルの "末尾" に 
testField というフィールドを追加します。仮に testTable が
現状10フィールドなら11フィールドになるといった具合です。
(上記mdb名等は仮の名称です。実際のテーブル数は細かい物を含め30以上あります)

そこで、この新mdbに対して既存の旧mdbの全テーブルデータをコピーできないかと考えています。
新testTableの1〜10フィールドまでに旧testTableの同じく1〜10フィールドの
値をセットし、新たな11フィールド目は空といった具合です。

引き続き調査・検討は続けますが、よろしければアドバイスお願いします。

編集 削除
魔界の仮面弁士  2008-01-28 16:09:10  No: 144357  IP: 192.*.*.*

テーブル定義を変更したい、という意図の質問なのか、それとも
テーブル定義を変更済みの新mdbは既に用意されており、そこに
旧mdbから、データだけコピーしたい、という意図なのか
読み取れませんでした。


とりあえず、後者(定義変更ではなくデータ複写が目的)だとすれば、
下記のような SQL を発行してみては如何でしょう。


INSERT INTO [testTable] (
[列1], [列2], [列3], [testField]
) SELECT
[列1], [列2], [列3], NULL
FROM [C:\old.mdb].[testTable]


上記は、新mdb に接続して、旧mdb からインポートする例です。
あるいは旧mdb に接続して、新mdb へとエクスポートしても、
同じような結果が得られるかと。

編集 削除
ピッツァ  2008-01-29 11:40:24  No: 144358  IP: 192.*.*.*

魔界の仮面弁士さん有難うございます。即回答して頂いたのにお礼が遅れて申し訳ありません。

質問の意図が伝えきれず申し訳ありませんでした。"後者"の方になります。
冗長な文章になりますが、今度はできるだけ詳しく書きたいと思います。

レイアウトの変更は今回で2〜3度目になるのですが、前任者の頃から
新フィールドはテーブル末尾に追加しその定義済みの新mdb(空です)に対して
各客先で既存データ(旧mdb)を復元するといった手順を踏んでいます。

基本的に変更テーブルの末尾に新フィールドが追加されていくだけなので
メンテナンスプログラムのような物を作成してテーブル数分のループ処理等で
旧mdb⇒新mdbといったコピーができないかと模索してました。
> テーブル定義を変更したい、という意図の質問なのか、それとも
というお話を聞き、もしかして客先で使用中のmdbの構成を直接変更する事も可能なのか?
とも思いそちらの方にも興味が出てきましたが…

とりあえず今は当初の質問通り
"後者"の旧mdb⇒新mdbへのデータコピーで話を進めさせて頂きます。

<現況>
質問投稿後も自身でいくつかの調査を続けたところ
GetOleDbSchemaTableというメソッドを見つけました。まだよく理解していませんが
DataTableオブジェクトにmdbの情報が取れるようなので、これをうまく利用できれば
仮にテーブル数やテーブル名が分からなくても、今回のような同一mdb間の話であれば
テーブル数分のループ処理でデータコピーができて、今後同様な変更があっても
文字通りメンテナンス用として使いまわし可能かな?と考えました。
(検討違いな調査・考えでしたらツッコミを入れてもらえると助かります)

あとはご教示いただいたSQLによるデータコピー法でテーブル毎にコピーするような
プログラムが組めればよいのですが、実際にVB上ではどう記述すれば良いか行き詰ってます。
SQLに関しては、VB上での記述(利用)法や知識が全然足りないようです。
(普段はDataAdapterなどもデザイン上の構成ウィザードで作成してますし)

こちらでももちろん調査等は続けますが
大変図々しいとは思いますが、今回のコーディングに関連するような使用例等
アドバイスや注意をして頂けると助かります。もしよろしければお願いします。

編集 削除
魔界の仮面弁士  2008-01-29 12:42:12  No: 144359  IP: 192.*.*.*

> もしかして客先で使用中のmdbの構成を直接変更する事も可能なのか?

たとえば、
  ALTER TABLE テーブル名 ADD COLUMN 追加する列名 TEXT(10)
という SQL を使って、列を追加できます。
http://office.microsoft.com/ja-jp/access/HP010322071041.aspx

> GetOleDbSchemaTable 
ADO.NET の GetOleDbSchemaTable や、
ADO の OpenSchema を使って、テーブル定義を得ることは可能ですね。


> 実際にVB上ではどう記述すれば良いか行き詰ってます。
どこで行き詰っているのか分からないので、「修正案」が出せないです…。
(代わりにコーディングするというわけにも行きませんし)

現時点では、どのようなコードを書いておられるのでしょうか?


> 今回のコーディングに関連するような使用例等
たとえば GetOleDbSchemaTable を使ったサンプルは、
google 等で幾つか見つかるかと思います。

テーブル名を列挙できれば、あとはその文字列を SQL 文へと加工すれば OK ですよね。

編集 削除
ピッツァ  2008-01-29 13:55:40  No: 144360  IP: 192.*.*.*

魔界の仮面弁士さん有難うございます。お世話になります。

> どこで行き詰っているのか分からないので、
ほとんどが mdb 接続や SQL 文絡みの部分です。
前述しましたが、今のところはまだ普段はDataAdapter構成ウィザードのクエリビルダで
テーブルやフィールドを選択した時に自動表示される物しかあまり触れる機会がないので
(OleDbConnection や OleDbCommand でコード上で操作するといった部分が特に未熟者です)

> 現時点では、どのようなコードを書いておられるのでしょうか?
ある程度まとまるまでもう少々時間を下さい。

それと貼っていただいたリンクも参考にさせて頂きます。
ではまた後ほど。引き続きお相手して頂ければ幸いです。

編集 削除
ピッツァ  2008-01-29 17:34:33  No: 144361  IP: 192.*.*.*

遅くなりましたが、一旦コードの方がまとまりました。一応目的の動作はしてくれています。
稚拙なコードですので本当は恥ずかしいのですが教えて頂いた結果報告として載せてみます。

Public Sub mdbDataCopy(ByVal oldmdbPath As String, ByVal newmdbPath As String)
    '
    Dim wOldmdbConnection As New OleDb.OleDbConnection
    Dim wNewmdbConnection As New OleDb.OleDbConnection
    Dim wCommand As New OleDb.OleDbCommand
    Dim wSourceMdbSchemaTable As DataTable
    '================================================================================
    ' 旧mdb
    wOldmdbConnection.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;" & _
                                         "Data Source=" & oldmdbPath & ";" & _
                                         "Persist Security Info=False"
    wOldmdbConnection.Open()
    '
    wSourceMdbSchemaTable = wOldmdbConnection.GetOleDbSchemaTable _
                            (System.Data.OleDb.OleDbSchemaGuid.Tables, _
                            New Object() {Nothing, Nothing, Nothing, "TABLE"})
    '================================================================================
    ' 新mdb
    wNewmdbConnection.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;" & _
                                         "Data Source=" & newmdbPath & ";" & _
                                         "Persist Security Info=False"
    wNewmdbConnection.Open()
    '
    wCommand.Connection = wNewmdbConnection
    '================================================================================
    ' データコピー
    Dim i As Integer
    Dim wTableName As String
    '
    For i = 0 To wSourceMdbSchemaTable.Rows.Count - 1
        ' 
        wTableName = wSourceMdbSchemaTable.Rows(i)(2).ToString
        ' 
        wCommand.CommandText = "INSERT INTO [" & wTableName & "] " & _
                               "SELECT [" & wTableName & "].* " & _
                               "FROM [" & oldmdbPath & "].[" & wTableName & "]"
        '
        wCommand.ExecuteNonQuery()
    Next
    '================================================================================
    If wOldmdbConnection.State = ConnectionState.Open Then
        wOldmdbConnection.Close()
    End If
    '
    If wNewmdbConnection.State = ConnectionState.Open Then
        wNewmdbConnection.Close()
    End If
End Sub

見よう見まねな所もありますので何かご指摘があれば是非お願いします。
(やはり CommandText の所で色々行き詰ってました)

編集 削除
ピッツァ  2008-01-30 16:10:17  No: 144362  IP: 192.*.*.*

本日、前回投稿のコードをプロジェクトにコピーして実際のシステム上でテストを行いました。
多少手は加えましたが、ほぼ前回投稿のコードのままで一通り動作してくれました。

細かいツッコミ所は色々あるかとは思いますが、とりあえず解決とさせて頂きます。
お世話になりました。また質問する機会あった場合はよろしくお願いします。

編集 削除