2009-11-11 69 views
7

ODP.Net公開了將關聯陣列作爲參數傳遞到C#中的Oracle存儲過程的功能。它是一個很好的功能,除非您嘗試在SQL查詢中使用該關聯數組中包含的數據。如何在SQL查詢中使用Oracle關聯陣列

原因是它需要一個上下文切換 - SQL語句需要SQL類型和一個傳遞到PL/SQL中的關聯數組,這樣實際上定義爲PL/SQL類型。我相信任何在PL/SQL包/過程/函數中定義的類型都是PL/SQL類型,而在這些對象之外創建的類型是SQL類型(如果您可以提供更清晰的內容,請做它,而不是它的目標題)。

所以,問題是,什麼是在過程中可以在SQL語句中使用這樣你會使用到的PL/SQL關聯數組PARAM轉換成某種方法:

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

對於在本例中,「associativeArray」是由PLS_INTEGER索引的簡單表varchar2(200)。在C#中,associativeArry參數填充字符串[]。

除了使用關聯數組之外,還有其他方法可以討論這種做法,但事先知道這些解決方案是不會被接受的。不過,我有興趣看到其他選項。

+0

在這裏看到了類似的問題+類似的解決方案:http://stackoverflow.com/questions/1625649/oracle-參數與在聲明/ 1655743#1655743 – tuinstoel 2009-11-13 18:51:42

回答

11

我想創建一個數據庫類型是這樣的:

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; 

+0

是的,那工作。 – ScottCher 2009-11-11 16:39:38

+4

令人驚訝的是,有多少例子在循環中使用關聯數組來運行插入等,但是沒有討論或提供用於側向跳轉上下文切換問題的示例。希望這對其他人也有幫助。 – ScottCher 2009-11-11 16:40:49

+0

這不會創建一個關聯數組 - 它正在創建一個集合。還要注意:'asscoiativeArray.FIRST'可能不是'1','associativeArray.COUNT'和'associativeArray.LAST'可能不相等(特別是如果關聯數組稀疏)。 – MT0 2017-08-08 10:25:58

1

(其中databaseArray被聲明爲類型V2T的。)您不能在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; 
/