我想将主键列表存储到同一个表中的其他记录中。然后我希望能够执行类似于以下内容的选择:
SELECT * FROM mytable WHERE myarraycol CONTAINS '123'
我已经看到Oracle有一个array data type。但是,看起来EXISTS函数只验证元素是否存在于指定的索引处。有没有办法在单个SQL查询中验证给定变量是否在数组数据类型列中?
作为使用数组数据类型的替代方法,我尝试将PK存储为逗号分隔的字符串,如“123,324,543,23432”。我的查询看起来像:
SELECT * FROM mytable WHERE mystringcol LIKE '%123%'
如果我想要所有带有PK'123'的记录。这个(以及许多其他记录)的问题是,如果另一个记录的值为“432,9912399,432”,则该记录将显示为“9912399”中的“123”。
使用“LIKE”和字符串解决此问题的一种方法可能是使用where子句:
WHERE mystringcol LIKE '%,123,% OR mystringcol LIKE '%123, OR mystringcol LIKE '%,123
测试“123”在整个字符串的中间,开头或结尾,但是开始变得难看,我宁愿不这样做。
有没有人之前做过这样的事情并且可以指出我正确的方向?
答案 0 :(得分:2)
理论上,Oracle具有收集功能的成员,但对于第三种常规形式,你的想法看起来很奇怪。
SQL> CREATE OR REPLACE PROCEDURE member_of_example AS
2 TYPE nestedTableType IS TABLE OF VARCHAR2(10);
3 myTable1 nestedTableType;
4 result BOOLEAN;
5 BEGIN
6 myTable1 := nestedTableType('F', 'G', 'S');
7 result := 'George' MEMBER OF myTable1;
8 IF result THEN
9 DBMS_OUTPUT.PUT_LINE('''George'' is a member');
10 END IF;
11 END member_of_example;
12 /
从逗号分隔的东西中获取plsql表的函数示例:
CREATE OR REPLACE function Str2NmbTbl(p_str varchar2) return number_table is
l_col number_table := number_table();
l_pos number;
l_cnt number := 1;
l_num number;
begin
l_pos := instr(p_str, '[', l_cnt);
while l_pos > 0 loop
l_num := to_number(substr(p_str, l_pos + 1, instr(p_str, ']', 1, l_cnt) - l_pos - 1));
l_col.extend;
l_col(l_cnt) := l_num;
l_cnt := l_cnt + 1;
l_pos := instr(p_str, '[', l_pos + 1);
end loop;
return l_col;
end;
/
with s as
(select 1 id, '[11412][21][3131][3333]' str from dual union all
select 2 id, '[64376][553]' str from dual union all
select 3 id, '[5943][74621][19][3333][0]' str from dual union all
select 4 id, '[21593][22321][43][094]' str from dual --union all
)
select id, Str2NmbTbl(str) collctn
from s;