0

我想将主键列表存储到同一张表中的其他记录。然后我希望能够执行类似于以下内容的选择:

SELECT * FROM mytable WHERE myarraycol CONTAINS '123'

我已经看到 Oracle 有一个数组数据类型。但是,看起来 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”是否在整个字符串的中间、开头或结尾,但这开始变得丑陋,我宁愿不这样做。

以前有没有人做过这样的事情并且可以指出我正确的方向?

4

1 回答 1

2

从理论上讲,Oracle 具有用于收集的 MEMBER OF 功能,但对于第 3 范式,您的想法看起来很奇怪。

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;
于 2012-10-19T20:19:53.500 回答