• 締切済み

SQL文でどこが悪いのか教えて下さい

初心者ですが教えて下さい。 表Aと表Bで表Aに含まれていないものを表Cに入れたいのですが、下記のやり方では表Aのものしか入れることができません。 どこが悪いのか教えて下さい。 ・コードは複雑なため、簡略化しています。UNIONは使わない方向で。 CREATE OR REPLACE PROCEDURE SAMPLE IS CURSOR SELLINE1 IS SELECT * FROM A ORDER BY KEY1,KEY2; CURSOR SELLINE2 IS SELECT * FROM B ORDER BY KEY1,KEY2; CNT1 NUMBER; CNT2 NUMBER; BEGIN SELECT COUNT(*) INTO CNT1 FROM C; IF CNT1 = 0 THEN FOR SELREC IN SELLINE1 LOOP INSERT INTO C VALUES (KEY1,KEY2,値);COMMIT; END LOOP; FOR SELREC IN SELLINE2 LOOP SELECT COUNT(*) INTO CNT2 FROM C WHERE (KEY1 = SELREC.KEY1) AND (KEY2 = SELREC.KEY2); IF CHK_CNT2 = 0 THEN INSERT INTO C VALUES (KEY1,KEY2,値);COMMIT; END IF; END LOOP; END IF; END; /

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

みんなの回答

  • 7colors
  • ベストアンサー率25% (29/114)
回答No.2

処理が途中ではいるのでPROCEDUREにしていると判断して回答します。 (そうでない場合はNo.1の方の回答で) 1.B表のCURSORをOPEN 2.B表上のA表との重複を比較したい項目でA表を検索 (CURSORを作りCOUNTをとるのが望ましいです 直書きでもいいですが・・・) 3.存在しない場合(COUNTが0の場合)INSERT 存在した場合は処理をしない この流れではないでしょうか? ちなみに、MINUSでSELECTを作りINSERTするのも手です。 (項目が同じでない場合手間が増えますが・・・)

zhen-yu
質問者

お礼

ご回答ありがとうございました。 下記の通り、格納データに問題があったようです・・・すみませんでした。 同じ処理をするにしてもいろいろなやり方があるので、持ってる知識でどこまでやれるか悪戦苦闘中です。

  • JavaZou
  • ベストアンサー率50% (1/2)
回答No.1

RDBの理論は数学の「集合」です。 ご所望の動作はとてもシンプルに記述できます。 insert into c select i from b where not exists(select * from a where a.i=b.i) UNIONは使わないとか条件が付いているところをみると 本当の初心者ではないですよね?(実は職業プログラマ?) 集合演算は教養として身につけるとよいですよ。

zhen-yu
質問者

お礼

ご回答ありがとうございました。 調べてみた結果、表に格納されているデータの方に問題があったみたいです。 他の言語、DBはやった事があるのですが、ORACLEはまったく初めてで・・・結果的に単純な事ですみませんでした。 集合演算の知識もなかったので、これから勉強したいと思います。

関連するQ&A

  • ORA-06502のエラー

    以下のPL/SQLを実行すると、ORA-06502:数値または値のエラーとでます。途中までは、INSERTできるのですが、IF文の180個目くらいでエラーになります。そのあたりをCur1の宣言時にWhereで指定するとうまくいきます。 DECLARE CURSOR Cur1 IS SELECT MOJI FROM A_TBL ; CNT NUMBER(10); KAKKO_FL NUMBER(1); BEGIN CNT := 0; KAKKO_FL :=0; FOR Cur_Rec1 IN Cur1 LOOP FOR S IN 1 .. LENGTH(Cur_Rec1.MOJI) LOOP IF(ASCII(SUBSTR(Cur_Rec1.MOJI,S,1)) = 33129) THEN /*33129は'('*/ EXECUTE IMMEDIATE ' INSERT INTO EDD.test1116 VALUES( ''' || Cur_Rec1.MOJI || ''' ) '; END IF; END LOOP; END LOOP; END; なにがなんだか、さっぱりわからないので、どうか、ご教授ください。

  • プロシージャの記述の仕方

    テーブルAとテーブルBがあります。 テーブルAとテーブルBのレイアウト(列名・サイズetc) は、まったく同じです。唯一、違う点は、テーブルAは フラグをもっている点です。 ここで、考えていただきたいのですが テーブルAのフラグが1のレコードは、テーブルBに フラグ以外のレイアウトをINSERTし、フラグが2のレコードは、一意のコードをキーにしてDELETEを行う処理を 行いたいのですが、下記のような感じでよいのでしょうか? CREATE OR REPLACE PROCEDURE A AS CURSOR B IS SELECT * FROM A; BIGIN FOR D IN B LOOP IF D.フラグ=1 THEN INSERT INTO B VALUES(…省略 ELSIF D.フラグ=2 THEN DELETE FROM B WHERE …省略 END IF; COMMIT; END LOOP; END; / こんな感じでよいのでしょうか? よろしくお願いします。

  • SQL xx件目からxx件目までを抽出したい

    SQLを習いはじめました。 ユーザーIDが100件あるテーブルの30件目~50件目の ユーザIDを抽出し、別テーブルに登録をしたいと思っています。 『このxx件目からxx件目まで』の抽出のしかたがわかりません。 どなたかわかる方がいましたら教えてください。 DECLARE CURSOR cursor_name IS SELECT USER_ID FROM TBL_USERID ; getid VARCHAR2(16); ryear NUMBER := '2008'; ryear2 NUMBER := '08'; rmonth NUMBER; rday NUMBER; usercnt NUMBER; rcnt NUMBER := '0'; --処理開始 BEGIN SELECT count(USER_ID) INTO usercnt FROM TBL_USERID ; OPEN cursor_name ; LOOP FETCH cursor_name INTO getid ; EXIT WHEN cursor_name%NOTFOUND; --月でループ(1~12月) For rmonth IN 1..12 LOOP --日でループ(1~22日) For rday IN 1..22 LOOP --スケジュール1件目 rcnt := (rcnt + 1); INSERT INTO TBL_SCH ( SCHEDULE_ID ,USER_ID ,UPDATE_DATETIME ) VALUES ( ryear || Trim(TO_CHAR(rmonth,'00')) || Trim(TO_CHAR(rday,'00')) || Trim(TO_CHAR(rcnt,'00000000')) ,'getid' ,SYSTIMESTAMP ); END LOOP; END LOOP; END LOOP ; CLOSE cursor_name ; END ;

  • sql merge文について

    該当KEY=12345が存在すれば、seqに1を加算、存在しない場合は、seqに1を設定する mergeを使用したsql文を作成したいのですが、 良いサンプルはありませんか? ↓こんな雰囲気でしょうか? MERGE INTO A表 ab USING (SELECT KEY FROM A表 where KEY = 12345 ) ac ON (ab.KEY = ac.KEY) WHEN MATCHED THEN UPDATE SET ac.SEQ = ac.SEQ +1 WHEN NOT MATCHED THEN INSERT (KEY, SEQ) VALUES ("12345",1) よろしくお願いします

  • PLSQLの識別子エラー

    下記PLSQLを実行した時に(sqlplus上で、@XXXX.SQLと実行) WCOUNT :=WCOUNT + 1; エラー PLS-00201: 識別子WCOUNTを宣言してください のエラーがでます 宣言をしているのですがわからず、お助けください また、他にもこのエラーを処置したあとに問題と なりそうな箇所があれば指摘お願いします -やろうとしてること (1)テーブルA を、男子を出席順に読み込んでその読み込んだ順番に 1から番号をふり、テーブルBへ新規追加する (2)テーブルAからテーブルBに新規追加していない女子を、出席順に読み込んで 1から番号をふり、テーブルBへ新規追加する (3)テーブルBのKEYは順番のみ (4)テーブルBのINSERT分は、今後機能追加する予定なのでNOT IN使用する -組んだPL/SQL(2つのINSETを1つのファイルに記述しています) DECLARE WCOUNT number; CURSOR カーソル IS SELECT 出席番号,名前,成績 FROM テーブルA  ORDER BY 出席番号; BEGIN FOR r IN カーソル LOOP INSERT INTO テーブルB (r.順番, r.名前,r.出席番号) VALUES (WCOUNT,r.名前); COMMIT; WCOUNT :=WCOUNT + 1; END LOO; / END; DECLARE CURSOR カーソル IS SELECT 出席番号,名前,成績 FROM テーブルA A WHERE A.出席番号 NOT IN (SELECT B.出席番号 FROM テーブルB B) ORDER BY 出席番号; BEGIN FOR r IN カーソル LOOP INSERT INTO テーブルB (順番, 名前) VALUES (WCOUNT,r.名前); COMMIT; WCOUNT :=WCOUNT + 1; END LOOP; / END;

  • ROWTYPEのINSERTが出来ません

    plsqlにてROWTYPEを使用したINSERTが出来ず困っています。 現在、以下のようなplsqlでROWTYPEのデータのINSERT処理をしようとしていますが、INSERTが出来ない状況となっています。 dbms_output.put_lineで確認するとINSERTしたいデータが存在していることは確認しています。 また、INSERT文をコメントアウトして実行すると、想定通りの回数のループ処理が 行われることも確認しています。 いまいち原因が分からず困っています。 DECLARE CURSOR zaiko_csr IS select * from zaiko_mst; zaiko_rec zaiko_mst%ROWTYPE; BEGIN OPEN zaiko_csr; LOOP FETCH zaiko_csr INTO zaiko_rec; EXIT WHEN zaiko_csr%NOTFOUND; insert into zaiko_bk(prd_cd, prd_nm, cnt) values(zaiko_rec.prd_cd, zaiko_rec.prd_nm, zaiko_rec.cnt); END LOOP; commit; close zaiko_csr; END;

  • PL/SQLでテーブル名に変数を使いたい

    下記のようにV_TABLE_NAMEに不定のテーブル名で使用したい ご存知の方は教えて頂けないでしょうか?V_TABLE_NAMEに取得したテーブルをセットし、データの件数を取得するPL/SQL CURSOR C_CUR IS SELECT COUNT (*) FROM V_TABLE_NAME; BEGIN for ・・・・・ loop ・・・  ・・・ V_TABLE_NAME := GET_TABLE;  OPEN C_CUR;  FETCH C_CUR into w_count; CLOSE C_CUR; end loop;

  • SQL GO TOするには?

    SELECTしたものを飛ばしてからINSERTしたいのですが、 どうしたら良いですか? CURSOR A is  SELECT~~~ BEGIN  FOR rec IN cur_z LOOP   項目追加(Arec);  END LOOP; END; PROCEDURE 項目追加(rec) IS ←ここでエラー BEGIN    INSERT~~~~ END 項目追加; としてあるのですが、 PLS-00103: 記号"PROCEDURE"が見つかりました。 PLS-00103: 記号")"が見つかりました。 のエラーが出ます。

  • 測定結果が決められた範囲内か判定するSQL文

    決められた範囲内に測定結果が入っているかを判定するSQL文(またはストアドプロシージャ)を PostgreSQL 14.0を使って作ろうとしていますが、正しい結果が得られません。 具体的には、ケーブル・テーブルとスペック・テーブルで一致するテスト項目同士(例えば、'Test_1'同士)だけを比較したいのですが、他のテスト項目も引っ掛けてしまいます。 あと、下記のwhere test_item = 'Test_1', 'Test_2', 'Test_3'の部分を select test_item from cable; から一つ一つ取り出してループで回して代入し、最終的には id | test_item | test ----+-----------+------ 1 | Test_1 | 1.5 2 | Test_1 | 1.8 2 | Test_2 | 2.5 という、まとまった出力を得たいのですが、その方法を教えていただけないでしょうか? 自作のテーブルとSQL文は以下になります: create table cable( id integer default 0 not null ,test_item varchar(30) not null ,test numeric(3, 1) ,primary key (id, test_item) ); insert into cable values(1, 'Test_1', 1.5); insert into cable values(1, 'Test_2', 4.5); insert into cable values(1, 'Test_3', 2.5); insert into cable values(2, 'Test_1', 1.8); insert into cable values(2, 'Test_2', 2.5); insert into cable values(3, 'Test_3', 2.5); create table spec( test_item varchar(30) not null , lower_spec numeric(3, 1) , upper_spec numeric(3, 1) , primary key(test_item) ); insert into spec values('Test_1', 1.0, 2.0); insert into spec values('Test_2', 2.0, 3.0); insert into spec values('Test_3', 3.0, 4.0); postgres=# select * from cable c WHERE c.test_item = test_item and test < (select upper_spec from spec where test_item = 'Test_1') and test > (select lower_spec from spec where test_item = 'Test_1'); id | test_item | test ----+-----------+------ 1 | Test_1 | 1.5 2 | Test_1 | 1.8 (2 行) postgres=# select * from cable c WHERE c.test_item = test_item and test < (select upper_spec from spec where test_item = 'Test_2') and test > (select lower_spec from spec where test_item = 'Test_2'); id | test_item | test ----+-----------+------ 1 | Test_3 | 2.5 ←'Test_3'なので引っ掛けたくない 2 | Test_2 | 2.5 3 | Test_3 | 2.5 ←'Test_3'なので引っ掛けたくない (3 行) postgres=# select * from cable c WHERE c.test_item = test_item and test < (select upper_spec from spec where test_item = 'Test_3') and test > (select lower_spec from spec where test_item = 'Test_3'); id | test_item | test ----+-----------+------ (0 行) 必要であれば補足します。 では、よろしくお願いします。

  • PL/SQLでの処理について

    キーの異なる2つのトランザクションテーブルA,Bに マスタCの値を引っ張ってきて各A,B埋める処理を、テーブル名を引数にPL/SQLのプロシージャにしたいのですが、良い方法はありますか? 以下のイメージです。 <TABLE A> KEY_A C_CD C_VALUE -----+----+------- 1 3 2 3 3 1 <TABLE B> KEY_B C_CD C_VALUE -----+----+------- 1 3 2 3 3 1 <TABLE C> C_CD C_VALUE ----+-------- 1 A 2 B 3 C SQL>EXECUTE foo('A'); <TABLE A> KEY_A C_CD C_VALUE -----+----+------- 1 3 C 2 3 C 3 1 A SQL>EXECUTE foo('B'); <TABLE B> KEY_B C_CD C_VALUE -----+----+------- 1 3 C 2 3 C 3 1 A <処理イメージ> CREATE OR REPLACE PROCEDURE FOO(TNAME VARCHA2) IS c_cd NUMBER; C1 INTEGER; SQL1 VARCHAR2(2000); I INTEGER; BEGIN SQL1 := 'SELECT c_cd FROM ' || tname; C1 := DBMS_SQL.OPEN_CURSOR; DBMS_SQL.PARSE(C1, SQL1, DBMS_SQL.V7); DBMS_SQL.DEFINE_COLUMN(C1, 1, c_cd); LOOP IF DBMS_SQL.FETCH_ROWS(C1) > 0 THEN DBMS_SQL.COLUMN_VALUE(C1, 1, c_cd); UPDATE tname set value = c_cd; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ↑ここの部分をうまくかけないでしょうか? ELSE EXIT; END IF; END LOOP; end /