会員登録で5000円分が当たります

DELETE 文とEXISTSの使い方について(Oracle10g)

2つのテーブル(A、B)を外部結合して、B側がNULLとなったレコードを
A側から削除する、というDELETE文が作りたいのですが、
EXISTS句を使ってみたもののどうも使い方がわからず苦戦しています。

目的は2つのテーブルを同期させる事で
このSQLを実行する時点で、常にA>Bになっています。

目的を達成できるSQLを教えてください。

<削除対象レコードをSELECTするSQL>
SELECT *
FROM A,
B
WHERE A.KEY1 = B.KEY1(+)
AND A.KEY2 = B.KEY2(+)
AND B.KEY1 IS NULL
;

<上をDELETE文にしてみたつもりが、削除0件になってしまうSQL>
DELETE FROM A
WHERE EXISTS(
SELECT 1
FROM B
WHERE A.KEY1 = B.KEY1(+)
AND A.KEY2 = B.KEY2(+)
AND B.KEY1 IS NULL
)
;

このQ&Aに関連する最新のQ&A

A 回答 (3件)

まず、select文について質問です。


※の行はテーブルを結合する上で必要ですか?

<削除対象レコードをSELECTするSQL>
SELECT *
FROM A,
B
WHERE A.KEY1 = B.KEY1(+)
AND A.KEY2 = B.KEY2(+) ←※
AND B.KEY1 IS NULL

必要がないようでしたら、

DELETE FROM A
WHERE NOT EXISTS (SELECT * FROM B WHERE A.KEY1 = B.KEY1);

でどうでしょか?
    • good
    • 0
この回答へのお礼

ご回答ありがとうございます。
NOT EXISTSは盲点でした。
B.KEY2は必要なため、少し加工して目的の結果が得られました。

DELETE FROM A
WHERE NOT EXISTS
(SELECT * FROM B WHERE A.KEY1 = B.KEY1 AND A.KEY2 = B.KEY2);

お礼日時:2010/03/16 14:46

DELETE A


FROM A LEFT JOIN B
ON A.KEY1 = B.KEY1
AND A.KEY2 = B.KEY2
WHERE B.KEY1 IS NULL

こんな感じのような気がします。
お試しあれ。

A.KEY1 = B.KEY1(+)
とか
A.KEY1 =* B.KEY1
みたいな書式は互換性が乏しいので、
如何なものかと・・・
    • good
    • 0

DELETE FROM A


WHERE A.KEY1 = (
SELECT A.KEY1
FROM A,
B
WHERE A.KEY1 = B.KEY1(+)
AND A.KEY2 = B.KEY2(+)
AND B.KEY1 IS NULL
)
;

こうでどうでしょう?
A.KEY1 =
より
A.KEY1 IN
かもしれませんが。
    • good
    • 0
この回答へのお礼

ご回答ありがとうございます。

言葉足らずでしたが、DELETE行を特定するには、
KEY1,KEY2 ともに必要です。
そのため、IN(副問合せ)では、KEY1 || KEY2 とする
必要があり、結果を得れましたがパフォーマンスが出ずに
断念しました。

お礼日時:2010/03/16 14:49

このQ&Aに関連する人気のQ&A

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています

関連するカテゴリからQ&Aを探す

このQ&Aと関連する良く見られている質問

QEXISTSを使ったDELETE文

「SELECT文の件数」と、
「同じSELECT文を使ったDELETE文の件数」が一致しない現象が起き、困っています。

【SELECT文】※2件返ってきます。
SELECT
  a.部署コード,
  a.社員コード
FROM
  社員マスタ a,
  組織マスタ b
WHERE
  a.部署コード = b.部署コード


【DELETE文】※50件 DELETEされます。
DELETE TABLE
  社員マスタ
WHERE
  EXISTS
  (
  SELECT
    a.部署コード,
    a.社員コード
  FROM
    社員マスタ a,
    組織マスタ b
  WHERE
    a.部署コード = b.部署コード
  )


環境はSQLSERVER2005です。
件数はSQLSERVER2005のカウントオプションで表示されているものなので間違いないです。

宜しくお願いします。

Aベストアンサー

EXISTS 句は、副問い合わせが行を返した場合 TRUE そうでない場合 FALSE と評価されます。

例示いただいた副問い合わせは TRUE を返すので DELETE されます。

詳細については、SQLの入門書を参考にしてください。

QSQL、2つのテーブルで条件一致したものだけdeleteする方法は?

オラクルSQLで質問です

やりたいことは、
テーブルAから以下の条件に該当するデータを削除する。
基本的にはテーブルBの内容と比較して、一致したもの。

条件(全ての条件を満たすこと)
 テーブルA.AAA = テーブルB.AAA
 テーブルA.BBB = テーブルB.BBB
 テーブルB.CCC > 0


調べたところ、SQLサーバでは以下のように
from を2つ書いて実現できるようです。
が、今回はオラクルなので文法エラーになります。

delete FROM テーブルA FROM テーブルB
where
テーブルA.AAA = テーブルB.AAA
AND
テーブルA.BBB = テーブルB.BBB
AND
テーブルA.CCC > 0
;
commit;


よろしくお願いします

Aベストアンサー

delete 文の細かい構文はちょっと覚えてませんが
サブクエリ使えばいいんじゃないですか

delete from table_a
where 主キーカラム = (
select table_a.主キーカラム
from table_a, table_b
where
指定の条件
)

Q片方のテーブルに無いデータを削除したい

過去ログを探っていろいろ試したのですが、うまくいかないので
教えてください。
TABLE1 に存在しない TABLE2 のデータをDELETEしたいのですが
TABLE2 の対象年月(item2の内容)が、指定年月以上の条件で
DELETEしたいのです。

●指定月=2008/02 の場合

<TABLE1>
key1 key1 key1 item1  item2
a   a   a   あ   2007/12
b   b   b   い   2007/12
c   c   c   う   2007/12

<TABLE2>
key1 key1 key1 item1  item2
a   a   a   あ   2007/12
b   b   b   い   2007/12
c   c   c   う   2007/12
d   d   d   え   2008/01 (削除しない)
e   e   e   お   2008/03 (削除対象)

<DELETE結果 TABLE2>
key1 key1 key1 item1  item2
a   a   a   あ   2007/12
b   b   b   い   2007/12
c   c   c   う   2007/12
d   d   d   え   2008/01

よろしくお願いします。
(環境:SQL Server2005 Standard)

過去ログを探っていろいろ試したのですが、うまくいかないので
教えてください。
TABLE1 に存在しない TABLE2 のデータをDELETEしたいのですが
TABLE2 の対象年月(item2の内容)が、指定年月以上の条件で
DELETEしたいのです。

●指定月=2008/02 の場合

<TABLE1>
key1 key1 key1 item1  item2
a   a   a   あ   2007/12
b   b   b   い   2007/12
c   c   c   う   2007/12

<TABLE2>
key1 key1 key1 item1  item2
a   a   a   あ...続きを読む

Aベストアンサー

SQL Server の場合、よく使うのは3パターンです。
状況に応じ使い分けられると便利なので、一応3つ書いときます。

--JOIN
DELETE TABLE2
FROM TABLE2 t2
LEFT OUTER JOIN TABLE1 t1 ON t1.KEY1=t2.KEY1 AND t1.KEY2=t2.KEY2 AND t1.KEY3=t2.KEY3
WHERE t1.KEY1 IS NULL
AND t2.ITEM2>='2008/02'

--EXISTS Clause
DELETE TABLE2
FROM TABLE2 t2
WHERE NOT EXISTS
(SELECT NULL FROM TABLE1 t1
WHERE t1.KEY1=t2.KEY1 AND t1.KEY2=t2.KEY2 AND t1.KEY3=t2.KEY3)
AND t2.ITEM2>='2008/02'

--IN Clause
DELETE FROM TABLE2
WHERE KEY1+'*'+KEY2+'*'+KEY3 NOT IN
(SELECT KEY1+'*'+KEY2+'*'+KEY3 FROM TABLE1)
AND ITEM2>='2008/02'

SQL Server の場合、よく使うのは3パターンです。
状況に応じ使い分けられると便利なので、一応3つ書いときます。

--JOIN
DELETE TABLE2
FROM TABLE2 t2
LEFT OUTER JOIN TABLE1 t1 ON t1.KEY1=t2.KEY1 AND t1.KEY2=t2.KEY2 AND t1.KEY3=t2.KEY3
WHERE t1.KEY1 IS NULL
AND t2.ITEM2>='2008/02'

--EXISTS Clause
DELETE TABLE2
FROM TABLE2 t2
WHERE NOT EXISTS
(SELECT NULL FROM TABLE1 t1
WHERE t1.KEY1=t2.KEY1 AND t1.KEY2=t2.KEY2 AND t1.KEY3=t2.KEY3)
AND t2.ITEM2>='2008/02'

...続きを読む

QUPDATE文のWHERE条件に他のテーブルのフィールドも入れたい

SQL文についてです。

表Aで列1と列2が'◎'のものについて、列3,列4,列5をそれぞれ'○','△','×'に更新したい場合は下記でOKだと思います。
UPDATE 表A
SET 列3 = '○', 列4 = '△', 列5 = '×'
WHERE 列1 = '◎' AND 列2 = '◎'

列1と列2をキーとして表Aと結合できる表Bが存在するとします。
条件に表Bの列6が'□'だった場合を追加したい時、どのような方法で行えば良いのでしょうか?
内部結合やWHERE EXISTSなどをいろいろ調べたのですが、SQL文に慣れていないためかうまくいきません。
初歩的な質問で申し訳ありませんが過去質問で参考になるものがなかったのでお願いします。

Aベストアンサー

UPDATE 表A
SET 列3 = '○', 列4 = '△', 列5 = '×'
WHERE 列1 = '◎' AND 列2 = '◎'
AND EXISTS
( SELECT 1 FROM 表B
WHERE 表B.列1 = 表A.列1
AND 表B.列2 = 表A.列2
AND 表B.列6 = '□' )
じゃだめですか。

Q3つの表の外部結合

表A、B、Cの3つがあり、Aのすべての行を出力したいと考えています。
外部結合を用いるのだとは思うのですが、3つの表に対して行う場合の
書き方がわからず困っています。
ご教授いただけないでしょうか?
select * from a,b,c
where a.商品ID =b.商品ID (+) and b.商品ID (+) =c.商品ID (+)
としてみましたが、うまくいきませんでした。

Aベストアンサー

ansi構文の趣旨からいえば、結合条件と絞り込み条件は分けて書くので・・

select *
from a
left join b on (a.商品ID =b.商品ID)
left join c on (b.商品ID =c.商品ID)
where a.年月 = 任意の値

と書くのが一般的でしょうね。

QSELECTで1件のみ取得するには?

こんにちわ。
いまORACLE9iを使用している者です。

ACCESSでは
SELECT TOP 1 項目名 FROM テーブル名
ORDER BY 項目名;
で並べ替えたデータ群のうち,先頭の1件だけを
取ることができますが,
ORACLEでそのような機能(SQL)はあるでしょうか?
教えてください。
よろしくお願いします。

Aベストアンサー

order by と rownum を併用する場合は注意が必要です。

[tbl01]
cola | colb
------------
1000 | aaaa
1001 | bbbb

というデータがある場合、
select cola from tbl01 where rownum < 1 order by cola desc;
とすると、「1001」ではなく、「1000」が返されます。
これは、order by の前に rownum < 1 が適用されてしまうからです。

解決するには、
select aaa from (select cola aaa from tbl01 order by cola desc) where rownum = 1;
とすれば良いです。

QMAX値を条件にデータを取得するには?

SQL文で困っています。
ご教授下さい。


下記のようなデータがあった場合、それぞれの区分毎に
年月が最大(最新)のデータを取得したいです。
(実際には1レコードにその他項目があり、それらも取得します。)
<検索対象データ>
区分 年月   金額
-----------------------------
A   200412  600
A   200503  560
B   200311  600
B   200508  1000
B   200504  560
C   200508  400
C   200301  1100


<取得したいデータ>

区分 年月   金額
-----------------------------
A   200503  560
B   200508  1000
C   200508  400

よろしくお願いします。

Aベストアンサー

テーブル名をXXXとすると次のようなSQLでよいと思います。(最善の方法かどうかは自信がないですが)

select B.* from (select 区分, max(年月) as 年月 from XXX group by 区分) As A
inner join XXX as B on A.区分 = B.区分 and A.年月 = B.年月
order by B.区分

QSQL文について(片方のテーブルに存在しないレコード抽出)

以下のような2つのテーブルがあったとして、
2つともに存在する「店コード」を抽出するのはSQLは分かるのですが、
片方に存在しない「店コード」(以下の例の場合、「2」)を抽出するSQLを
一文で書くにはどうすればいいのでしょうか?

<店テーブル>
店コード住所・・・(その他、基本情報)
1aaa
2bbb
3ccc

<販売テーブル>
店コード販売品目・・・(その他、販売数など)
1xxx
3zzz

Aベストアンサー

オプティマイザ次第だけど、NOT-INは、あまりお勧めでない。
外部結合も索引があっても有効に使われないので、お勧めでない。

select * from A where not exists(select 1 from B where A.店コード=B.店コード);

Q異なるテーブルのレコード削除

オラクル初心者です。宜しくお願いします。
AAA、BBB、CCCというテーブルがあると仮定します。
画面から入力された値(ddd)をキーとして、CCCテーブルから該当するレコードをセレクト文で引っ張り、eeeという値を抜き出したとします。
そのeeeという値をキーにAAA、BBBテーブルのレコードを削除するにはどういうSQLを発行すればよろしいでしょうか?
"delete from
AAA, BBB
where eee =
(select eee from CCC where fff = ddd);"
では駄目でした。
質問が下手でわかりにくいかもしれませんが、どうかご教授お願いします。

Aベストアンサー

DELETE文1文では、1つのテーブルに対してしか操作できませんので、
DELETE文を2つ投入するか、PL/SQLブロックとして投入するかいずれかに
なります。
(無名PL/SQLが投入できるミドルウエアと投入できないミドルウエアがあります)

QOracle(オラクル)で、日付時刻型の検索方法について

質問させていただきます。
データベースはオラクルを使っていて、
SQL文で、抽出するときにエラーが出て困っています。

日付時刻型が「2005/05/26 19:13:00」という感じで入ってます。
2005/05/26 を抽出したいのですが、
BETWEEN '2005/05/26 00:00:00' AND '2005/05/26 23:59:59'

だと、エラーでできません。
どなた様か、ご教授よろしくお願いしますm(_ _)m

Aベストアンサー

日付検索を行う場合は、以下のように書式を含める必要があります。

col BETWEEN TO_DATE('2005/05/26 00:00:00','YYYY/MM/DD HH24:MI:SS') AND TO_DATE('2005/05/26 23:59:59','YYYY/MM/DD HH24:MI:SS')

ただ、厳密には

col >= TO_DATE('2005/05/26', 'YYYY/MM/DD')
AND
col < TO_DATE('2005/05/27', 'YYYY/MM/DD')

と書くべきでしょうね。


このQ&Aを見た人がよく見るQ&A

人気Q&Aランキング