- ベストアンサー
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 /
- みんなの回答 (3)
- 専門家の回答
質問者が選んだベストアンサー
こんにちわ。 > あとは、ROWIDを指定することを考えていますが、 > Oracleの構造上問題ないでしょうか。 問題ありません。 一応暗黙的な型変換を防止するために、 ROWID ⇔ VARCHAR2 の個所は ROWIDTOCHAR, CHARTOROWID ファンクションを 使用した方が良いと思います。 因みに、ROWIDTOCHAR ファンクションで変換した 文字列長は18文字です。 詳細は、ユーザ登録 (無料) が必要ですが、 OTN Japan にPDF 形式のマニュアルが公開されて いますので、Download されては如何でしょうか?
- 参考URL:
- http://otn.oracle.co.jp/
その他の回答 (2)
- osamuy
- ベストアンサー率42% (1231/2878)
単純に値をセットするだけなら、 execute immediate 'update ' || tname || ' T Set v = (select v from TABLE_C where cd = T.cd)'; ――と一発で更新できそうな気がします。 そういう話じゃない?
補足
質問時のテーブルでは、その通りなのですが、 KEY_A,KEY_Bが異なる複数列にて主キーになっていますので、質問が曖昧で済みませんでした。 ROWIDで対応する方法を検討していましたが、特に問題ないとの回答も得ました。 こちらで対応しようと考えております。 ありがとう御座いました。
- tsukasa-12r
- ベストアンサー率65% (358/549)
動的SQLでできると思います。 ↓こんな感じかと。 declare s varchar2(2000); ... begin ... s := 'UPDATE ' || tname || ' SET C_VALUE = :data1'; execute immediate s using c_cd; end;
補足
早速のご回答ありがとうございます。 頂きました回答で s := 'UPDATE ' || tname || ' SET C_VALUE = :data1'; という形では、WHERE句が指定されていないので 全レコード更新されてしまいますよね? 更新したいレコードは現在、FETCHしている行なので、ベストとしては WHERE CURRENT OF c1 が指定できると良いのですが、 動的SQLで上記を指定はできませんよね? UPDATE tname set value = c_cd WHERE CURRENT OF c1 ↑こんな動的SQLって使えますか? 回避策として主キーをWHERE句に指定することも考えましたが、テーブル毎に主キーが異なるのでこれもできません。 あとは、ROWIDを指定することを考えていますが、Oracleの構造上問題ないでしょうか。
お礼
了解です。 ROWIDを使う方向で検討いたします。 ありがとう御座います。