1

私は次のコードを持っています:

CREATE OR REPLACE FUNCTION repeatable_rand_text(ftype    IN VARCHAR2
                                              , in_val   IN VARCHAR2)
    RETURN VARCHAR2 IS
    workval         VARCHAR2(64);
    insert_needed   BOOLEAN := FALSE;
BEGIN
    BEGIN
        SELECT new_name
        INTO   workval
        FROM   ps_dt_mixnames_preserve
        WHERE  name_type = ftype AND old_name = in_val;

    EXCEPTION
        WHEN NO_DATA_FOUND THEN
            workval := rand_text(ftype);
            insert_needed := TRUE;
    END;

    IF insert_needed THEN
        INSERT INTO ps_dt_mixnames_preserve(name_type, old_name, new_name)
        VALUES      (ftype, in_val, workval);
    END IF;

    RETURN workval;
END repeatable_rand_text;

このルーチンの目的は、本番環境から開発データベースを作成する準備の一環として、データベース内の名前をマスクすることです。

名前をマスクしたいのですが、結果が次のようになるように、名前を繰り返し可能にする必要があります:(左側に入力;右側に出力)

JOHN JONES  -> STEEL POTATO
SAM JONES   -> LARGE POTATO
MARY JONES  -> WHITE POTATO
SUE SMITH   -> LARGE CARROT
FRED JONES  -> RED POTATO
JOHN SMITH  -> GREEN CARROT

おそらくあなたは考えを理解するでしょう:家族の名前はランダムな値に変更されますが、それが再び遭遇すると繰り返されます。名は単にランダムです。ここで気になるのは家系の名前です。

配列やその他の非永続的なソリューションは、実際にはすべて同じセッション内で実行される一連の大規模なUPDATEステートメントとして実行されるため、うまく機能しません。GTTはこの種のものにぴったりのようでした。

最終的には、次のような更新を実行する必要があります。

UPDATE MY_TABLE
SET ORIG_NAME = repeatable_rand_text('last', ORIG_NAME)

ただし、「このルーチンの結果を証明するために、次のSQLを実行します。

SELECT ORIG_NAME, repeatable_rand_text('last',ORIG_NAME)
FROM MY_TABLE

さて、明らかにその関数のINSERTはSELECTの結果として実行され、それはノーノーです。(そして、それができなければ、自然に続くUPDATEを試すのは嫌です。私たちが知っている限り、同様のメッセージで失敗する可能性があります。)問題は、このシナリオを回避する合理的な方法があるかどうかです。

4

3 に答える 3

1

ついに自律ブロックを使用しました。これらが良いアイデアになることはめったにありませんが、この場合は単なるチケットだと思います。外観は次のとおりです。

function repeatable_rand_text(ftype IN VARCHAR2, in_val IN VARCHAR2)
    -- The idea is to assign random values to an entity (such as family name),
    -- and to repeat that value each time that entity is seen again.  In this
    -- manner, we can assign random values without losing associations such as
    -- (again) family NAMES.
    --     JONES  -> POTATO
    --     SMITH  -> CARROT
    --     DOE    -> ONION
    --     JONES  -> POTATO
    --
    -- Parameters:
    --    field-type  ('ADJ'  'NOUN'   'BOTH')
    --    field-value
    --
    RETURN VARCHAR2
    DETERMINISTIC IS
    PRAGMA AUTONOMOUS_TRANSACTION;
    workval         VARCHAR2(64);
    insert_needed   BOOLEAN := FALSE;
BEGIN
    BEGIN
        SELECT new_name
        INTO   workval
        FROM   ps_dt_mixnames_preserve
        WHERE  name_type = UPPER(ftype) AND old_name = UPPER(in_val);
    EXCEPTION
        WHEN NO_DATA_FOUND THEN
            workval := rand_text(ftype);
            insert_needed := TRUE;
    END;

    IF insert_needed THEN
        INSERT
        INTO   ps_dt_mixnames_preserve(name_type, old_name, new_name)
        VALUES (UPPER(ftype), UPPER(in_val), UPPER(workval));

        COMMIT;
    END IF;

    RETURN workval;
END repeatable_rand_text;
于 2012-09-25T17:55:44.937 に答える
0

マスキングにはmd5ハッシュを試すことができます。このようにして、テーブルには元の(実際の)名前に変換できないハッシュ値が含まれます。また、クエリは通常、実際の名前ではなく、emp_idまたは同様のキーを介して結合されると想定しています。

したがって、すべての名前についてdevテーブルを1回更新します。

update my_table
set lastname = rawtohex(dbms_crypto.hash(utl_i18n.string_to_raw(lastname,'AL32UTF8'),2));

commit;

これは姓の大文字と小文字を区別しますが、必要に応じてupper(lastname)を実行できることに注意してください。お役に立てば幸いです。

于 2012-09-17T17:29:09.467 に答える
0

特にきれいではありませんが、匿名ブロックを使用できます。

set serveroutput on
declare
    cursor c is
        SELECT ORIG_NAME
        FROM MY_TABLE;
begin
    for r in c loop
        dbms_output.put_line(r.orig_name || ' -> ' ||
            repeatable_rand_text('last', r.orig_name));
    end loop;
end;
/

データ量によっては、これは実用的でない場合があります。そして、値を埋めて、それらを整列させることができると思います。

rand_text(in_val)あなたはではなく電話をかけるべきではありませんrand_text(ftype)か?これは常にランダム化されたバージョンのを取得し'last'ますが、公平を期すために、の値ごとに異なりますin_val

于 2012-09-17T16:21:24.667 に答える