質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Oracle Database

Oracle Databaseは、米オラクルが開発・販売を行うリレーショナルデータベース管理システムです。

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

Q&A

解決済

2回答

4671閲覧

連番を割り振るSQLを実行したいが、一意制約に引っかかる

sogarin

総合スコア1

Oracle Database

Oracle Databaseは、米オラクルが開発・販売を行うリレーショナルデータベース管理システムです。

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

0グッド

1クリップ

投稿2020/06/15 05:33

前提・実現したいこと

テーブルの構造は次のようになっております。

ID/KOJINNO/CD/RENBAN/INSERT_DATE
1/00001/0001/1/2020-06-15
2/00002/0121/1/2020-06-15
3/00002/0143/1/2020-06-18
4/00002/0777/1/2020-06-17
5/00003/0777/1/2020-06-18

主キー : ID
ユニークキー : KOJINNO,CD,RENBAN

上記テーブルの"CD"カラムのコードをこの度変更することとなりました。
変更は次のようになっております。

旧CD/新CD
0001/1111
0121/2222
0143/9999
0777/9999

コードの変換は
UPDATE HM_KIO SET KIOCD = '1111' where KIOCD = '0001';
UPDATE HM_KIO SET KIOCD = '2222' where KIOCD = '0121';
のように順に実施し、連番は、KOJINNO,CDに重複があった場合、重複レコードのMAX(RENBAN)+1をセットするという形としました。
上記のコードの変更に伴い、コード変換を行った後のテーブルが次になります。

ID/KOJINNO/CD/RENBAN/INSERT_DATE
1/00001/1111/1/2020-06-15
2/00002/2222/1/2020-06-15
3/00002/9999/1/2020-06-18
4/00002/9999/2/2020-06-17
5/00003/9999/1/2020-06-18

ここで、'KOJINNO'と'CD'が重複するデータが発生し、連番を適切に割り振る必要が生まれました。
INSERT_DATEを基準に日付順に連番を割り振るという処理を実施したいのですが、うまくいきません。

下記のSQLを実行したところ、日付で連番を取得することができました。
select kojinno, cd, insert_date, row_number() over(PARTITION BY kojinno, cd order by INSERT_DATE) from TABLE_TEST order by kojinno

しかし、更新を行うとなると、エラーが発生します。
update TABLE_TEST a SET a.renban = (select row_number() over(PARTITION BY kojinno, cd order by INSERT_DATE) from TABLE_TEST b where a.kojinno = b.kojinno and a.cd = b.cd and a.renban = b.renban)

解決のアプローチや、そもそもupdate処理の認識が間違っている気もします。
よろしければ、アドバイスや解決法を教えていただければ幸いです。

処理

発生している問題・エラーメッセージ

ORA-00001: 一意制約(XXXXXXXXXXXX)に反しています

該当のソースコード

SQL

1update TABLE_TEST a SET a.renban = (select row_number() over(PARTITION BY kojinno, cd order by INSERT_DATE) from TABLE_TEST b where a.kojinno = b.kojinno and a.cd = b.cd and a.renban = b.renban)

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

そもそも、row_number()はselectの結果分しか取得しませんので、連番全体で取得しようとしてもサブクエリーが複数行を返すのでエラーです。
※仮にそれを相関で1行にしようとしても(無意味ですが)、これから設定しようとする連番で相関するのは矛盾しています。

一度別テーブルに連番全体を出力し、その結果で更新を掛けるようにして下さい。
尚、その為には連番を含めないで一意になっている必要があります。
※更新の例から言うと、(kojinno, cd , INSERT_DATE)が候補でしょう。

一意になっていない箇所がある場合は、個別で更新して仕上げするしかないでしょうね。

追記

データ補正に関しては、一度結果をじっくりと見た方が良いと考えて別テーブルへの出力をお薦めしました。
重複が無いかどうかの検証なども考えると、データが確定していた方が、問い合わせが高速なので、総じて作業工数を短縮できます。

元々の質問に関して、キーの状況次第ではupdate文で可能です。
津島博士のパフォーマンス講座 第30回 UPDATEについて
あくまで可能という事で、MERGEの方が自由度は高いですけど。

投稿2020/06/15 05:54

編集2020/06/15 08:01
sazi

総合スコア25184

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

sogarin

2020/06/15 06:23

回答ありがとうございます。 次のように認識しました。 ①仮テーブル作成。カラムはID/KOJINNO/CD/INSERT_DATE ②更新対象テーブルから採番した結果(上記項目)を仮テーブルにINSERT ③仮テーブルの情報(採番)をもとに更新対象テーブルを更新。(このとき、仮テーブルが一意になっていることが大前提ですが、INSERT_DATE次第では危険な感じですね・・・。) 認識違いがあるかもしれませんが、まずはこのようにやってみようと思います。
sazi

2020/06/15 06:29

create table xxx as selectでテーブル作成+insertが同時にできます。
sogarin

2020/06/15 07:13

ありがとうございます。無事に採番し、テーブルの更新を行うことができました。
sogarin

2020/06/15 08:19

追記までいただき、本当にありがとうございます。 別テーブルに出力することで、INSERT_DATEの重複の確認を簡潔にまとめ、行うことができました。 参考URLもよく読み、さらに知見を深めたいと思います。
guest

0

ベストアンサー

KOJINNOとCDを更新した時点では一意制約違反にならないのでしょうか、
という点が気になりますが・・・。
KOJINNO、CD、INSERT_DATEで一意である前提です。

SQL

1MERGE INTO TABLE_TEST 2USING 3( 4 --TABLE_TESTからKOJINNO,CD,INSERT_DATEと、KOJINNO,CD毎のINSERT_DATE順の連番取得 5 SELECT 6 KOJINNO 7 , CD 8 , INSERT_DATE 9 , ROW_NUMBER() OVER(PARTITION BY KOJINNO, CD order by INSERT_DATE) NEW_RENBAN 10 FROM 11 TABLE_TEST 12) SUB 13ON 14( 15--KOJINNO,CD,INSERT_DATEでマッチング 16 TABLE_TEST.KOJINNO = SUB.KOJINNO 17AND TABLE_TEST.CD = SUB.CD 18AND TABLE_TEST.INSERT_DATE = SUB.INSERT_DATE 19) 20--マッチする行を更新 21WHEN MATCHED THEN 22 UPDATE SET 23 RENBAN = NEW_RENBAN;

投稿2020/06/15 06:35

toyotaku

総合スコア103

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

sogarin

2020/06/15 07:14

ありがとうございます。無事にテーブルの更新をすることができました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問