質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
VBA

VBAはオブジェクト指向プログラミング言語のひとつで、マクロを作成によりExcelなどのOffice業務を自動化することができます。

Access

Accessはマイクロソフトによるリレーショナルデータベース管理システムです。オブジェクト指向のアプリケーション作成に対応しており、テーブルや編集をはじめ、クエリ生成、入力フォーム作成、レポート作成など一通りの機能を備えています。

Q&A

解決済

3回答

15005閲覧

Access vba アクションクエリを連続して実行するには?/エラー:更新可能なクエリであることが必要

nekomura

総合スコア132

VBA

VBAはオブジェクト指向プログラミング言語のひとつで、マクロを作成によりExcelなどのOffice業務を自動化することができます。

Access

Accessはマイクロソフトによるリレーショナルデータベース管理システムです。オブジェクト指向のアプリケーション作成に対応しており、テーブルや編集をはじめ、クエリ生成、入力フォーム作成、レポート作成など一通りの機能を備えています。

0グッド

0クリップ

投稿2016/05/13 07:31

編集2016/05/13 08:16

よろしくお願いいたします。

ひとつのボタンクリックイベント時に、下記箇条書きの順番でアクションクエリを実行するロジックについて試行錯誤中です。
・更新クエリ(変数upSQL)①

・追加クエリ(変数addSQL)②

・削除クエリ(変数delSQL)③

テーブルの任意の行の値を2倍にして(更新)、2倍にした行のうちチェック(True)がついているものだけを結果テーブルに追加して(追加)、
追加した分は元のテーブルから削除する(削除)という流れです。
変数の中には、この仕組みに沿ったSQL文が代入されています。

ここで本題ですが、この3つを順番に実行していく方法がわからない為、とりあえず3つを
ただ順番に記述していったところ、アクションクエリ実行のコードは無視され、初めのメッセージと
最後のテーブルを開くコードのみが実行されました(もちろん、結果テーブルには内容は反映されず空の状態)。
なので、②と③を一旦コメントアウトして①の更新クエリのみ実行したところ、エラーが出ました。

【実行時エラー3073
更新可能なクエリであることが必要です。】

3つのアクションクエリを順に実行できるやり方と、更新アクションクエリ実行部分のコードの
エラーの解決策を教えていただけませんか。

色々と試行錯誤した結果解決が出来なかった為、
有職者の皆様、どうぞよろしくお願いいたします。

Private Sub 更新追加削除_Click() If MsgBox("チェックのついたデータを更新して結果テーブルに追加しますか?", vbOKCancel) = vbOK Then If MsgBox("元のチェックデータは消えますがよろしいですか?", vbOKCancel) = vbOK Then ①更新クエリ DoCmd.RunSQL upSQL //②と③をコメントアウトした場合、エラー ②追加クエリ DoCmd.RunSQL addSQL ③削除クエリDoCmd.RunSQL delSQL End If DoCmd.OpenTable "アクションクエリ結果テーブル", , acAdd End If End Sub

~追記~
各クエリの内容は以下です。

upSQL

1taddSQL = "INSERT INTO アクションクエリ結果テーブル ( 番号, 名前, 売上 ) SELECT テーブル名番号, テーブル名.名前, テーブル名.売上 FROM テーブル名 WHERE (((テーブル名.結果)=True))" 2delSQL = "DELETE テーブル名.結果 FROM テーブル名 WHERE (((テーブル名.結果)=True))" 3bkSQL = "SELECT テーブル名.番号, テーブル名.名前, テーブル名.分類, テーブル名.日付, テーブル名.売上, テーブル名.結果 INTO バックアップ_テーブル名 FROM テーブル名"

※ためしに作った下記コードのテーブル作成クエリのイベントがうまくいったので、
それを元に本題のコードを作っています。

~成功例~ ※変数bkSQLには、テーブル作成アクションクエリのSQL文を代入しています。 If MsgBox("バックアップテーブルを作成します。", vbYesNo) = vbYes Then DoCmd.RunSQL bkSQL MsgBox "テーブルを作成しました。" End If

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kaz.Suenaga

2016/05/16 02:54

念のためなんですが、 DoCmd.RunSQL upSQL の前の行に Debug.Print upSQL として、イミディエイトに出力されるSQL文が想定通りか確認できますか。 また、そのSQLをクエリで実行したとき、正しく実行できますか。
nekomura

2016/05/16 03:02

Suenaga様 お世話になります。早々のご返信に感謝いたします。 >Debug.Print upSQL として、イミディエイトに出力されるSQL文が想定通りか確認できますか。 →はい、問題なく確認できました。 >そのSQLをクエリで実行したとき、正しく実行できますか。 アクションクエリを作った際に、動作確認は済んでいます。正しく実行されます。 また、変数に代入しているSQL文はすべてアクションクエリのSQL文からコピペしたものになります。 どうぞよろしくお願いいたします。
kaz.Suenaga

2016/05/16 03:04

何かその書き込み先のテーブルや、それに関連するクエリを開きっぱなしで動作テストしたりしていませんか。
kaz.Suenaga

2016/05/16 03:06

もう1点、upSQL の内容は提示いただけませんか。
nekomura

2016/05/16 03:59

Suenaga様 ありがとうございます。 upSQL の内容は以下です。 "UPDATE dbo_qAction SET dbo_qAction.売上 = [売上]*2" dbo_qAction が、テーブル名(リンクテーブル)です。 >何かその書き込み先のテーブルや、それに関連するクエリを開きっぱなしで動作テストしたりしていませんか。 →Access上では、閉じた状態で、イベントボタンをクリックして実行しています。。。 よろしくお願いいたします。
guest

回答3

0

ベストアンサー

UPDATE dbo_qAction SET dbo_qAction.売上 = [売上]*2"の最後の [売上]をdbo_qAction.[売上]としてはどうでしょうか。

また、テーブル名からするとSQLServerへのリンクテーブルな気がしますが、リンク先はテーブルでしょうか、viewでしょうか。

viewだとしたら、そのまま更新対象とするのは難しい気がします。

投稿2016/05/16 04:25

kaz.Suenaga

総合スコア2037

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

nekomura

2016/05/16 04:37

Suenaga様 ありがとうございます。 テーブルは、リンクテーブルでリンク先はテーブルです。 >UPDATE dbo_qAction SET dbo_qAction.売上 = [売上]*2"の最後の [売上]をdbo_qAction.[売上]としてはどうでしょうか。 アドバイスに従ってコードを書き換えてみたのですが…。 出るエラーは同じで”更新可能なクエリであることが必要です”でした。。。 すみません。。。
nekomura

2016/05/16 04:49

Suenaga様 余談ですが、ためしにdbo_qAction(リンクテーブル)と同じ内容のものをaccess上に作ってみて、 本質問内容のコードを実行したところ更新クエリは実行できました。 テーブル作成クエリ、追加クエリはリンクテーブルのSQLで実行できるのに、更新クエリと削除クエリはなぜリンクテーブルでは実行できなかったのでしょうか…。
kaz.Suenaga

2016/05/16 04:50

リンクテーブルを作成するときのSQLServerへのアクセス権限がリードオンリーだったりしませんか。
nekomura

2016/05/16 04:58

Suenaga様 大変低次元の質問で申し訳ないのですが、 >リンクテーブルを作成するときのSQLServerへのアクセス権限がリードオンリー か否かはどこで確認すればよろしいですか? リードオンリーは、ADOやDAO接続のロジックを書いているときしか見たことが無いもので、先ほどリンクテーブルのデザインモードやSQLserverを確認したのですが、わかりませんでした。 申し訳ありませんがご教示いただけますか。
nekomura

2016/05/16 05:13

eripong 様 よろしくお願いいたします。 参考URL、拝見いたしました。 >「固有インデックスが設定されていないリンクした ODBC テーブル」 該当していました。 また、主キーもつけていませんでした。 こちらを直して試してみます、ありがとうございます!
kaz.Suenaga

2016/05/16 05:24

まず、SQLServerへ接続する際のユーザが何かを確認する必要があります。 https://msdn.microsoft.com/ja-jp/library/ms144284%28v=sql.120%29.aspx?f=255&MSPPError=-2147217396 SQLServer上でユーザを作って、それを利用して接続している場合は「SQL Server 認証」、ActiveDirectoryやSQLServerがインストールされているWindowsサーバのユーザ権限で接続している場合は「Windows統合認証」です。 ユーザーID/PWを別途どこかで設定して接続した記憶がない場合は、おそらくはWindows統合認証になっています。 (この先、手元に環境見ていないのでイメージで語ります) http://www.atmarkit.co.jp/ait/articles/0111/27/news001.html 上記はとてつもなく古いバージョンのSQLServerなので画面がだいぶ違いますが、SQLServerの場合、1つのユーザに対して、 ・ログイン ・DB ・オブジェクト(テーブルやらクエリ) の3階層で権限付与ができます。 (今はもしかするとテーブルの列単位、というのができていた気も) そのログイン・DBあたりの権限が、接続しているユーザに付与されているのかをまず確認してみてください。 その辺はSQLServer管理者の方に教わるとわかりやすいかもしれません。 ものを見ながらのほうが解ると思いますので。
nekomura

2016/05/16 05:30

suenaga様 はい、お察しの一つの通りWindows統合認証です。 長文によるご解説、本当にありがとうございます。 とても勉強になるうえ、わかりやすい解説でこんがらがっている頭が整理され、 指導者である上司に現在の問題点を伝えやすくなります。
kaz.Suenaga

2016/05/16 05:35

もしSQLServerが実運用されているものと共用であれば、安全のため書き込みできない権限にされている可能性があります。 手っ取り早く確認するとしたら、Accessのリンクテーブルを開いて、適当なデータを書き換えて見ることができるかどうかをやってみましょう。
nekomura

2016/05/16 08:09

Suenaga様 エラーの際には、ずいぶんと幅広い視野をもってエラーを探し出さないといけないのですね。。 私自身、まだ狭い範囲しか見ることができずエラーから抜け出すことがいつも出来ないので、本当に毎回ためになります。 一旦現場を離れるので、明日には解決出来そうです。またご報告させてください。
kaz.Suenaga

2016/05/16 08:56

どちらかというと、あまり推測や想像をせずに、淡々と「何ができないのか」をたどっていくことが近道ですよ。 エラーが出る→何をしようとした時に出ているエラーか→何というエラーか→そのエラーが出るのはどういう場合か→・・・ と、切り分けを行なっていくことが遠回りのようで一番スムーズです。 その意味で前のコメントになった 「ためしにdbo_qAction(リンクテーブル)と同じ内容のものをaccess上に作ってみて、本質問内容のコードを実行したところ更新クエリは実行できました。」 これは非常に良い検証だと思います。 これによって、データ構造やソースコードの問題ではなくて書き込む先の問題、というのがはっきりしましたよね。 いい学習プロセスをたどっていると思いますよ。 自分の手を動かして、見つけていくのが一番です。
nekomura

2016/05/17 02:15

Suenaga様 技術的なことだけでなく、習得においての流れやコツもご教示頂き感謝です。 ありがとうございます。 毎回とても勉強になっています。 今回は、無事に解決いたしました。 取り急ぎのお礼、失礼いたします。
guest

0

がんばってますね。
回答をしたいところですが、以下が不明なため答えるのが難しいです。
・DoCmd.RunSQLの中身
・各クエリの詳細

たぶん更新クエリ(upSQL)に問題があるのではないかと思いますが…。

それから余談ですが、今回のように連続した処理をする場合、トランザクションを意識する必要があります。
3個あるクエリのうち、途中で失敗したらデータが中途半端な状態になってしまいますからね。

トランザクション開始
①更新クエリ DoCmd.RunSQL upSQL
②追加クエリ DoCmd.RunSQL addSQL
③削除クエリDoCmd.RunSQL delSQL
コミット
エラー発生
ロールバック

具体的な関数名とか手順は調べてみてください。

投稿2016/05/13 07:57

ttyp03

総合スコア16998

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

nekomura

2016/05/13 08:04

ttyp03様 ありがとうございます! また、早々のご回答に感謝いたします。 >今回のように連続した処理をする場合、トランザクションを意識する必要があります。 なるほど…。それは意識していませんでした。 アドバイスを元に調べてみます!
nekomura

2016/05/13 08:14

ttyp03様 五月雨式の質問で申し訳ないのですが、 >DoCmd.RunSQLの中身 とはどういった意味でしょうか…。まだ勉強不足のためttyp03様の意図が良く掴めず、 申し訳ありません。 >各クエリの詳細 冗長になりますが、以下です。 upSQL = "UPDATE テーブル名 SET テーブル名売上 = [売上]*2" taddSQL = "INSERT INTO アクションクエリ結果テーブル ( 番号, 名前, 売上 ) SELECT テーブル名番号, テーブル名.名前, テーブル名.売上 FROM テーブル名 WHERE (((テーブル名.結果)=True))" delSQL = "DELETE テーブル名.結果 FROM テーブル名 WHERE (((テーブル名.結果)=True))" bkSQL = "SELECT テーブル名.番号, テーブル名.名前, テーブル名.分類, テーブル名.日付, テーブル名.売上, テーブル名.結果 INTO バックアップ_テーブル名 FROM テーブル名" 後ほど本質問にも追記しておきます! よろしくお願いいたします。
ttyp03

2016/05/13 08:28

失礼しました。 DoCmd.RunSQLはVBAのメソッドなのですね。 過去の質問から独自に作ったのかと思いました。 クエリについては、「SET テーブル名売上」のところが、テーブル名の後ろにピリオドがないのが気になりましたが、単に編集ミスでしょうか。 更新クエリ自体は他に気になるところはないです。
nekomura

2016/05/16 02:41

ttyp03様 いつもお世話になっております。 少し日にちが空いてしまい申し訳ないのですが、 表題の件で行き詰ってしまいもう少々お知恵をお貸しいただけないでしょうか。 >クエリについては、「SET テーブル名売上」のところが、テーブル名の後ろにピリオドがないのが気になりましたが、単に編集ミスでしょうか。 はい、その通りです。 >今回のように連続した処理をする場合、トランザクションを意識する必要があります。 ご教示いただいた内容を元に、調べてみました。 まだ深く理解は出来ず解決には至っていないのですが、トランザクション処理をする場合は、DAOを使用して、excuteメソッドを使用するということになりますでしょうか? 本質問に記載しております成功例、bkSQLのように、DoCmd.RunSQLメソッドだけでシンプルに実現させることは難しいのでしょうか…。 ちなみに、表題にある元のソースですが、コメントアウトして一つずつ実行したところ、真ん中の追加クエリのみが実行できました。 また、最後の削除クエリについては実行時エラーが出た為、下記URLの https://support.office.com/ja-jp/article/-%E6%8C%87%E5%AE%9A%E3%81%95%E3%82%8C%E3%81%9F%E3%83%86%E3%83%BC%E3%83%96%E3%83%AB%E3%81%8B%E3%82%89%E5%89%8A%E9%99%A4%E3%81%A7%E3%81%8D%E3%81%BE%E3%81%9B%E3%82%93%E3%81%A7%E3%81%97%E3%81%9F%E3%80%82-%E3%81%A8%E3%81%84%E3%81%86%E3%82%A8%E3%83%A9%E3%83%BC-%E3%83%A1%E3%83%83%E3%82%BB%E3%83%BC%E3%82%B8%E3%81%8C%E8%A1%A8%E7%A4%BA%E3%81%95%E3%82%8C%E3%82%8B-20dec5e8-5402-4667-802d-523cf4923a46 固有のレコード" プロパティを [Yes/はい] に設定もやってみたのですがエラーは解決されず…。 可能であれば、今一度ご教示を頂ければ幸いです。 何か気になるところのヒントだけでも結構ですので、どうぞお知恵をおかしください。
ttyp03

2016/05/16 04:03

トランザクションについて 少し調べてみましたが、DoCmd.RunSQLではトランザクションはできないようですね。 DAOやADOでトランザクションを実装することになりそうです。 DAOであれば、DoCmd.RunSQLをCurrentDb.Executeに置き換えればすみそうですね。 削除クエリについて 構文が間違ってますね。次のような感じでよいでしょう。 DELETE FROM テーブル名 WHERE 結果=True 削除の場合、レコード単位での削除になるので、DELETEのあとにカラムを記述しているのが間違いです。
nekomura

2016/05/16 08:07

ttyp03 様 本日は時間の都合でDAOでの実装は出来なかったのですが、 >DAOであれば、DoCmd.RunSQLをCurrentDb.Executeに置き換えればすみそうですね。 この方法(トランザクション)は、経験地の浅い私には思いつかないので、毎回新しい知識をご教示いただいけるので勉強になります。 いつもありがとうございます。
ttyp03

2016/05/16 08:21

トランザクションについてはデータベースを使う限り必ず出てくると思うので、頭に入れておいた方がいいですね。 ところで削除クエリは解決できましたか?
nekomura

2016/05/17 02:19

ttyp03 様 あの後上司から「トランザクションを学んでおくように」と言われ、おお!となりました。 色々とご教示頂き大変助かっております。 削除クエリですが、SQLserver側の認証をwindows認証からSQLserver認証に変更し、 元のテーブルを設定しなおす事で(主キーや、Accessとの型の整合性)解決いたしました。 ありがとうございました!
guest

0

更新クエリの内容がまずいのではないでしょうか?
このあたりが参考になりそうです。
http://accessvba.blog.so-net.ne.jp/2012-01-11

投稿2016/05/13 07:51

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

nekomura

2016/05/13 08:05

skuromaku様 いつもお世話になっております。 このサイトは知りませんでした、参考になりそうですね。 これを元にもう少し試行錯誤してみます。 よろしくお願いいたします。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問