【问题标题】:How to use an Oracle Associative Array in a SQL query如何在 SQL 查询中使用 Oracle 关联数组
【发布时间】:2010-12-15 12:24:56
【问题描述】:

ODP.Net 公开了将关联数组作为参数从 C# 传递到 Oracle 存储过程的能力。这是一个不错的功能,除非您尝试在 sql 查询中使用该关联数组中包含的数据。

这样做的原因是它需要上下文切换 - SQL 语句需要 SQL 类型,并且像这样传递到 PL/SQL 的关联数组实际上被定义为 PL/SQL 类型。我相信在 PL/SQL 包/过程/函数中定义的任何类型都是 PL/SQL 类型,而在这些对象之外创建的类型是 SQL 类型(如果您可以更清楚地说明这一点,请这样做,但这不是目标问题)。

所以,问题是,您将使用哪些方法将 PL/SQL 关联数组参数转换为可在过程中用于 sql 语句的东西,如下所示:

OPEN refCursor FOR
SELECT T.*
FROM   SOME_TABLE T,
       ( SELECT COLUMN_VALUE V
         FROM   TABLE( associativeArray )
       ) T2
WHERE  T.NAME = T2.V;

就本示例而言,“associativeArray”是一个简单的 varchar2(200) 表,由 PLS_INTEGER 索引。在 C# 中,associativeArry 参数由字符串[] 填充。

请随意讨论除了使用关联数组之外的其他方法,但请提前知道这些解决方案不会被接受。不过,我有兴趣查看其他选项。

【问题讨论】:

标签: sql oracle plsql associative-array odp.net


【解决方案1】:

我会创建一个这样的数据库类型:

create type v2t as table of varchar2(30);
/

然后在程序中:

FOR i IN 1..associativeArray.COUNT LOOP
    databaseArray.extend(1);
    databaseArray(i) := associativeArray(i);
END LOOP;

OPEN refCursor FOR
SELECT T.*
FROM   SOME_TABLE T,
       ( SELECT COLUMN_VALUE V
         FROM   TABLE( databaseArray )
       ) T2
WHERE  T.NAME = T2.V;

(其中 databaseArray 被声明为 v2t 类型。)

【讨论】:

  • 令人惊讶的是,有多少示例在循环中使用关联数组来运行插入等,但没有讨论或提供回避上下文切换问题的示例。希望这对其他人也有帮助。
  • 这不是创建一个关联数组 - 它是创建一个集合。另请注意:asscoiativeArray.FIRST 可能不是 1associativeArray.COUNTassociativeArray.LAST 可能不相等(尤其是在关联数组稀疏的情况下)。
  • @MT0 我没有说它是“如何创建关联数组”,我是在解释如何解决在 SQL 中使用当前位于关联数组中的数据的问题 - 通过移动它到一个集合。我假设关联数组不是稀疏的,这是真的 - 如果不是,那么显然需要不同的代码!
  • @TonyAndrews 如果关联数组是一个非稀疏的 1 索引数组,那么这几乎总是表明您首先不需要关联数组并且最好已经开始有一个集合(在这种情况下,这个问题变成了学术问题)。
  • 但是,关联数组的使用可能是由于 ODP.Net 的限制,因为 OracleCollectionType enumeration 仅列出 PLSQLAssociativeArray,并且似乎不支持其他(更合适的)集合类型。
【解决方案2】:

您不能在 SQL 范围内使用关联数组 - 它们只能在 PL/SQL 范围内使用。

一种方法是将关联数组映射到集合(如果集合类型已在 SQL 范围而不是 PL/SQL 范围中定义,则可以在 SQL 范围中使用)。

SQL

CREATE TYPE VARCHAR2_200_Array_Type AS TABLE OF VARCHAR2(200);
/

PL/SQL

DECLARE
  TYPE associativeArrayType IS TABLE OF VARCHAR2(200) INDEX BY PLS_INTEGER;
  i                PLS_INTEGER;
  associativeArray associativeArrayType;
  array            VARCHAR2_200_Array_Type;
  cur              SYS_REFCURSOR;
BEGIN
  -- Sample data in the (sparse) associative array
  associativeArray(-2) := 'Test 1';
  associativeArray(0)  := 'Test 2';
  associativeArray(7)  := 'Test 3';

  -- Initialise the collection
  array := VARCHAR2_200_Array_Type();

  -- Loop through the associative array
  i := associativeArray.FIRST;
  WHILE i IS NOT NULL LOOP
    array.EXTEND(1);
    array(array.COUNT) := associativeArray(i);
    i := associativeArray.NEXT(i);
  END LOOP;

  -- Use the collection in a query
  OPEN cur FOR
    SELECT *
    FROM   your_table
    WHERE  your_column MEMBER OF array;
END;
/

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-04-04
    • 2011-02-20
    • 1970-01-01
    • 1970-01-01
    • 2011-02-21
    • 2023-03-09
    • 2013-10-22
    相关资源
    最近更新 更多