Microsoft Access 掲示板

.AddNewでデータを登録する場合に、変数を利用する方法

9 コメント
views
4 フォロー

INSERT INTOを使ってデータの登録をすると、処理時間がかかりすぎるので、.AddNewを利用する場合のトラブルです。

以下のようにすれば、問題なく登録できます。

Set adoRs = CreateObject("ADODB.Recordset") 'ADOレコードセットオブジェクトを作成

Dim List1 As Variant
Dim List2 As Variant

List1 = Array("fact0", "fact1", "fact2")
List2 = Array("a", "い", "う")

adoRs.AddNew List1, List2
adoRs.Close

しかし、実際にはデータ数が多くなるので、
配列に格納する場合に、変数を使用する必要があります。
"a", "い", "う"は、submtという配列に入っているので

Dim List1(2) As Variant
Dim List2(2) As Variant

For i = 0 To 2
  List1(i) = "fact" & i & List1(i)
  List2(i) = submt(i)
 Next

で、List1にフィールド名、List2にデータを格納してから

adoRs.AddNew List1, List2
を実行すると、

実行時エラー 2147217887「要求された名前、または序数に対応する項目がコレクションに見つかりません」
というエラーが発生します。

力技で、テキストを作って変数に代入してみましたが、ダメでした。

For i = 1 To 2
 tex = tex & """" & "fact" & i & """" & ", "
 tex2 = tex2 & """" & submt(i) & """" & ", "
Next

 tex = """" & ", " & Left(tex, Len(tex) - 2)
 tex2 = """" & ", " & Left(tex2, Len(tex2) - 2)

List1 = Array(tex)
List2 = Array(tex2)

どのように、処理したらよいのでしょうか?

タークン
作成: 2024/08/07 (水) 20:29:36
通報 ...
1
りんご 2024/08/07 (水) 20:55:25 935bc@0e907

後だしで、どんどん情報がかわっていくいつものパターンでしょうか?
ここはAccessに関する質疑応答、技術的な情報交換の場です。
それを踏まえて、他の閲覧者や後から検索で訪問した人にとって、意味のある情報になるように、Accessでどのように解決するかという観点で、質問していますか?

2

INSERT INTOを使ってデータの登録をすると、処理時間がかかりすぎるので、.AddNewを利用する場合のトラブルです。

具体的にどのようなコードを書いたのか不明ですが、
追加するデータはどこにどのような形で存在するのでしょうか。

Accessのテーブル、CSVデータ、エクセルシート、あるいは他データベースのテーブルなどなら、INSERT INTOの方がAddNewより高速です。

そうでないなら、どこにどのようなデータがあるのかの説明が必要です。

実行時エラー 2147217887「要求された名前、または序数に対応する項目がコレクションに見つかりません」
というエラーが発生します。

adoRs.AddNew List1, List2 でそのエラーが発生するということですか。

エラーメッセージから推測するに、List1 に格納されているフィールド名が、追加するテーブルに存在しないという状況だと思います。

3
タークン 2024/08/08 (木) 11:25:27 e67d7@2705a

2000件くらいのデータを一括で登録する場合、
.AddNewを利用すると、INSERT INTOを利用した時と比べて、1/5くらいの時間で処理できてる感じです。

ですが、2000件分のコードを書くのは、間違っているような気がしまして
フィールド名をList1に、登録するデータをList2に格納するのですが、
 List1 = Array("fact1","fact2","fact3")
と2000件書き続けるわけにはいかないので、
変数を利用する必要が出てきます。
しかし、

For i = 1 to 2000
 List1(i) = "fact" & i & List1(i)
next

で処理すると、エラーが出てしまうわけです。
List1(0)には、"jan"の文字列が入るので、1からスタートしています。

List1 に格納されているフィールド名が、追加するテーブルに存在しないという状況のようなのですが、
factに連番を振っているだけなので、
 List1(i) = "fact" & i & List1(i)
の部分に、なにか致命的な間違いがあるような気がしてますが、原因が分かりません。

ちなみに、主キーのjanを登録してから、updateで残りのデータで更新をかけると
全てsqlで処理しても、コードの簡潔さを考慮すれば、OKレベルではあるのですが、、、、

なんか、負けたようで嫌なのです。
ですが、updateの方が不可が少ないような感じなので、これが正解なのかもしれないのですが、

4
タークン 2024/08/08 (木) 13:11:25 e67d7@2705a

INSERT INTOの、100件程度の処理速度を測ってみましたが、
1秒かからないので、コードが簡単に作れることを考えると、
200件程度だったら、これでいいかな~という感じでした。

コードは、
    For i = 1 To 200
      tex = tex & "fact" & i & ","
     Next
    Tn = "算定基礎届"
    Fn = "(" & "jan" & "," & Left(tex, Len(tex) - 1) & ")"
で作ってエラーが出ないので、
List1のフィールド名にも、間違いはなかったはずです。

やはり、根本的な間違いをしているような気がします。

5
名前なし 2024/08/08 (木) 14:11:08 2ce57@dbee8

INSERT INTOを使ってデータの登録をする

  • INSERT INTO ... VALUES ステートメントと INSERT INTO ... SELECT ステートメントのどちらを意味しているのかが不明瞭。

実際にはデータ数が多くなる

  • 「レコードの件数」のことを言っているのか、「フィールドの個数」のことを言っているのかが不明。

"a", "い", "う"は、submtという配列に入っている

  • 具体的にどこから参照したデータをどうやって配列として取得しているのかが不明。

実行時エラー 2147217887「要求された名前、または序数に対応する項目がコレクションに見つかりません」

  • レコードの追加先となるテーブルの構造(各フィールドの名前/データ型、インデックス定義)が全く不明。

2000件くらいのデータを一括で登録する場合、
.AddNewを利用すると、INSERT INTOを利用した時と比べて、
1/5くらいの時間で処理できてる感じです

₋ 具体的なテストコードと実行時間の測定方法および測定結果が不明。

やはり、根本的な間違いをしているような気がします。

主に足りていないのは、次の 3 つについての理解でしょう。

  • VBA における配列の扱い方

  • ADODB.Recordset オブジェクトの AddNew メソッドの使い方

  • Access データベースにおけるテーブル/クエリの仕様

For i = 1 to 2000
 List1(i) = "fact" & i & List1(i)
next

adoRs.AddNew List1, List2

仮に adoRs が参照しているのが Access データベース上のテーブルなのであれば、
1 つのテーブルに定義できるフィールドの数の上限は 255 個ですので、
2000 個ものフィールドを持つレコードを追加することなど絶対に不可能です。

6

ハンドルネームを入力し忘れました。失礼。

7
タークン 2024/08/08 (木) 16:24:54 e67d7@2705a

まず、根本的に無理だったのですね。
200程度でも、やはり処理速度には差が出るので、
色々と試してみたのですが、
引数が間違った型、許容範囲外、または競合しています。
というエラーメッセージが出るようになりました。

この原因を見つけ出すのは、かなり困難なので止めます。

脱.Executeは、今後の課題にします。

ありがとうfございました。

8
りんご 2024/08/08 (木) 21:55:02 935bc@0e907

 結局、いつもの右往左往して自己完結でしたね。そして、貴方の自己完結には脈絡がありません。
 もしかして言葉のキャッチボールを知らないのかしら?

9

質問者さんは自己完結されてるようなので、
後から来た閲覧者のために、
大量のデータをテーブルに新規追加する方法の速度に関する、
一般論を置いておきます。

SQLの INSERT INTO ... VALUES ステートメントで1レコードずつ新規追加を繰り返す方法と、
DAOまたはADOの .AddNewメソッドで1レコードずつ新規追加を繰り返す方法では、
後者の方が高速。

理由
  INSERT INTO ... VALUES ステートメントでは、1回実行するたびに、レコードセットの生成、破棄が実行される。例えば200レコード追加する場合は、それが200回繰り返される。
  .AddNew の場合は、最初にOpenRecorset でレコードセットを生成、200回追加して(.AddNew)後に、最後にレコードセットを破棄(Close)することが可能。生成、破棄は1回のみですむ。

ただし、追加するデータが、Accessのテーブル、CSVデータ、エクセルシート、他データベースのテーブルなどなら、テーブルとして扱うことが可能なので、 INSERT INTO ... SELECT ステートメントを使えば、複数レコード追加でも、1回の実行で可能なので、高速だし、コードもシンプルになる。