获取 PL/SQL 集合中元素的索引

发布于 2024-10-14 23:59:23 字数 838 浏览 2 评论 0原文

是否有内置函数可以确定 PL/SQL 集合中元素的(第一个)索引?

就像

DECLARE
  TYPE t_test IS TABLE OF VARCHAR2(1);
  v_test t_test;
BEGIN
  v_test := NEW t_test('A', 'B', 'A');
  dbms_output.put_line( 'A: ' || get_index( v_test, 'A' ) );
  dbms_output.put_line( 'B: ' || get_index( v_test, 'B' ) );
  dbms_output.put_line( 'C: ' || get_index( v_test, 'C' ) );
END;

A: 1
B: 2
C: 

我可以使用关联数组、嵌套表或变量数组,只要有必要。如果同一元素存在多次,则第一次出现的索引就足够了。


否则我必须做类似的事情

CREATE FUNCTION get_index ( in_test IN t_test, in_value IN VARCHAR2 )
  RETURN PLS_INTEGER
AS
  i PLS_INTEGER;
BEGIN

i := in_test.FIRST;
  WHILE( i IS NOT NULL ) LOOP
    IF( in_test(i) = in_value ) THEN
      RETURN i;
    END IF;

    i := in_test.NEXT(i);
  END LOOP;

  RETURN NULL;

END get_index;

Is there a built-in function to determine the (first) index of an element in a PL/SQL collection?

Something like

DECLARE
  TYPE t_test IS TABLE OF VARCHAR2(1);
  v_test t_test;
BEGIN
  v_test := NEW t_test('A', 'B', 'A');
  dbms_output.put_line( 'A: ' || get_index( v_test, 'A' ) );
  dbms_output.put_line( 'B: ' || get_index( v_test, 'B' ) );
  dbms_output.put_line( 'C: ' || get_index( v_test, 'C' ) );
END;

A: 1
B: 2
C: 

I can use Associative Arrays, Nested Tables or Varrays, whatever necessary. If the same element exists more than once, then the index of the first occurrence is sufficient.


Otherwise I'd have to do something like

CREATE FUNCTION get_index ( in_test IN t_test, in_value IN VARCHAR2 )
  RETURN PLS_INTEGER
AS
  i PLS_INTEGER;
BEGIN

i := in_test.FIRST;
  WHILE( i IS NOT NULL ) LOOP
    IF( in_test(i) = in_value ) THEN
      RETURN i;
    END IF;

    i := in_test.NEXT(i);
  END LOOP;

  RETURN NULL;

END get_index;

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

北凤男飞 2024-10-21 23:59:23

不确定这是否真的有帮助,或者您是否认为它更优雅:

create type t_test as table of varchar2(1);
/

DECLARE
--TYPE t_test IS TABLE OF VARCHAR2(1);
  v_test t_test;

  function get_index(q in t_test, c in varchar2) return number is
    ind number;
  begin
    select min(rn) into ind from (
      select column_value cv, rownum rn
       from table(q) 
    )
    where cv = c;

    return ind;
  end get_index;

BEGIN
  v_test := NEW t_test('A', 'B', 'A');

  dbms_output.put_line( 'A: ' || get_index( v_test, 'A' ) );
  dbms_output.put_line( 'B: ' || get_index( v_test, 'B' ) );
  dbms_output.put_line( 'C: ' || get_index( v_test, 'C' ) );
END;
/

show errors

drop type t_test;

Not sure, if this really helps, or if you think it is more elegant:

create type t_test as table of varchar2(1);
/

DECLARE
--TYPE t_test IS TABLE OF VARCHAR2(1);
  v_test t_test;

  function get_index(q in t_test, c in varchar2) return number is
    ind number;
  begin
    select min(rn) into ind from (
      select column_value cv, rownum rn
       from table(q) 
    )
    where cv = c;

    return ind;
  end get_index;

BEGIN
  v_test := NEW t_test('A', 'B', 'A');

  dbms_output.put_line( 'A: ' || get_index( v_test, 'A' ) );
  dbms_output.put_line( 'B: ' || get_index( v_test, 'B' ) );
  dbms_output.put_line( 'C: ' || get_index( v_test, 'C' ) );
END;
/

show errors

drop type t_test;
江南烟雨〆相思醉 2024-10-21 23:59:23

我不认为有一个内置函数可以搜索集合。但是,如果您知道需要经常搜索集合,则可以构建索引。向集合中添加元素会稍微昂贵一些,但查找元素将是 O(1) 操作(而不是强力搜索的 O(n) 操作)。例如,您可以使用如下内容:

SQL> DECLARE
  2     TYPE t_test IS TABLE OF VARCHAR2(1);
  3     TYPE t_test_r IS TABLE OF NUMBER INDEX BY VARCHAR2(1);
  4  
  5     v_test t_test;
  6     v_test_r t_test_r;
  7  
  8     FUNCTION get_index(p_test_r t_test_r,
  9                        p_element VARCHAR2) RETURN NUMBER IS
 10     BEGIN
 11        RETURN p_test_r(p_element);
 12     EXCEPTION
 13        WHEN no_data_found THEN
 14           RETURN NULL;
 15     END get_index;
 16  
 17     PROCEDURE add_element(p_test IN OUT t_test,
 18                           p_test_r IN OUT t_test_r,
 19                           p_element VARCHAR2) IS
 20     BEGIN
 21        p_test.extend;
 22        p_test(p_test.count) := p_element;
 23        p_test_r(p_element) := least(p_test.count,
 24                                     nvl(get_index(p_test_r, p_element),
 25                                         p_test.count));
 26     END add_element;
 27  BEGIN
 28     v_test := NEW t_test();
 29     add_element(v_test, v_test_r, 'A');
 30     add_element(v_test, v_test_r, 'B');
 31     add_element(v_test, v_test_r, 'A');
 32     dbms_output.put_line('A: ' || get_index(v_test_r, 'A'));
 33     dbms_output.put_line('B: ' || get_index(v_test_r, 'B'));
 34     dbms_output.put_line('C: ' || get_index(v_test_r, 'C'));
 35  END;
 36  /

A: 1
B: 2
C: 

PL/SQL procedure successfully completed

您还可以定义一个包含数组的记录,并且与数组交互的所有函数/过程都将使用此记录类型。

I don't think there is a built-in function that searches a collection. However, if you know you will need to search a collection a lot, you could build an index. Adding element to the collection will be a bit more expensive, but looking for an element will be an O(1) operation (instead of O(n) for a brute force search). For example, you could use something like this:

SQL> DECLARE
  2     TYPE t_test IS TABLE OF VARCHAR2(1);
  3     TYPE t_test_r IS TABLE OF NUMBER INDEX BY VARCHAR2(1);
  4  
  5     v_test t_test;
  6     v_test_r t_test_r;
  7  
  8     FUNCTION get_index(p_test_r t_test_r,
  9                        p_element VARCHAR2) RETURN NUMBER IS
 10     BEGIN
 11        RETURN p_test_r(p_element);
 12     EXCEPTION
 13        WHEN no_data_found THEN
 14           RETURN NULL;
 15     END get_index;
 16  
 17     PROCEDURE add_element(p_test IN OUT t_test,
 18                           p_test_r IN OUT t_test_r,
 19                           p_element VARCHAR2) IS
 20     BEGIN
 21        p_test.extend;
 22        p_test(p_test.count) := p_element;
 23        p_test_r(p_element) := least(p_test.count,
 24                                     nvl(get_index(p_test_r, p_element),
 25                                         p_test.count));
 26     END add_element;
 27  BEGIN
 28     v_test := NEW t_test();
 29     add_element(v_test, v_test_r, 'A');
 30     add_element(v_test, v_test_r, 'B');
 31     add_element(v_test, v_test_r, 'A');
 32     dbms_output.put_line('A: ' || get_index(v_test_r, 'A'));
 33     dbms_output.put_line('B: ' || get_index(v_test_r, 'B'));
 34     dbms_output.put_line('C: ' || get_index(v_test_r, 'C'));
 35  END;
 36  /

A: 1
B: 2
C: 

PL/SQL procedure successfully completed

You could also define a record that contains both arrays and all functions/procedures to interact with arrays would use this record type.

真心难拥有 2024-10-21 23:59:23

如有疑问,请查阅文档 ;) (此处

DECLARE
  TYPE aa_type_int IS TABLE OF INTEGER INDEX BY PLS_INTEGER;
  aa_int  aa_type_int;

  PROCEDURE print_first_and_last IS
  BEGIN
    DBMS_OUTPUT.PUT_LINE('FIRST = ' || aa_int.FIRST);
    DBMS_OUTPUT.PUT_LINE('LAST = ' || aa_int.LAST);
  END print_first_and_last;

BEGIN
  aa_int(1) := 3;
  aa_int(2) := 6;
  aa_int(3) := 9;
  aa_int(4) := 12;

  DBMS_OUTPUT.PUT_LINE('Before deletions:');
  print_first_and_last;

  aa_int.DELETE(1);
  aa_int.DELETE(4);

  DBMS_OUTPUT.PUT_LINE('After deletions:');
  print_first_and_last;
END;
/

结果:

Before deletions:
FIRST = 1
LAST = 4
After deletions:
FIRST = 2
LAST = 3

When in doubt, consult the documentation ;) (here)

DECLARE
  TYPE aa_type_int IS TABLE OF INTEGER INDEX BY PLS_INTEGER;
  aa_int  aa_type_int;

  PROCEDURE print_first_and_last IS
  BEGIN
    DBMS_OUTPUT.PUT_LINE('FIRST = ' || aa_int.FIRST);
    DBMS_OUTPUT.PUT_LINE('LAST = ' || aa_int.LAST);
  END print_first_and_last;

BEGIN
  aa_int(1) := 3;
  aa_int(2) := 6;
  aa_int(3) := 9;
  aa_int(4) := 12;

  DBMS_OUTPUT.PUT_LINE('Before deletions:');
  print_first_and_last;

  aa_int.DELETE(1);
  aa_int.DELETE(4);

  DBMS_OUTPUT.PUT_LINE('After deletions:');
  print_first_and_last;
END;
/

Result:

Before deletions:
FIRST = 1
LAST = 4
After deletions:
FIRST = 2
LAST = 3
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文