Microsoft Accessのいくつかのクエリで、次のようなメッセージが表示されます。 操作は更新可能なクエリを使用する必要があります。(というメッセージが表示されます(エラー3073)。 一時テーブルを使用して回避していますが、もっと良い方法はないでしょうか。 関係するすべてのテーブルには主キーがあります。以下はそのコードです。
UPDATE CLOG SET CLOG.NEXTDUE = (
SELECT H1.paidthru
FROM CTRHIST as H1
WHERE H1.ACCT = clog.ACCT AND
H1.SEQNO = (
SELECT MAX(SEQNO)
FROM CTRHIST
WHERE CTRHIST.ACCT = Clog.ACCT AND
CTRHIST.AMTPAID > 0 AND
CTRHIST.DATEPAID < CLOG.UPDATED_ON
)
)
WHERE CLOG.NEXTDUE IS NULL;
Jet 4 以降、データを要約する SQL 文への JOIN を持つすべてのクエリは、更新不可になります。あなたはJOINを使用していませんが、WHERE句はまさにJOINと同等なので、JetクエリオプティマイザはこれをJOINと同じように扱います。
しかし、私よりもJet SQLの知識がある人なら、回避策を思いつくかもしれません。
ちなみに、Jet 3.5 (Access 97)では更新可能だったクエリの多くが、Jet 4にアップグレードすると更新不可能になります。
--
次のクエリが機能しない同様の問題がありました。
update tbl_Lot_Valuation_Details as LVD
set LVD.LGAName = (select LGA.LGA_NAME from tbl_Prop_LGA as LGA where LGA.LGA_CODE = LVD.LGCode)
where LVD.LGAName is null;
update tbl_LOT_VALUATION_DETAILS inner join tbl_prop_LGA on tbl_LOT_VALUATION_DETAILS.LGCode = tbl_prop_LGA.LGA_CODE
set tbl_LOT_VALUATION_DETAILS.LGAName = [tbl_Prop_LGA].[LGA_NAME]
where tbl_LOT_VALUATION_DETAILS.LGAName is null;
ただし、DLookupを使用すると問題が解決しました。
update tbl_Lot_Valuation_Details as LVD
set LVD.LGAName = dlookup("LGA_NAME", "tbl_Prop_LGA", "LGA_CODE="+LVD.LGCode)
where LVD.LGAName is null;
このソリューションは当初、https://stackoverflow.com/questions/537161/sql-update-woes-in-ms-access-operation-must-use-an-updateable-queryで提案されました。
この問題は明らかにmax()関数の使用に関連するものです。結合中に使用される集約関数(結合されたテーブルから最大値、最小値、平均値を取得する場合など)はすべてエラーの原因となります。また、(元のコードのように)結合の代わりにサブクエリを使用した場合にも同じことが言えます。
これは非常に迷惑なことです(そして不当なことです!)。私はこれを回避するために一時テーブルを使用しなければなりませんでした(insertステートメントで集約値を一時テーブルに取り込み、更新でこのテーブルに結合し、一時テーブルを削除します)。
Glenn
コードにエラーはありません。 しかし、次の理由により、エラーはスローされます。
- Please check weather you have given Read-write permission to MS-Access database file.
- The Database file where it is stored (say in Folder1) is read-only..?
データベース(MS-Accessファイル)を読み取り専用フォルダーに保存し、アプリケーションを実行しているときに接続が強制的に開かれていないとします。 したがって、「C:\ Program files」のようにファイル権限/そのフォルダー権限を変更します。ほとんどすべてのcドライブファイルが設定されているため、この権限を変更するとこの問題が解決します。
これは、更新されるテーブルのUNIQUE MS-ACCESSキーがない場合に発生します。 (SQLスキーマに関係なく)。
SQLテーブルへのMS-Accessリンクを作成する場合、リンク時にインデックス(キー)を指定するように求められます。 これが正しく行われていない場合、またはまったく行われていない場合、リンクされたテーブルに対するクエリは更新できません。
SQLテーブルをAccess MAKE SUREにリンクする場合、Accessがインデックス(キー)を要求するときに、SQLが問題を回避するために使用するものを正確に使用しますが、一意のキーを指定すると、Accessがテーブルを更新する必要があります。
テーブルを最初にリンクした人物でない場合は、リンクされたテーブルをMS-ACCESSから削除し(リンクは削除されるだけです)、キーを指定して再度リンクすると、すべてが正しく機能します。
AccessでUPDATEクエリを作成してみます。 自分で書いた更新クエリがありました。
UPDATE TABLE1
SET Field1 =
(SELECT Table2.Field2
FROM Table2
WHERE Table2.UniqueIDColumn = Table1.UniqueIDColumn)
クエリはあなたが見ているそのエラーを私に与えました。 これは私のSQL Serverで機能しましたが、前述のように、Access UPDATE構文は標準の構文ではありません。 ただし、Accessのクエリウィザードを使用して再構築した場合(JOIN構文を使用)、問題なく動作しました。 通常、UPDATEクエリをパススルーにして非JET構文を使用しますが、参加していたテーブルの1つはローカルアクセステーブルでした。
上記のiDevlopによる回答は、私にとってはうまくいきました。 更新クエリでRecordsetTypeプロパティが見つからなかったことに注意してください。 ただし、クエリを選択クエリに変更し、そのプロパティをiDevlopが指摘するように設定してから、クエリを更新クエリに変更することで、そのプロパティを見つけることができました。 これはうまくいきました。臨時テーブルは必要ありません。
これがiDevlopが投稿した内容へのコメントになり、彼のソリューションから流れたかったのですが、十分なスコアがありません。
要するに、あなたのSQLは完全に合理的に見えますが、JetはUPDATE
のためのSQL標準構文をサポートしたことがありません。その代わりに、Jetは独自の構文(SQL Server独自のUPDATE
構文とはまた異なる)を使用しており、それは非常に*制限されています。多くの場合、唯一の回避策である "Operation must use an updatable query" は、非常につらいものです。より高性能なSQL製品への乗り換えを真剣に検討してください。
具体的な問題の詳細と可能な回避策については、Update Query Based on Totals Query Fails を参照してください。
今日の私のMS-Access 2003では、ODBC tablaがSAパスワードを使用してSQL Server 2000を指しているため、同じエラーが発生しました。 SQL Serverデータベースのテーブルに主キーを定義しましたが、問題はなくなりました。
同様に更新するコードをVBAにいつでも書き込むことができます。 私もこの問題がありました。, そして、私の回避策は選択されたクエリを作成することでした。, すべての結合で。, 更新できるように探していたすべてのデータがありました。, そのレコードセットを作成し、更新クエリを繰り返し、更新テーブルのみの更新クエリとして実行します。, 基準のみを検索します'。;探しています。
Dim updatingItems As Recordset
Dim clientName As String
Dim tableID As String
Set updatingItems = CurrentDb.OpenRecordset("*insert SELECT SQL here*");", dbOpenDynaset)
Do Until updatingItems .EOF
clientName = updatingItems .Fields("strName")
tableID = updatingItems .Fields("ID")
DoCmd.RunSQL "UPDATE *ONLY TABLE TO UPDATE* SET *TABLE*.strClientName= '" & clientName & "' WHERE (((*TABLE*.ID)=" & tableID & "))"
updatingItems.MoveNext
Loop
私はこれを1日に約60レコードしか行っていません。クエリが最初から最後まで複数回実行されているため、グループ全体を選択して変更を加えるだけでなく、数千レコードを実行すると、さらに時間がかかる可能性があります。 tableIDの引用符の周りには文字列であるため、「」が必要になる場合がありますが、これが私にとってうまくいったことだと私は確信しています。
DRUAが彼/彼女の答えで言及したことにさらに答えるため。..
Access 2007でデータベースを開発しています。 私のユーザーはaccess 2007ランタイムを使用しています。 彼らは、database_Front(フロントエンド)フォルダーへの読み取り権限と、database_Backフォルダーへの読み取り/書き込み権限を持っています。
新しいデータベースを展開する際、ユーザーはフロントエンドをコンピューターにコピーするという完全な指示に従わず、代わりにショートカットを作成しました。 ショートカットでフロントエンドを実行すると、ファイルの書き込み制限のためにクエリが更新できない状態になります。
フロントエンドをドキュメントフォルダにコピーすると、問題が解決します。
はい、ユーザーがフロントエンドの更新バージョンを取得する必要がある場合は複雑になりますが、少なくともクエリは一時的なテーブルなどに頼る必要なく機能します。