我有以下代码:
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;
此例程的目的是掩盖数据库中的名称,作为从Production创建开发数据库的准备工作的一部分。
我们希望屏蔽名称,但我们希望它们可重复,以便我们的结果类似于:(左侧输入;右侧输出)
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。对于我们所知道的,它可能会因类似的消息而失败。)问题是,这个场景是否有合理的方法?
答案 0 :(得分: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;
答案 1 :(得分: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
的每个值仍然会有所不同。
答案 2 :(得分:0)
您可以尝试使用md5哈希进行屏蔽。这样,表包含不可转换为原始(实际)名称的哈希值。我还假设您的查询通常会通过emp_id或类似的密钥加入,而不是实际名称。
因此,为所有名称更新您的开发表一次:
update my_table
set lastname = rawtohex(dbms_crypto.hash(utl_i18n.string_to_raw(lastname,'AL32UTF8'),2));
commit;
请注意,这在lastname上区分大小写,但如果您愿意,可以使用upper(lastname)。希望有所帮助。