如何从Oracle中的字符串序列列中获取值?

问题描述:

我有一个包含一对键值柱:如何从Oracle中的字符串序列列中获取值?

键1 = 111111 |键2 = 222222 | KEY3 = 333333 | KEY4 = 444444

值是在不同的表中的列的标识。 如果key2存在,如何获得值'222222',然后用它与另一个表连接?

你能为我提供rexeg吗?提前致谢。

+0

你是说你有一个名为KEY的列和名为VALUE的列? – BobC

+0

@BobC否,列被称为“选项”,它包含类似“key1 = 111111 | key2 = 222222 | key3 = 333333 | key4 = 444444”的字符串,其中key是另一个表中的列的ID ... –

如果这是在“适当的形式”(而不是一列中的一个值,你会在两列中有四行 - 一个表的键列和另一个值的列),那么它会很容易,对?而且 - 如果你的专栏与另一专栏,某种id配对,那么同一专栏应该在“正确的形式”表中?

我永远不知道人们最终不得不使用类似“你的”现有专栏的东西。但是如果你没有权力,写一个视图是最有意义的(可能是为了更好的性能而物化),并使用它来代替当前的表。例如:

create table t1 (id number, key_val varchar2(4000)); 
insert into t1 
    select 101, 'key1=111111|key2=222222|key3=333333|key4=444444' from dual union all 
    select 102, 'key1=800001|key5=800002|key6=900030|key9=339900' from dual; 
commit; 

create view t1_view (id, key, val) as (
    select id, regexp_substr(key_val, '(\||^)(.*?)=', 1, level, null, 2), 
      regexp_substr(key_val, '=(.*?)(\||$)', 1, level, null, 1) 
    from t1 
    connect by level <= length(key_val) - length(translate(key_val, 'z=', 'z')) 
     and prior id = id 
     and prior sys_guid() is not null 
); 

select * from t1_view; 

    ID KEY VAL 
---- ----- ------- 
101 key1 111111 
101 key2 222222 
101 key3 333333 
101 key4 444444 
102 key1 800001 
102 key5 800002 
102 key6 900030 
102 key9 339900 

8 rows selected. 

这里val仍然是一个字符串。如果它应该是一个数字,最好将最后的regexp_substr包装在to_number()之内。

现在编写所有的连接以使用此视图而不是t1

+1

如果这*真的*是设计,这太可怕了。这是完全错误地使用产品的经典案例 – BobC

+1

我并不在行业工作,但我被告知这种bs数据模型非常普遍,尤其是在老的,非常大的组织(医院,保险公司,银行......)也许从RDBMS发明之前。当然,没有理由在这么多年后不去修复它,但是必须与那些对这一切毫无头绪的业务经理打交道,并且对任何事情都说**不行。 – mathguy

+0

不幸的是,这在新的应用程序中也太常见了。有一种看法认为,“关键价值”商店对性能有好处,可扩展等,更不用说“时髦”了。 – BobC