DOBON.NET DOBON.NETプログラミング掲示板過去ログ

データテーブル から MDBのレコードの更新ができない

環境/言語:[OS : Windows 7 / 言語 : Visual Basic .NET / .NET Framework : 4.5]
分類:[.NET]

【解決したい問題】

XPの時は、VB6.0を使っていました、Windows7 に変えて   VisualStudio community2013に変えたのですが、データベース(Access2010)への新規行追加ができません、デバック時に「da.update(tbl)」に「Inserto -intoの構文エラー」が付きます。そこで、da.update(tbl)の行を無効にして実行すると、データグリッドビューには追加したレコードが表示されているので、データテーブルにはレコードが追加されていると思いますが、色々な資料をみてもこれ以外に対策がなく悩んでいます。
  すでに1ケ月近く悩んでいます、御指導の程お願いいたします。

更新のテストをしたプログラムです。 よろしく。

Dim cn As New System.Data.OleDb.OleDbConnection
Dim cm As New System.Data.OleDb.OleDbCommand
Dim da As System.Data.OleDb.OleDbDataAdapter
Dim ds As New DataSet
Dim dt As New DataTable
Dim cb As OleDb.OleDbCommandBuilder
Dim dtv3 As New DataView
DIM dbfilename As String = "C:\NAOI\VS2013\SIZAIITIRAN.mdb"
DIM connectionString As String = "Provider =Microsoft.jet.OLEDB.4.0;Data Source=" & dbfilename & ";"

commandText = "SELECT* FROM SYUSIITIRAN"

da = New System.Data.OleDb.OleDbDataAdapter(commandText, connectionString)
cb = New OleDb.OleDbCommandBuilder(da)

da.Fill(dt)

Dim dr As DataRow
dr = dt.NewRow
dr("KOJINO") = "15-0080"
dr("KOJISUBNO") = "0"
dr("KOJIMEI") = "DB更新テスト"
dr("TOKUISAKIMEI") = "アクセス工務店"
dt.Rows.Add(dr)

cb = New OleDb.OleDbCommandBuilder(da)
da.Update(dt)    'この行でエラーになる

Dim BindingSource1 As New BindingSource
BindingSource1.DataSource = dt
dgv3.DataSource = BindingSource1
dgv3.Refresh()

【解決するために何をしたか】

インサイダー.NET ADO.NET 基礎講座 @IT
DOBON.NET 掲示板
VisualBasic2010 データベース 至高の技[秀和システム)
VisualBasic.NET データベースの技(技術用論社)
2015/03/19(Thu) 20:20:59 編集(投稿者)

■No32878に返信(Naoiさんの記事)
> デバック時に
デバッ「グ」ですね。DEBUG。バグを潰す作業。


> commandText = "SELECT* FROM SYUSIITIRAN"
このテーブルの 列名と型 を教えてください。


> 「Inserto -intoの構文エラー」が付きます。

Inserto (INSERT?)がエラーになっているのだとしたら、
確認するべきは da.InsertCommand の内容です。

・CommandText は、期待通りの SQL になっているか?
 たとえば、予約語(UpDate、No、From など)を列名に使われていないか。

・Parameters の内容は適切か?
 たとえば、日付型のフィールドに対して、
 OleDbType.Date (日付時刻型)ではなく、
 OleDbType.DBDate (日付型)が割りあたっていないか?


これらの情報に問題があるようなら、Update を呼び出す前に、
InsertCommand の内容を修正しておく必要があります。

(DeleteCommand / UpdateCommand も同様)
■No32879に返信(魔界の仮面弁士さんの記事)

 早速の対応に感謝します、有難うございます。
SIZAIITIRAN(MDB),SYUSIITIRAN(テーブル)
   SRNO (オートナンバー型)
   SYORIBI (日付型)
* KOJINO (テキスト型)
* KOJISUBNO (数値型)
* KOJIMEI (テキスト型)
* TOKUISAKIMEI (テキスト型)
KEIYAKUGAKU (数値型)
NYUKINGAKU (数値型)
NYUKINBI (日付型)
NYUKINZANGAKU (数値型)
NYUKINYOTEIBI (日付型)

今回は、* 印 のフィールドを新規追加したいと考えています。
以上ですが、今回の御指摘の答えになっていますでしょうか?
 初歩的なことで、申し訳ありません。
名前の使い方も不適切な処があり指摘いただきまして、感謝しています。
■No32880に返信(Naoiさんの記事)
> 今回は、* 印 のフィールドを新規追加したいと考えています。
dr = dt.NewRow の後は、* のフィールドのみ操作されているようですが、
それ以外の項目については、何を登録したいのでしょうか。

他の項目は null で良い、というのであれば現状のコードで構いませんが、
既定値を設定したい、というのであれば、INSERT クエリの作成が必要です。


> SIZAIITIRAN(MDB),SYUSIITIRAN(テーブル)

当方ではエラーが再現せず、そのまま mdb に登録されました。

エラーが発生したときの
  ・例外の型 (System.何某.なんとかException)
  ・例外メッセージの内容
を、正確に記載いただけますでしょうか。
スペルミスの可能性も含め、現状を把握しておきたいので…。
名前の使い方も不適切な処があり指摘いただきまして、感謝しています。
■No32881に返信(魔界の仮面弁士さんの記事)
お手数をおかけします、有難うございます。

例外の型
型'Sysutem.Data.OleDb.OleDbException のバンドルされていない例外が、  System.Data.dllで発生しました。
追加情報
INSERT INTO ステートメントの構文えらーです。

ご指摘の変数の型について、次のように変えてみました。
dim SUBNO AS Integer

SUBNO = 0

  dr("KOJISUBNO") = "SUBNO"
その結果は、「ArgumentExceptionはバンドルされませんでした。」
  型 「型'sysutem ArgumentExceptionのバンドルされない例外が System.Data.dll で発生しました。
  追加情報
入力文字列の形式が正しくありません、列 KOJISUBNO に <SUBNO>を格納できませんでした。必要な型は、Int32 です。
このような結果になりました。

SYUSIIRIRAN の KOJISUBNOフィールドの型は、数値型の整数型です。
本当にお手数をおかけして、申し訳ありません。 
■No32882に返信(Naoiさんの記事)
> INSERT INTO ステートメントの構文えらーです。
平仮名の えらー ですか…。(^^;

「正確に記載」した結果がこれだと、最初の質問内容をどこまで信じればよいのか
不安ではありますが(少なくとも当方では再現しなかったので)、とにかく、
> commandText = "SELECT* FROM SYUSIITIRAN"
の部分は、空白の数なども含め、実際に指定したコードと
完全に一致していると思って良いのですよね?

エラー内容からして、今回の肝は SQL 文の指定にありそうなので…。
(もしくは環境依存の問題と言う可能性もありますけど)


> ご指摘の変数の型について、次のように変えてみました。
なんだか状況が悪化していますね。(^^;;

確認頂きたかったのは VB 側や mdb のデータ型ではなく、
ADO.NET 部分のデータ型についです。
いわゆる System.Data.OleDb.OleDbType のところ。
この確認箇所については、本回答の最後の部分を参照してください。


> SUBNO = 0
>   dr("KOJISUBNO") = "SUBNO"
そのように書きたいのであれば、ここは
   dr("KOJISUBNO") = SUBNO
ですね。元のコードだと、「数値のゼロ」をセットしているのではなく、
「SUBNO という文字列」をセットしていることになります。


Integer すなわち System.Int32 型が期待されるフィールドに対し、
文字列 "SUBNO" が指定されたため、型変換エラーになっています。それが
> 入力文字列の形式が正しくありません、列 KOJISUBNO に <SUBNO>を格納できませんでした。必要な型は、Int32 です。
というエラーの意味です。


上記の型変換エラーは単純なコーディングミスなのでさておき、
当初のエラーが意味しているのは、行追加のための INSERT INTO ステートメントが
構文エラーになっているように見受けられます。SQL 文を見直しておきましょう。

No32879 で書いた「InsertCommand」というのは DataAdapter のプロパティなのですが、
初期値は Nothing になっているはずです。特に InsertCommand をセットしていない場合には
 da.InsertCommand = cb.GetInsertCommand()
でそれを自動生成して割り当てることができます。その上で、

 ・da.InsertCommand.CommandText に格納された SQL 文(INSERT INT)

 ・da.InsertCommand.Parameters(パラメータ番号) それぞれの
  ParameterName と OleDbType

が本当に正しいのか。その INSERT INTO の SQL 文を Access で実行した場合に
今回の現象と同じようなエラーになるのかどうかを探ってみて下さい。
■No32883に返信(魔界の仮面弁士さんの記事)

> 初期値は Nothing になっているはずです。特に InsertCommand をセットしていない場合には
>  da.InsertCommand = cb.GetInsertCommand()
> でそれを自動生成して割り当てることができます。その上で、
>
>  ・da.InsertCommand.CommandText に格納された SQL 文(INSERT INT)
>
>  ・da.InsertCommand.Parameters(パラメータ番号) それぞれの
>   ParameterName と OleDbType

何回も御手を煩わせて申し訳ありません。

 INSERTCOMMAND カレント

CommandText INSERT INTO SYUSIITIRAN (SYORIBI, KOJINO, KOJISUBNO, KOJIMEI, TOKUISAKIMEI, KOJISYUEKI, KEIYAKUGAKU, TEGATA, NYUKINBI, NYUKINGAKU, SIMEBI, NYUKINZANGAKU, NYUKINYOTEIBI, NYUKINZEI, SEIKYUGAKU, NOHINSYO, SIHARAIBI, SIHARAIGAKU, SIHARAIYOTEIBI, SIHARAIZANGAKU, SHOHIZEI, WARIBIKI, KAKUNIN, [MEMO])
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)

CommandType Text

Parameters
(Name) KOJINO , (DbType) String
(Name) KOJISUBNO , (DbType) Int16
(Name) KOJIMEI , (DbType) String
(Name) TOKUISAKIMEI , (DbType) String

以下同様にUpDateのプロパティーを書いておきます。

UPDATE SYUSIITIRAN SET SYORIBI = ?, KOJINO = ?, KOJISUBNO = ?, KOJIMEI = ?, TOKUISAKIMEI = ?, KOJISYUEKI = ?, KEIYAKUGAKU = ?, TEGATA = ?, NYUKINBI = ?, NYUKINGAKU = ?,
SIMEBI = ?, NYUKINZANGAKU = ?, NYUKINYOTEIBI = ?, NYUKINZEI = ?, SEIKYUGAKU = ?, NOHINSYO = ?, SIHARAIBI = ?, SIHARAIGAKU = ?, SIHARAIYOTEIBI = ?,
SIHARAIZANGAKU = ?, SHOHIZEI = ?, WARIBIKI = ?, KAKUNIN = ?, [MEMO] = ?
WHERE (SRNO = ?) AND (? = 1 AND SYORIBI IS NULL OR
SYORIBI = ?) AND (? = 1 AND KOJINO IS NULL OR
KOJINO = ?) AND (? = 1 AND KOJISUBNO IS NULL OR
KOJISUBNO = ?) AND (? = 1 AND KOJIMEI IS NULL OR
KOJIMEI = ?) AND (? = 1 AND TOKUISAKIMEI IS NULL OR
TOKUISAKIMEI = ?) AND (? = 1 AND KOJISYUEKI IS NULL OR
KOJISYUEKI = ?) AND (? = 1 AND KEIYAKUGAKU IS NULL OR
KEIYAKUGAKU = ?) AND (? = 1 AND TEGATA IS NULL OR
TEGATA = ?) AND (? = 1 AND NYUKINBI IS NULL OR
NYUKINBI = ?) AND (? = 1 AND NYUKINGAKU IS NULL OR
NYUKINGAKU = ?) AND (? = 1 AND SIMEBI IS NULL OR
SIMEBI = ?) AND (? = 1 AND NYUKINZANGAKU IS NULL OR
NYUKINZANGAKU = ?) AND (? = 1 AND NYUKINYOTEIBI IS NULL OR
NYUKINYOTEIBI = ?) AND (? = 1 AND NYUKINZEI IS NULL OR
NYUKINZEI = ?) AND (? = 1 AND SEIKYUGAKU IS NULL OR
SEIKYUGAKU = ?) AND (? = 1 AND NOHINSYO IS NULL OR
NOHINSYO = ?) AND (? = 1 AND SIHARAIBI IS NULL OR
SIHARAIBI = ?) AND (? = 1 AND SIHARAIGAKU IS NULL OR
SIHARAIGAKU = ?) AND (? = 1 AND SIHARAIYOTEIBI IS NULL OR
SIHARAIYOTEIBI = ?) AND (? = 1 AND SIHARAIZANGAKU IS NULL OR
SIHARAIZANGAKU = ?) AND (? = 1 AND SHOHIZEI IS NULL OR
SHOHIZEI = ?) AND (? = 1 AND WARIBIKI IS NULL OR
WARIBIKI = ?) AND (? = 1 AND KAKUNIN IS NULL OR
KAKUNIN = ?) AND (? = 1 AND [MEMO] IS NULL OR
[MEMO] = ?)

変なことをお聞きするのかもしれませんが、INSERT INTO の SQL 文のAccess での実行テストは AccessのVBAで確認すると言うことでしょうか?
幼稚な質問でお許しください。
■No32884に返信(Naoiさんの記事)

追記)

先の質問の最後にお聞きした、Accessに直接実行するテストの件ですが。
データアダプターを介さないで、テーブルにSQL文を実行することですか?
VBA の件は間違いです、緊張して冷静さを欠いていました、申し訳ありません。
 少し時間をくださいExecuteNoneQueryのコマンドのテストをしてみます。
何回も、すみません。
■No32884に返信(Naoiさんの記事)
> 何回も御手を煩わせて申し訳ありません。

No32880 で提示頂いたテーブル定義とは、随分と違うようですね…。


>  INSERTCOMMAND カレント

注意が必要そうなのは、「MEMO」というフィールドですね。
これは JET のメモ型を意味する予約語ですので、そのままだと
データ更新時に問題を引き起こす可能性がありそうです。


たとえば、Access で INSERT のクエリを実行する場合、
 INSERT INTO TABLE1 ( MEMO ) VALUES ( ? )
という SQL だと、『INSERT INTO の構文エラーです』のエラーになります。

フィールド名やテーブル名に「予約語」や「空白を含んだ名前」を使う場合は、
こうした問題が起きやすいので、データベース設計時に避けるようにしてみてください。

どうしても改名できない事情がある場合は、
 INSERT INTO TABLE1 ( [MEMO] ) VALUES ( ? )
とか
 INSERT INTO TABLE1 ( `MEMO` ) VALUES ( ? )
のように、その項目名を 角括弧 もしくは アクサングラーブ で囲む必要があります。


ただ、今回提示頂いた SQL を見ると、既に [MEMO] 形式で処理されていますので、
GetInsertCommand メソッドで予めコマンドを DataAdapter に割り当ててから実行すれば、
エラーを回避できるかもしれません。


> Parameters
> (Name) KOJINO , (DbType) String
> (Name) KOJISUBNO , (DbType) Int16
> (Name) KOJIMEI , (DbType) String
> (Name) TOKUISAKIMEI , (DbType) String

あれ、「?」の数に対して、パラメータの数が圧倒的に足りていないようですね。
しかし、パラメータが不足しているなら、別のエラーになりそうなものですが…。




> 変なことをお聞きするのかもしれませんが、INSERT INTO の SQL 文のAccess での実行テストは AccessのVBAで確認すると言うことでしょうか?

INSERT INTO の SQL を Access のクエリデザイナに貼り付けて実行してみるという事です。
■No32886に返信(魔界の仮面弁士さんの記事)
返信が遅れてすみません。風邪で熱が出たためメールが読めず遅れました。
「MEMO」フィールドが注意したい、とのご指摘がありましたので、
データベース(SIZAIITIRAN)のフィールドをSRNO,KOJINO,KOJISUBNO,KOJIMEI
,TOKUISAKIMEI,SYORIBI を残しあとは削除しました。その結果は、無事 UPDATE
の処理ができ、データベースに新規追加ができました。
 この後、一フィールドづつ追加してみて、どのフィールドでエラーになるか?
確認します。それと「データコマンド」の追加コマンド(INSERT INTO)を使ってみたいと思っています。2、3日時間をください。
   この質問の投稿はそのままで宜しいですか? 結果の報告もこの投稿欄で宜しいのでしょうか? 今日からテストしてみます。感謝しています。
■No32889に返信(Noiさんの記事)
 初歩的な質問に、親切に対応して頂きまして、心から感謝しています。
結論から申し上げますと、ご指摘いただいた「MEMO]フィールドを削除して、正常な動作になりました。本当に有難うございました。データリーダーとデータコマンドも良く調べて使いたいと思っています。しかし、できるだけご厄介にならないように努力します。今回は有難うございました。
解決済み!

DOBON.NET | プログラミング道 | プログラミング掲示板