首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >插入GTT时的ORA-14551

插入GTT时的ORA-14551
EN

Stack Overflow用户
提问于 2012-09-17 23:44:24
回答 3查看 311关注 0票数 1

我有以下代码:

代码语言:javascript
运行
复制
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;

此例程的目的是掩码数据库中的名称,作为从生产环境创建开发数据库的准备工作的一部分。

我们希望屏蔽名称,但希望它们是可重复的,以便我们的结果类似于:(输入在左侧;输出在右侧)

代码语言:javascript
运行
复制
JOHN JONES  -> STEEL POTATO
SAM JONES   -> LARGE POTATO
MARY JONES  -> WHITE POTATO
SUE SMITH   -> LARGE CARROT
FRED JONES  -> RED POTATO
JOHN SMITH  -> GREEN CARROT

您可能会得到这样的想法: family name被更改为一个随机值,但当再次遇到它时,它会重复。给定的名字只是随机的。在这里,需要关注的是姓氏。

数组和其他非永久性解决方案对我们来说不能很好地工作,因为这实际上将作为一系列大型的UPDATE语句在同一会话中执行。GTT似乎非常适合这种类型的东西。

最终,我们将执行类似于以下内容的更新:

代码语言:javascript
运行
复制
UPDATE MY_TABLE
SET ORIG_NAME = repeatable_rand_text('last', ORIG_NAME)

但是为了“证明这个例程的结果,我们执行以下SQL:

代码语言:javascript
运行
复制
SELECT ORIG_NAME, repeatable_rand_text('last',ORIG_NAME)
FROM MY_TABLE

现在,很明显,该函数中的INSERT将作为SELECT的结果执行,这是一个禁忌。(如果不能做到这一点,我们就不愿意尝试自然地进行更新。据我们所知,它可能会失败,并显示类似的消息。)问题是,有没有一种合理的方法绕过这种情况?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2012-09-26 01:55:45

我终于使用了一个自主块。这很少是一个好主意,但在这种情况下,我认为这只是一张门票。下面是它的外观:

代码语言:javascript
运行
复制
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;
票数 1
EN

Stack Overflow用户

发布于 2012-09-18 00:21:25

不是特别漂亮,但您可以使用匿名块:

代码语言:javascript
运行
复制
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的每个值仍然是不同的。

票数 0
EN

Stack Overflow用户

发布于 2012-09-18 01:29:09

您可以尝试使用md5散列进行掩蔽。这样,表中就包含了不能转换为原始(实际)名称的散列值。我还假设您的查询通常会通过emp_id或类似的键连接,而不是实际的名称。

因此,为所有名称更新一次dev表:

代码语言:javascript
运行
复制
update my_table
set lastname = rawtohex(dbms_crypto.hash(utl_i18n.string_to_raw(lastname,'AL32UTF8'),2));

commit;

请注意,这是区分大小写的lastname,但如果您愿意,您可以使用大小写(Lastname)。希望这能有所帮助。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/12462735

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档