web-dev-qa-db-ja.com

MS AccessでのSQL更新の問題-操作は更新可能なクエリを使用する必要があります

別のテーブルで検索できるように、基本的にフィールドを再フォーマットするためにテキスト操作を行う選択クエリがあります。

「J1/2」のようなフィールドがある最初のテーブルの場合、適切なフィールドにJ1とJ2がある別のテーブルのレコードのIDを検索します。

これはすべてうまくいきます。

次に、元のテーブルを更新したいので、この文字列操作を使用してルックアップを実行する必要はありませんが、更新クエリでの試行は「操作は更新可能なクエリを使用する必要があります」で終わります

何か案は?

私のSELECTステートメント:

SELECT DISTINCT
t1.DD,
t1.TN,
t1.DD & " J" & MID(t1.TN,2,1) AS CalculatedStart,
t1.DD & " J" & MID(t1.TN,4,1) AS CalculatedEnd,
t2.ID
FROM t1 INNER JOIN t2
ON (t1.DD & " J" & MID(t1.TN,2,1)=t2.StartLink)
AND (t1.DD & " J" & MID(t1.TN,4,1)=t2.EndLink)
WHERE t1.TN Like "J?/?"
AND t1.DD Like "M*";

思い出してください-これは問題なく動作し、必要なt2.IDをもう一方の端から取得します。

だから私は次のようなことをしたいです:

UPDATE t1 SET t2ID = (
    SELECT Query1.ID
    FROM Query1
    WHERE t1.DD=Query1.DD
    AND t1.TN=Query1.TN
    )
WHERE t1.TN Like "J?/?"
AND t1.DD Like "M*";

これだけが失敗します。これはMS Access自体の内部にあるため、「操作は更新可能なクエリを使用する必要がある」という問題のほとんどのように、実際の権限の問題を想像できません。

編集:うまくいかないケースを単純化しようとしています。

このUPDATEクエリは問題ありません。

UPDATE t1
SET t2ID="Unknown"
WHERE TN LIKE "J?/?"
AND DD LIKE "M*";

これは失敗します(Goedkeに感謝-サブクエリが複数の結果を返すため、この例は明らかに失敗します。問題を見つけるために単純化しすぎていました)

UPDATE t1
SET t2ID=(SELECT ID FROM t2)
WHERE TN LIKE "J?/?"
AND DD LIKE "M*";

それで、サブクエリ構文が何らかの方法で間違っているだけですか?

編集:このSELECTステートメントも問題ありません:

SELECT t1.OA, t1.DD, t1.TN, t1.HATRIS,
    query1.DD, query1.TN, query1.ID
FROM t1 INNER JOIN query1
ON t1.DD=query1.DD
AND t1.TN=query1.TN

さらに、上記のselectステートメントでcountを使用すると、(DD、TN)の組み合わせごとに正確に1つのIDが返されることが示されます

編集:

私が今までに持ってきた最も単純なケース-さまざまなSELECTステートメントを使用して、2列だけのテーブルを作成しました-t1の主キーとt1に挿入する値。

まだ書けないようです

UPDATE t1 SET t1.f2 = (SELECT t2.f2 FROM t2 WHERE t2.f1 = t1.f1)

ここで、t1の主キーはf1です。 WHERE t1.f1 IN(SELECT f1 FROM t2)を追加しても役に立ちません。 (サブクエリが0の結果を返す可能性を排除するために追加されました)

15
Paul Smith

(SELECT ID FROM t2)のサブクエリは、t2に1つのレコードしかない場合は機能しません。どのIDを使用する予定ですか?

報告されているエラーメッセージは通常、結合があり、データバインドフォームのテーブルに更新するために必要なすべての主キーが含まれていない場合に発生します(たとえば、元のDISTINCTはキーに関する情報を破棄するため、バインドされている場合フォームに戻すと、フォームは保存できなくなります)。

ここでDISTINCTを使用しているという事実は、サブクエリがより複雑な例で複数の行を返しているのではないかと疑っています。これはおそらく、サブクエリの結果からの割り当てで最も一般的な問題です。where句の制約が不十分です。

サブクエリからの割り当てで見た別の問題は、内部クエリのsyntaxが正しくない場合です。少なくともSQL 2000および2005のバックエンドでは、クエリプロセッサはサイレントに失敗し、そのような場合にNULLを返します。 (これは、私が知る限り、バグです。トップレベルでエラーを返す何かがサブクエリで黙って許可される理由はわかりません...しかし、それはあります。)

編集:ポールも私も夢中にならないようにするために、次のテーブルを作成しました。

t1 | ID, FK, Data
t2 | ID2, Data2

IDとID2に主キー以外の制約を設定しましたしません。すべてのフィールドはテキストでした。これは、通常IDに使用するものとは異なりますが、無関係である必要があります。

t1:

ID  FK  Data
Key1        Data1
Key2        Data2
Key3        Data3

t2:

ID2 Data2
Key1    DataA
Key2    DataB
Key3    DataC

次の形式のクエリ:

UPDATE t1 SET t1.FK = (select ID2 from t2 where t2.ID2 = t1.ID);

Paulが受け取ったのと同じメッセージで失敗しました。

select *, (select ID2 from t2 where t2.ID2 = t1.ID) as foreign from t1, 

期待どおりに動作するため、サブクエリ構文に問題がないことがわかります。

UPDATE t1 SET t1.FK = 'Key1'

も期待どおりに機能するため、破損したり更新できない宛先はありません。

注:データベースバックエンドをネイティブからSQL 2005に変更すると、更新が機能します。少しグーグルで回って、Access MVPがDLOOKUPにサブクエリを置き換えるように提案しているのを見つけます。

http://www.eggheadcafe.com/software/aspnet/31849054/update-with-subquerycomp.aspx

どうやらこれはAccess SQLのバグであり、SQL Express 2000以降のバックエンドを使用するときに回避されるバグです。 (「アクセス更新サブクエリ」のGoogleの結果はこの理論をサポートしています)。

この回避策の使用方法については、こちらをご覧ください: http://www.techonthenet.com/access/functions/domain/dlookup.php

6
Godeke

OPに関するDavid W. Fentonのコメントを検討する必要があります。

これはJet/ACEで非常に迷惑な問題です。しかし、どちらかを試してください:

  1. クエリのプロパティに移動し(テーブルが表示されているペインの背景をクリック)、[Unique Records]を[Yes]に設定します
  2. オプション1は、少し奇妙に見えるDISTINCTROWキーワードをSELECT句に追加するのと同じです。たとえば、

UPDATE DISTINCTROW tblClient 
       INNER JOIN qryICMSClientCMFinite 
          ON tblClient.ClientID = qryICMSClientCMFinite.ClientID
   SET tblClient.ClientCMType = "F";

これにより、このエラーメッセージに関連する多くの問題が解決され、ほとんどばかげています。

それが一言で言えばMS Accessです。問題xに対する企業秘密の回避策がわからない場合は、答えを見つけるのに何日もかかることがあります。 10,000の回避策を知るにはISでAccessをプログラムします。これは、初心者に対する警告で十分ですか?

ベン

17
Ben McIntyre

これは私のために働きました(Access 2000)

UPDATE DISTINCTROW T1 inner join T2 on T2.f1 = T1.f1  SET f2 = f2;
7
David Leigh

私はスレッド全体を読んでいませんが、これは私が使用している解決策です:

update (select * from t1 inner join t2 on t1.key = t2.key) set t1.field1 = t2.field2

そして、それは私にとってMS Accessでうまく機能します。

6
Sandip

Access 2010を使用して同じエラー(「操作は更新可能なクエリを使用する必要があります」)が発生し、内部結合を使用した単純な更新クエリを実行していました。私が行ったのは、参加しているテーブルに主キーを追加することだけで(もちろん、更新中のテーブルに既に1つありました)、すべてが機能しました。

1
user3775507

私の解決策はそのように私のSQLを変更することでした。

  update (select o.pricein, g.pricein from operations o left join goods g on g.id = o.goodid where o.opertype = 4 and o.acct = 1) 
  set o.pricein = g.pricein
1
Plamen

この場合:UPDATE t1 SET t1.f2 =(SELECT t2.f2 FROM t2 WHERE t2.f1 = t1.f1)

UPDATE t1 INNER JOIN t2 ON t1.f1 = t2.f1 SET t1.f2 = [t2].[f2];
0
JeffO