SQL初心者がROWNUMを使用したUPDATE文で一意制約違反が発生する問題

このQ&Aのポイント
  • SQL初心者が、テーブルの一意制約違反が発生する問題に直面しています。
  • 現在、ROWNUMを使用してNUMBERを更新しようとしているが、一意制約違反が発生してしまう。
  • この問題を解決するためには、UPDATE文の条件を見直す必要がある。
回答を見る
  • ベストアンサー

ROWNUMでUPDATEをしたいのですが・・・。

SQL初心者です。 以下のようなテーブルがあり、 ESTAB/PATTERN/NUMBER/CD 1/00/ 1/01 1/00/ 3/02 1/00/ 4/04 1/00/ 5/05 7/00/ 1/01 7/00/ 2/03 7/00/ 3/04 7/00/ 4/05 (主キー=ESTAB、PATTERN、NUMBER) SELECT ROWNUM,ESTAB,PATTERN,NUMBER,CD FROM (SELECT ESTAB,PATTERN,NUMBER,CD FROM M_PATTERN WHERE PATTERN='00' AND ESTAB='1' ORDER BY NUMBER) WHERE PATTERN='00' AND ESTAB='1' で検索したところの、ROWNUMでNUMBERを更新したいのですが、 UPDATE M_PATTERN A SET A.NUMBER= (SELECT ROWNUM FROM (SELECT ESTAB,PATTERN,NUMBER FROM M_PATTERN WHERE PATURN='00' AND ESTAB='1' ORDER BY NUMBER) B WHERE A.NUMBER=B.NUMBER AND A.PATTERN=B.PATTERN AND A.ESTAB=B.ESTAB AND B.PATTERN='00' AND B.ESTAB='1') WHERE A.PATTERN='00' AND A.ESTAB='1' としてみたところ、一意制約違反が発生してしまいます。 それとも、このようなUPDATEは無理なんでしょうか?

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

質問者が選んだベストアンサー

  • ベストアンサー
回答No.1

ROWNUMを使った更新は不可能ではありません。 更新で使用しているサブクエリが、更新すべき値を1コ見つけてくるSQLであれば 正しく処理できます。 NUMBERカラムの再採番が目的だと思うので、 update M_PATTERN X set X.NUMBER= ( select count(*) + 1 from M_PATTERN Y where X.ESTAB=Y.ESTAB and X.PATTERN=Y.PATTERN and Y.NUMBER<X.NUMBER ) where X.ESTAB='1' and X.PATTERN='00'; な感じで、ROWNUMを使わない解決が良いと思います。

tak_cha77s
質問者

お礼

回答ありがとうございます。 ご推察の通り、再採番がしたかったんです。 確かに、それを目的とするならこちらの方がSQLがすっきりしていて、わかりやすいですね。 実行させたところ、意図した更新が出来ました。 ありがとうございました。

関連するQ&A

  • ROW_NUMBER()を使用したデータ取得

    ROW_NUMBER()を使用してORDERした結果の5行目から10行目を 取得したい場合、どこのサイトを参照しても下記(1)のように NOで並び替えたデータをインラインビューとして WHERE RNUM BETWEEN 5 AND 10 と条件を絞っていますが、(2)のように直接条件を指定した場合と どのような違いがあるのか教えてください。 (1) SELECT NO, NAME FROM ( SELECT NO, NAME, ROW_NUMBER() OVER (ORDER BY NO) RNUM FROM ROWNUM_TEST ) WHERE RNUM BETWEEN 5 AND 10 (2) SELECT NO, NAME,ROW_NUMBER() OVER (ORDER BY NO) RNUM FROM ROWNUM_TEST WHERE RNUM BETWEEN 5 AND 10

  • oracleでwith句の結果を使ってupdate

    oracleでwith句の結果を使って外部結合?でupdateしたいのですが 上手くいきません。 oracleでは無理なのでしょうか。 よろしくお願いいたします、。 /*---------- with v1 as ( select row_number() over(PARTITION BY ・・・ ORDER BY ・・・) as rnum ,no ,col1 ,・・・ from ・・・ ) update ( select A.col1 A_COL, v1.col2 B_COL from table1 A inner join table2 B on A.cd1=B.cd1 inner join v1 on A.no=v1.no where v1.rnum=1 and ・・・ ) set A_COL=B_COL ; ----------*/ と書いたのですが、 実際に実行してみると、 カッコ「(」、「)」がないとか、 selectが必要とか, A_COLやB_COLが無効ですとか、 となります。 どこが悪いのでしょうか。 oracleではupdateでwithは使えないのでしょうか。 よろしくお願いします。

  • sqlのwhereで指定した条件の前後を取得したい

    テーブル=T) KEY DATA 001 あ 002 い 003 う 004 え 005 お SQL) SELECT DATA FROM T WHERE KEY = 003 ; 上記のSQLでは、「う」のデータしか取得できませんが、 「003」の前後1件、合計3件の「い」「う」「え」を取得する方法を教えて下さい。 ちなみに、 SELECT DATA FROM T WHERE KEY >= 003 AND ROWNUM <= 2 と SELECT * FROM ( SELECT DATA FROM T WHERE KEY < 003 ORDER BY KEY DESC ) WHERE ROWNUM < 1 のUNIONでは上手く行きませんでした。 よろしくお願いします。

  • OracleSqlで『RORNUM』の使い方について

    VB6でコーディングをしています DBはOracle7.3です SELECT A.One, A.Two, SUM(A.Three) Three,  FROM A  WHERE ( A.One = '001' AND A.Two = '3')  GROUP BY A.One, A.Two ORDER BY Three DESC  上記のようにAテーブルの項目One,Two,Threeを抽出するSQLで 重複項目One,Twoでグループ化したThreeの合計値の内、上位25件を 取得したいのですが... SELECT *  FROM ( SELECT A.One, A.Two, SUM(A.Three) Three,  FROM A  WHERE ( A.One = '001' AND A.Two = '3')  GROUP BY A.One, A.Two ORDER BY Three DESC ) WHERE ROWNUM <= 25 上記のように記述するとORDER BY句でエラーになります ORDER BY句をWHERE ROWNUMの下に記述するとSQLはとおりますが 条件が変わってしまいます。 抽出条件でマージ、降順ソートしたものに対して上位n件の取得をするには どうすれば良いのでしょうか?

  • UPDATE文の書き方を教えて下さい。

    いつもお世話になっています。 UPDATEの書き方について教えて下さい。 以下のようなUPDATE文を作成しました。 処理的には必要な結果を返してくれていますが、もう少しシンプルには ならないでしょうか? UPDATE文がまだ理解出来ていないのですが、”WHERE EXISTS(”以降に 書いているSELECT文は、SET文の値算出時にも同じSELECT文を書いて いるのですが、それを代用することは出来ないのでしょうか? (SELECTの結果をWHERE文の中で簡単に呼び出して使えないのでしょうか?) ※うまく内容が伝わってないかもしれませんが、どうぞよろしくお願いします。 <<<更新処理>>> UPDATE TBL01 SET( TBL01_MARNO, TBL01_UPDYMD )=( SELECT TBL02_MARNO, TO_NUMBER(TO_CHAR(SYSDATE,'YYYYMMDD')) FROM (SELECT TBL02_TENCD, TBL02_REN, TBL02_MARNO, TBL02_UPDKBN, RANK () OVER (PARTITION BY TBL02_TENCD, TBL02_REN ORDER BY TBL02_YMD DESC, TBL02_DAT DESC ) WRK_RANK FROM TBL02 WHERE TBL02_OKFLG = 1 ) WHERE TBL02_TENCD = TBL01_TENCD AND TBL02_REN = TBL01_REN AND WRK_RANK = 1 AND TBL02_UPDKBN = 2 ) WHERE EXISTS( SELECT 'TRUE' FROM (SELECT TBL02_TENCD, TBL02_REN, TBL02_MARNO, TBL02_UPDKBN, RANK () OVER (PARTITION BY TBL02_TENCD, TBL02_REN ORDER BY TBL02_YMD DESC, TBL02_DAT DESC ) WRK_RANK FROM TBL02 WHERE TBL02_OKFLG = 1 ) WHERE TBL02_TENCD = TBL01_TENCD AND TBL02_REN = TBL01_REN AND TBL02_UPDKBN = 2 AND WRK_RANK = 1 );

  • SQL得意な方

    仕事で困っています、 なにとぞお力添えを。 テーブル1から、TOP50 でaとbを表示させたいのです。 で、その際の条件として、 開始するレコードも指定したいのです。 下記SQLの[○]の部分に50が入っていたら、 51~100件を表示する、と、いうような。 SELECT TOP 50 a,b FROM テーブル1 WHERE c='1' AND a >= '' AND a NOT IN ( SELECT TOP 〇 a FROM テーブル1) ORDER BY a で、順調だったのですが、WHERE条件が なんだか怪しいらしく、 a >= ''の時だけはきちんと動くのですが、 ANDでc='1'をつけた所、普通に全件表示されてしまいます。 [ちゃんと51件目から100件目を表示するSQL] SELECT TOP 50 a,b FROM テーブル1 WHERE a >= '' AND a NOT IN ( SELECT TOP 〇 a FROM テーブル1) ORDER BY a [何故か全件表示になるSQL] SELECT TOP 50 a,b FROM テーブル1 WHERE c='1' AND a >= '' AND a NOT IN ( SELECT TOP 〇 a FROM テーブル1) ORDER BY a ※[何故かNOT IN (~)の部分がまったく働いていない] どうしてなのでしょう?。 解りにくい質問で大変申し訳ないのですが どなたかご教授いただけないでしょうか。

  • SQLでSELECTした一覧をUPDATEする方法を教えてください。

    AのテーブルをINNER JOINのWHERE文を用いて、selectした結果の項目にBテーブルの内容をUPDATEしたいのですが、 下記方法でうまくいきません。 解決方法を教えてください。 よろしくお願いいたします。 SELECT A.PointZan FROM A INNER JOIN B ON A.Code = B.Code WHERE (B.TrDate = '091012') AND (B.Comment = '失効中止') UPDATE A SET PointZan = (SELECT B.PointZan FROM B INNER JOIN A ON B.Code = A.Code WHERE (B.TrDate = '091012') AND (B.Comment = '失効中止'))

  • 日付の古い順番に削除したいのですが

    レコード登録時にテーブルの件数が規定数を越えているならば、指定件数分の既存レコードを削除したいのですが、方法が見つかりません。 目的のテーブルは以下のような構造になっております。 P-Key1:大枠のID(プライマリキー1) P-Key2:大枠内の序列を表す(プライマリキー2) THRED:登録元スレッド番号(プライマリキー3) FILE:ファイルパスを格納 TIMESTAMP:登録日付、DATE型 TERMID:端末ID(プライマリキー4) この内、削除時に指定するのはスレッド番号と端末IDだけです。 残りのプライマリキーが一つならば、IN句の副問い合わせでできそうな感じですが、2つある為、IN句では指定できませんでした。 以下は、試したSQL文です。ただし、全部失敗しております。 DELETE FROM (select * FROM テーブル WHERE THREAD = 1 AND TERMID = '端末ID' ORDER BY TIMESTAMP) WHERE ROWNUM < 3; DELETE FROM テーブル WHERE P-Key1 IN (SELECT P-Key1 FROM テーブル WHERE THREAD = 1 AND TERMID = '端末ID' AND ROWNUM < 3 ORDER BY TIMESTAMP) AND P-Key2 IN (SELECT P-Key2 FROM テーブル WHERE THREAD = 1 AND TERMID = '端末ID' AND ROWNUM < 3 ORDER BY TIMESTAMP); よろしくお願いします。

  • 複雑なUPDATE文2

    先に質問をさせていただき、1度は解決したものの再び行き詰ってしまいました。 UPDATEの際うまくいかず困っています。 お知恵を拝借いただけると助かります。 使用バージョンはPostgresV7.3.4です。 tableA a1|a2|b|c -+--+-+- 1 | 1 | 1| 1 (★) 1 | 1 | 0| 1 1 | 2 | 0| 1 2 | 2 | 1| 0 2 | 1 | 0| 1 3 | 2 | 1| 1 (★) 3 | 2 | 0| 1 3 | 1 | 0| 1 b=1 and c=1 で一致する行を★行とする。 ★行のa1列の値とa2列の値(上記の例だと(a1=1,a2=1)と(a1=3,a2=1))をもつ行に対して 下記の条件◆でUPDATEを行う。 [条件◆] b=0 and c=1 [UPDATEの内容] 条件◆に一致したc列を3に更新する [理想の結果] tableA a1|a2|b|c -+--+-+- 1 | 1 | 1| 1 1 | 1 | 0| 3 ←更新 1 | 2 | 0| 1 2 | 2 | 1| 0 2 | 1 | 0| 1 ←★にあてはまらないので更新されない 3 | 2 | 1| 1 3 | 2 | 0| 3 ←更新 3 | 1 | 0| 1 ←最下行 ========================================== UPDATE tableA set c = 3 WHERE 条件◆ and a1 in (select a1 from tableA where b=1 and c=1) and a2 in (select a1 from tableA where b=1 and c=1) このようなイメージなのですが、この場合、 最下行のc列も更新してしまいました。 (説明しずらいのですが、) a1とa2の条件は独立させるのでは無く、セットとして考えたいのですが、 方法が分りません。 ご協力お願いします。 ==========================================

  • SQL構文

    MASTER_TBLを、CDとKAKU_CDの2列で一意をなるようにしたいので、重複データを洗い出すためのSQLを組もうとしています。 FROM句のサブクエリ単体では、正常な結果が取得できるのですが、下のSQLを流すと、全データ件数×全データ件数が結果として返ってきます。 重複行のみを表示するにはどうすればいいのでしょうか?単純な構文ミスのような気がするのですが、、、 SELECT  M1.CD AS CD1,  M1.KAKU_CD AS KAKU_CD1,  M1.UPDATE_DATE AS UPDATE_DATE1 FROM  MASTER_TBL M1,  (   SELECT M2.CD || M2.KAKU_CD AS CODE2, COUNT(*)   FROM MASTER_TBL M2   GROUP BY M2.CD, M2.KAKU_CD   HAVING COUNT(*) > 1  ) SUB_T; WHERE M1.CD || M1.KAKU_CD IN ( CODE2 ) ORDER BY 1, 2, 3 ;