• 締切済み

SELECT FOR UPDATE で該当レコードがなかった場合

SELECT FOR UPDATE ですが、該当レコードのみ ロックすると思うんですが、 該当レコードがない場合は、 ロックできないんでしょうか? たとえば、(COLUMN_BBB が PK として) SELECT * FROM TABLE_AAA WHERE TABLE_AAA.COLUMN_BBB = 'BBB' FOR UPDATE で、そもそも SELECT * FROM TABLE_AAA WHERE TABLE_AAA.COLUMN_BBB = 'BBB' となるレコードがない場合でも、 他トランザクションによる 該当レコードの INSERT を排他防御できるのか無理なのか、 教えていただけたらありがたいです。 すみません、時間的余裕があまりないので、 (すぐに回答ほしいです)でアップします。

  • Oracle
  • 回答数1
  • ありがとう数2

みんなの回答

回答No.1

ロックする対象がなければ、ロックのしようがありません。 インサートするレコードのキーを予約する意味での行為なら、そのような手法ではだめです。 代替え策ですが、FOR-UPDATEで存在チェック&インサート予約、その後にじっくりインサートするのでなく、 いきなりプライマリーキーだけインサートして、インサートできたなら、存在チェックOK&予約済みとし、 後でその他のデータを更新すると良いかと思います。 もし、更新を辞めたいなら、ロールバックすれば良いかと。

関連するQ&A

  • select for updateのロック

    オラクルのselect for updateでロックをするタイミングがいつですか? こんなPL/SQLのコードがあったとします。 ---↓↓↓ソースコードここから↓↓↓------------------------- select * from テーブル1 where id = 1 for update; ・・・・・(a) ~ update テーブル1 set kingaku=100 where id = 1 ・・・・・(b) ~ commit; ---↑↑↑ソースコードここまで↑↑↑------------------------- id = 1のレコードがロックされるのは(a)、(b)どちらのタイミングですか? また、このロックは ・他トランザクションから読めるけど更新できない ・他トランザクションからは読むことすらできない のどちらでしょうか? よろしくお願いします。

  • select されたレコードの操作

    以下のようなuser_idとuser_pwのtableがあります。 |id(ai)|user_id|user_pw|flg| |1|AAA|111|0| |2|BBB|222|0| select id from table where user_id = AAA をされると 1 を返し、 update table set flg = 1 where id = 1 かまたは update table set flg = 1 where user_id = AAA を発行したいと思っています。 ただ、sql 発行元から2個のsqlを出せない事情があり、DB側で対応しなければなりません。 トリガはselectでは使えませんよね?  最悪、query_logを監視しながらselectが来たら自分でupdateを発行するスクリプト しかないのかと考えています。 アドバイスお願いします。

  • SELECT FOR UPDATE について

    ■SELECT FOR UPDATEとは、 複数のプログラムで在庫の更新などが行われる場合に、 使用するべきでしょうか? ■SELECT FOR UPDATEのロック期間は、他の更新が待たされるのは 下記2.~3.の間でしょうか? バッチ更新(5分) 1.トランザクション開始 2.SELECT FOR UPDATE 3.UPDATE 4.トランザクション終了 ■上記2.のSELECT FOR UPDATEがおこなれた時点のレコードに対し、  他の場所でSELECT FOR UPDATEした場合、  上記2.の時点のデータがSELECTされるのでしょうか?  それとも、上記3.が終わるまでSELECTを待つのでしょうか? DBは、MySQL5ですが、DB問わず同じ挙動と思い、 このカテゴリに質問されていただきました。

  • 排他ロックしたレコードが、別トランザクションから参照されてしまい困っています。

    SQL Server2000を使用し、 あるトランザクションで排他ロック(XLOCK)をかけたレコードが 他のトランザクションから共有ロックを使用し参照できてしまう状態は存在するのでしょうか? 排他ロックをかけたレコードが 他のトランザクションから参照できてしまい困っています。 現在、下記の環境で開発を行っております。 ・サーバ側 Windows Server2003 SQL Server2000(sp4) ・クライアント側 Windows Xp(sp3) jdk6.0 jdbc 3.0 Type4 以下が具体的な状況となります。 前提として、 ・二つのトランザクション(以下A、Bと表記します)が存在する。 ・AとBは別のユーザでコネクションを張っている。 ・autoCommitはfalseに設定している。 ・テーブルにプライマリキーやインデックスは張っていない。 ・レコードは10件。 ・分離レベルはREAD COMMITED (1)Aから、「SELECT * FROM TEST_TABLE WITH(XLOCK) 」を発行 (2)Bから、「SELECT * FROM TEST_TABLE」を発行 このような状況で、(1)、(2)の順で処理を行った場合に 私の認識では、(2)の検索時にタイムアウト等が発生するという認識です。 しかし、(2)のSQLは正常に終了し、(1)と同じデータが取得されてしまいます。 ◆その他、確認したこと ・(1)の処理直後に処理を停止し、Enterprise Managerでロックが取得されているか確認したところ、トランザクションAがすべてのレコードを排他ロック(X)していた。 ・(2)の処理直後にロックの状態を確認しても、やはりトランザクションAが、排他ロック(X)していた。 ・CSEを使いODBC経由で同様の操作を行った場合も同じ動作がおこる。 ・(1)WITH(XLOCK, TABLOCK)とすると(2)でデータが取得できなくなる。 ・(2)のSQLを「SELECT * FROM TEST_TABLE WHERE COLUMN01 > 0」のように指定するとタイムアウトする(期待通りの動き) ・(2)のSQLを「SELECT COLUMN01 FROM TEST_TABLE WHERE COLUMN01 > 0」のように指定すると、今度は、なぜか取得出来てしまう。 ・(1)と(2)の間にトランザクションAでUPDATEなどを行うと(COMMITはしない)(2)のSQLのWHERE句や取得するカラムに関係なく、(2)のSQLはタイムアウトする(当り前か。。。) いろいろ書きましたが、排他ロックされたレコードに 共有ロックはかけれないという認識なのですが、 そうではないのでしょうか? また、そうではない場合どういった場合に、 共有ロックが可能となるのでしょうか? SQL Serverの排他制御に詳しい方や 同じような現象に陥った方がいましたら、ご教授お願いします。

  • 複数テーブルからデータを取り、updateする

    http://oshiete1.goo.ne.jp/kotaeru.php3?q=1211685 にも同じような質問があったのですが、同様の処理でうまくupdateされません。分かる方がいらっしゃいましたら教えてください。 今、テーブルが2つ(table1、table2)があり、それぞれ2つのカラム(column1、column2)を持っています。ここで、それぞれのカラム2が等しく、カラム1が指定した値のレコードのみ値をupdateしたいです。 update table1 set column1 = 'AAA' from table1,table2 where table1.column2 = table2.column2 and table1.column1 = 'BBB' and table2.column1 = 'CCC' としたところ、「from table1,table2 where 」の辺りに間違いがあると表示されます。 上の例とどう違うのか分かりません。 よろしくお願いします。m(__)m

  • mysqlで横方向ではなく縦方向の条件抽出は…

    id   hoge   num 01   AAA   0 01   BBB   1 02   AAA   1 03   BBB   0 というテーブルがあったとします。 select id from table where hoge='AAA' and num=0 のような条件で検索するのは普通ですが、 カラムではなくレコード単位で見て hogeの値がAAAとBBBの両方である場合のデータとして「01」というidのみを抽出する方法はないものでしょうか。 よろしくお願いします。

    • ベストアンサー
    • MySQL
  • SELECT FOR UPDATE にトランザクションは必要ですか?

    SELECT FOR UPDATE を使う時に、 SELECTの前でトランザクションを開始する必要はあるでしょうか? それとも、ただ、 SELECT FOR UPDATE UPDATE でも、行ロックされるでしょうか? そもそもトランザクションとは、 複数の更新がない場合は使う必要はないのでしょうか?

    • ベストアンサー
    • MySQL
  • SELECT時の行ロックの必要性について

    SELECT ~ FOR UPDATEやSELECT ~ LOCK IN SHARE MODEという行ロックがあり、この件について解説しているサイトをいろいろ見ているのですが、振る舞いが複雑だということはわかりました。 しかしそもそもなぜSELECTで行ロックするのか、運用上でどんなときに使うのかを解説しているサイトは見当たりませんでした。 私は、SELECTするときは単に SELECT * FROM tb_a WHERE id = 1; としか記述していません。 質問1. なぜSELECTするのにトランザクションが必要なのでしょうか?運用上でどんなときにSELECTでトランザクションを使うのでしょうか?よく解説サイトには、 BEGIN; SELECT * FROM tb_a WHERE id = 1 FOR UPDATE; COMMIT; と書いています。SELECTするのに行をロックする必要性がいまいちわからないです。 質問2. トランザクションを開始したときにロックがかかるのではないのでしょうか?つまりBEGIN;でロックがかかるわけではないのですか?SELECTのクエリーにFOR UPDATEと書くということはこのSELECTのコードが実行された時点でロックがかかるのでしょうか? 質問3. FOR UPDATEやLOCK IN SHARE MODEというのはSELECTにしか使えないのか、もしくはSELECTだから意味があるのでしょうか?UPDATEやDELETEは単にBEGINE;とCOMMIT;で囲えばいいだけですよね? 質問4. 以下のようなコードを解説しているサイトがあります。 BEGIN; SELECT * FROM tb_a WHERE id = 1; COMMIT; SELECT文にはFOR UPDATEも書いていないのですが、これは何を意味するのでしょうか?つまり、SELECTするのになぜトランザクションを実行するのでしょうか? 一番知りたいのは運用上どのような場合にSELECTでトランザクションを使って行ロックするのか、ということです。 どうぞよろしくお願い致します。

    • ベストアンサー
    • MySQL
  • SQLで他のテーブルに無いIDの抽出

    MySQLを使っています。 下記は、 1.テーブルaaaには、存在するidのものが、 2.テーブルbbbには、存在しない、 3.テーブルaaaのレコードを抽出したいものです。 "SELECT DISTINCT aaa.*" + " FROM aaa" + " WHERE (aaa.flag = false)" + " AND NOT EXISTS (SELECT * FROM bbb" + " WHERE (aaa.id = bbb.id) AND (bbb.flag = false))" ですが、実行すると、下記エラーがでます。 SQLException:Base table or view not found, message from server: \"Unknown table 'bbb' in where clause" どうすればよいのでしょうか?

    • ベストアンサー
    • MySQL
  • すっきりとしたSQL文にしたいのですが

    Oracle9iにてテーブルのデータを更新しようと思っています。 目的としてはAAAのカラムa1とBBBのカラムb1が同一なレコードである場合、 AAAのa2にBBBのb2を更新したいのですが、 <条件> AAA:テーブル1 BBB:テーブル2 a1:CHAR b1:CHAR a2:VERCHAR b2:VERCHAR すべて必須で桁数は10 UPDATE AAA SET AAA.a2 = ( SELECT BBB.b2 FROM BBB WHERE AAA.a1 = BBB.b1) WHERE AAA.a1 = ( SELECT BBB.b1 FROM BBB WHERE AAA.a1 = BBB.b1) ; いまはこんな無駄の多そうなSQLしか分かりません。 この他にも条件が2つ追加される予定なので もっとすっきり更新できる方法を教えていただけませんでしょうか? よろしくお願いします。