Skip to Main Content

Japanese

Announcement

For appeals, questions and feedback about Oracle Forums, please email oracle-forums-moderators_us@oracle.com. Technical questions should be asked in the appropriate category. Thank you!

Interested in getting your voice heard by members of the Developer Marketing team at Oracle? Check out this post for AppDev or this post for AI focus group information.

FROMでの副問合せに関数をかませた結果列を複数列で利用すると、利用した列数分関数が呼ばれる

988825Aug 4 2017 — edited Aug 29 2017

大量のテストデータを作りにあたり、少々困ったことがありまして、質問させてください。

既存の大量データを持つテーブルAと同じ数のレコードを、全く別のテーブルBに挿入しよう

としています。テーブルBにレコードを挿入するにあたり、一部の列にはテーブルAの列の値

をそのまま投入します。さらに、テーブルBには、レコード毎にランダムで同じ値を入れたい

列が複数存在します。

上記のようなデータを作成するにあたり、以下のようなパッケージ、およびINSERT文を作成

して動作確認したのですが、「複数列に対し、行毎にランダムで値の異なる値を設定」が

うまく機能せず、行毎だけでなく列毎にランダムとなってしまいました。以下、単純化した

再現可能なサンプルソースです。

-- パッケージ宣言

CREATE OR REPLACE PACKAGE TEST_PAC AS

    -- ランダムな文字列10バイトを返却する

    FUNCTION GET_RANDOM RETURN VARCHAR2;

END TEST_PAC;

/

-- パッケージ本体

CREATE OR REPLACE PACKAGE BODY TEST_PAC AS

    -- ランダムな文字列10バイトを返却する

    FUNCTION GET_RANDOM RETURN VARCHAR2 AS

    BEGIN

        DBMS_OUTPUT.PUT_LINE('GET_RANDOM called!');

        RETURN DBMS_RANDOM.STRING('x', 10);

    END GET_RANDOM;

END TEST_PAC;

/

-- テーブルA

CREATE TABLE A (

    COL1 VARCHAR2(10),

    COL2 VARCHAR2(10)

);

INSERT INTO A (COL1, COL2) VALUES ('oooo', 'pppp');

INSERT INTO A (COL1, COL2) VALUES ('qqqq', 'rrrr');

-- テーブルB

CREATE TABLE B (

    COLX VARCHAR2(10),

    COLY VARCHAR2(10),

    COLZ VARCHAR2(10)

);

SET SERVEROUTPUT ON;

-- テーブルAからテーブルBのレコードを挿入

INSERT INTO B (

    COLX,

    COLY,

    COLZ

) SELECT

    A_REC.COL1,

    A_REC.RANDOM_STR,

    A_REC.RANDOM_STR

FROM (

    SELECT

        COL1,

        TEST_PAC.GET_RANDOM() AS RANDOM_STR

    FROM A

) A_REC;

-- 上記SQL実行により、以下が出力される(2行×2列分で4回実行されている)

GET_RANDOM called!

GET_RANDOM called!

GET_RANDOM called!

GET_RANDOM called!

-- レコード内容確認

SELECT * FROM B;

COLX       COLY       COLZ

---------- ---------- ----------

oooo       I90VJJ9P5O Z7Y9CYTNN7

qqqq       SAILHIHFS8 MURUB7O177

上記の通り、2つのレコードのCOLY, COLZの値が異なる、という結果となっています。

意図としては、テーブルAのレコード数だけTEST_PAC.GET_RANDOM()が呼ばれ、返却値を

レコード毎に使い回して欲しいのですが、そうなっていません。

これに対し、以下のように DBMS_RANDOM を直接利用すると、意図した結果となっています。

-- テーブルBの内容を削除

DELETE FROM B;

-- DBMS_RANDOM パッケージを直接用いて挿入

INSERT INTO B (

    COLX,

    COLY,

    COLZ

) SELECT

    A_REC.COL1,

    A_REC.RANDOM_STR,

    A_REC.RANDOM_STR

FROM (

    SELECT

        COL1,

        DBMS_RANDOM.STRING('x', 10) AS RANDOM_STR

    FROM A

) A_REC;

-- レコード内容確認

COLX       COLY       COLZ

---------- ---------- ----------

oooo       N4RH2CVW4B N4RH2CVW4B

qqqq       P3XSGURCZ0 P3XSGURCZ0

実際のパッケージファンクションは、上記の例よりずっと複雑で、上記のように

インサート文に直接記述することができません。また、内部に DBMS_RANDOMを使用

しているため、RESULT_CACHEを指定することもできません。

普通こんなこと、やらないだろう、と思われるかもしれませんが、何かいい手は

ありますでしょうか?

よろしくお願いします。

This post has been answered by tlokweng on Aug 15 2017
Jump to Answer

Comments

Locked Post
New comments cannot be posted to this locked post.

Post Details

Locked on Sep 26 2017
Added on Aug 4 2017
2 comments
2,117 views