0

我有一些代码在 Oracle PL/SQL 中创建了一个引用游标,以便能够遍历结果行。该表有一个大的管道分隔的文本字符串列,然后我循环获取 x 位置数组值

(例如:如果这些行都像 'Mike|Male|100|Yes|UK' 和 'Dave|Male|200|No|UK' 那么我有一个公式允许将数组位置传递给函数以返回结果值的数组

数组位置 1 调用返回 'Mike' 和 'Dave' 数组位置 2 调用返回 'Male' 和 'Male'

如果我希望能够拥有一个返回数组位置的不同值的函数,那么最好的方法是什么

所以数组位置 1 调用将返回 2 数组位置 2 调用将返回 1

我对 PL/SQL 很陌生,所以请原谅这个愚蠢的问题!

不幸的是,将源表拆分为单独的列不是一种选择:-(

非常感谢

麦克风

作为对@zero323 的回应(抱歉错过了这一点)

到目前为止的示例代码是......

FUNCTION DistinctInterfacelineValues(
    inArrayPos     NUMBER,
    inSessionIdMIN NUMBER,
    inSessionIdMAX NUMBER)
  RETURN NUMBER
AS
  int_cursor interfaceline_refcursor_type;
  runningTotal NUMBER:=0;
  tempValue    NUMBER:=0;
  int_record inttestintrecs%ROWTYPE;
  lineLength INTEGER:=1;
  distinctCount NUMBER:=0;

  TYPE table_type IS TABLE OF VARCHAR2(100) INDEX BY BINARY_INTEGER; 
  tempTable  table_type;
  tempTablePos INTEGER:=1;

BEGIN

 OPEN int_cursor FOR SELECT * FROM inttestintrecs WHERE (sessionid>=inSessionIdMIN AND sessionid <=inSessionIdMAX);
  LOOP
    FETCH int_cursor INTO int_record;
    EXIT
  WHEN int_cursor%NOTFOUND;
    lineLength := LENGTH(int_record.interfaceline) - LENGTH(REPLACE(int_record.interfaceline, '|', '')) + 1;
    FOR i                                         IN 1 .. lineLength
    LOOP
      IF i            =inArrayPos THEN
***VALUE HERE IS 'Mike' or 'Dave' DEPENDING ON LOOP POSITION***
***I WANT TO KNOW COUNT THE DISTINCT VALUES HERE***
      END IF;
    END LOOP;
  END LOOP;
  CLOSE int_cursor;
  RETURN runningTotal;



END DistinctInterfacelineValues;
4

1 回答 1

1

您实际上并不需要 PL/SQL。你可以使用regexp_substr

select count(distinct value)
from (
  select regexp_substr(interfaceline, '[^|]+', 1, :arrayPos) as value
  from inttestintrecs
  where sessionid between :loSessId and :hiSessId
);

...其中绑定变量是您传递给函数的值。如果你真的想要一个函数,你可以包装查询(使用 tbonereplace处理空值的技巧更新):

create or replace function DistinctInterfacelineValues(
    inArrayPos     NUMBER,
    inSessionIdMIN NUMBER,
    inSessionIdMAX NUMBER)
  RETURN NUMBER
AS
  distinctCount NUMBER;
BEGIN
  select count(distinct value)
  into distinctCount
  from (
    select trim(regexp_substr(replace(interfaceline, '|', ' |'),
      '[^|]+', 1, inArrayPos)) as value
    from inttestintrecs
    where sessionid between inSessionIdMIN and inSessionIdMAX
  );
  RETURN distinctCount;
END;
/

SQL 小提琴演示


在您发布的嵌套循环版本中,您可以维护一个按值而不是数字索引的 PL/SQL 表:

...
  TYPE table_type IS TABLE OF NUMBER INDEX BY VARCHAR2(100); 
  tempTable  table_type;
  tempValue VARCHAR2(100);
...
      IF i = inArrayPos THEN
        tempValue := regexp_substr(int_record.interfaceline, '[^|]+', 1, i);
        tempTable(tempValue) := 1;
      END IF;
...
  RETURN tempTable.count;
...

另一个 Fiddle只是为了好玩,但是拥有所有 PL/SQL 循环开销确实没有意义,尤其是regexp_substr在中间的情况下。你可以增加tempTable每个值的计数,这样你就知道你看到了多少,你也可以从中获取实际值tempTable......但是你可以从纯 SQL 版本中轻松获取这些值(选择value, count(*)distinct value)。

于 2013-09-20T11:40:52.687 回答