- - PR -
同期処理時を行うPLSQLでエラーが出てしまう
1
投稿者 | 投稿内容 | ||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
投稿日時: 2009-03-25 18:23
Oracle9iで作成したデータベースの同期処理を行うPLSQLの作成を行っているのですが、今回PLSQLを触るのは初めてでSQLも苦手なものでアドバイスでも頂ければと思い書き込みました。
教えて頂きたい内容は、TEST1のテーブルからIDとKBNにひもづく更新日時が最新のデータを取得する方法です。 何度か書き換えてやってみたのですが「フェッチされています。」と表示されてしまいうまく行きませんでした。 同期の内容を下記に記述いたしました。 説明不足ではあると思いますがよろしくお願いいたします。 同期の内容はTEST1とTEST2データを比較して、下記の動作を行います。 ・IDとKBN同一のデータが無ければINSERT ・IDとKBN同一のデータが有ればDATEを見て同期元の更新日時が新しければUPDATE 以下は作成したPLSQLとトリガーより自動生成された同期管理テーブルのデータです。 TABLENAME:TEST1 ID KBN DATE _______________________ 000000000001 A 09-03-23 000000000001 A 09-03-25 000000000002 A 09-03-23 000000000003 A 09-03-23 000000000003 A 09-03-25 000000000004 A 09-03-25 000000000006 B 09-03-25 TABLENAME:TEST2 ID KBN DATE _______________________ 000000000001 A 09-03-23 000000000001 A 09-03-25 000000000002 A 09-03-23 000000000003 A 09-03-23 000000000003 A 09-03-25 000000000004 A 09-03-25 000000000004 B 09-03-25 __________________ DECLARE ct VARCHAR2(256); dt VARCHAR2(256); yt VARCHAR2(256); /* カーソル */ CURSOR SYNCHRO IS SELECT DISTINCT ID, KBN FROM TEST1 WHERE UP_DT IN (SELECT MAX(UP_DT) FROM TEST1); TEMP SYNCHRO%ROWTYPE; BEGIN OPEN SYNCHRO; LOOP FETCH SYNCHRO INTO TEMP; EXIT WHEN SYNCHRO%NOTFOUND; SELECT DISTINCT ID,KBN,UP_DT INTO CT,YT,DT FROM TEST2@TEST WHERE UP_DT IN (SELECT MAX(UP_DT) FROM TEST2); IF TEMP.ID = '' THEN ...... ELSE ...... END IF; END LOOP; CLOSE SYNCHRO; EXCEPTION .......... END; / | ||||||||||||||||
|
投稿日時: 2009-03-26 00:22
始まりさん、こんにちは。
ループするまでもなく、UPDATE1回とINSERT1回を実行するのはどうでしょう? | ||||||||||||||||
|
投稿日時: 2009-03-30 11:19
よっしー様回答ありがとうございます。
体調を崩しており返事が送れたことをお詫びいたします。 UPDATE、INSERT1回で出来れば楽なのですが、仕様だと INSERT、DELETEのみで処理を行う。UPDATEは使用不可、 同期処理のデータ1件毎にコミットを行いエラーが発生した場合ロールバックを行うとなっています。 後一番大事な事を書き忘れていましたがTEST1とTEST2のデータは比較するだけであって 実際に同期を行うテーブルは別になります。 TEST1、TEST2のテーブルにプライマリキーは設定されていませんが、同期を行うテーブルにはID,KBNがプライマリキーとして設定されています。 DBとテーブルは以下の用になっています。 ------------------------------- 同期1 TEST1 ----------上下別サーバー------- 同期2 TEST2 ------------------------------- 同期1テーブルにデータが挿入されると、挿入されたデータのID,KBN,DATE(SYSDATE)がTEST1に挿入される、同データを更新した回数だけ同ID,同KBN,DATEが挿入される (同期2も同様) 同期の流れは以下のように1件ずつ判定を行う為、全件の処理を一括で行う事は出来ないです。 TEST1のデータ 「例) 000000001 A 2009/03/31 000000001 A 2009/03/28 000000001 A 2009/03/12」 この用にキー項目が同一のデータが複数あった場合、最新の日時の物を取得する。 取得したキー項目と同一のデータをTEST2から取得して同期判定を行う。 TEST1のDATEがTEST2より新しければTEST1のキーと同一のデータを同期2からDELETEして、TEST1のキーと同一のデータを同期1から取得して、同期2にINSERTする。 その後、更新を行ったID,KBNにひもづく全てのデータをTEST1,TEST2からDELEEする。 このとき同期処理が正常に終わっていたらコミット、エラーが発生したらロールバックを行う。 投稿してからの進捗はTEST1、TEST2の比較を行う事が出来ましたが、 「TEST1のデータがTEST2に無かった場合」の処理がうまく行きません。 判定はPLSQLで定義してある変数で、明示カーソルを使用して取得を行っています。 (ID1:TEST1 ID2 =TEST2) このときID1のデータは1つに絞り込めているのですが、ID2のデータが複数あり絞り込めていません。 その為「ID1 != ID2」の条件のとき 「ORA-01422: 完全フェッチが要求よりも多くの行を戻しました」とエラーが表示されてしまいます。 原因はID2が一つに絞り込めていないのが原因なのですが、力量不足故条件の絞込み方法を教えて頂きたいです PLSQLは投稿したときに記述した内容とほぼ変わりないので、どこが不適切なのか指摘をお願い致します。 文面が不適切で分かりにくい所が多いと思われますが、ご教授の方宜しくお願い致します。 [ メッセージ編集済み 編集者: 始まり 編集日時 2009-03-30 11:19 ] | ||||||||||||||||
|
投稿日時: 2009-03-30 12:46
始まりさん、こんにちは。
下記と矛盾しませんか?
別ということはTEST1でもTEST2でもないということでしょうか? | ||||||||||||||||
|
投稿日時: 2009-03-30 14:27
ちょっと2点程気になりましたので。
@提示されている条件とSQLについて 始まり様の書き込み(2009-03-25 18:23)より
上記の条件に対してのSQLですが、[b]TEST1の最新の日付を持つデータ[/b/を取得する内容 となっているので、条件と一致しません。
ID・KBN毎の最新日付を取得する場合ですと、次のようなSQLになります。
APLSQLでの『SELECT INTO』について 始まり様の書き込み(2009-03-25 18:23)より
次に上記のSQLですが、PLSQLでは『複数件のレコードを返す』SQLは、カーソルを使用 しないとエラーとなります。 ※『SELECT INTO』句は1行の結果を処理する為の命令で、複数件のレコードが返された 時点でエラーが発生します。 『カーソル』は複数件のレコードでも一件のレコードでも処理されますので、大抵の 『SELECT』文は『カーソル』を使用する事でエラーは減らせるかと思います。 |
1