2011-12-26 91 views
4

在Oracle中,它可能返回cursor一個SQL查詢中,使用cursor關鍵字,像這樣:遊標SQL查詢

select owner, table_name, 
    cursor (select column_name 
     from all_tab_columns 
     where owner = allt.owner 
     and table_name = allt.table_name) as columns 
from all_tables allt 

的問題是:

  1. 有誰知道在哪裏我可以找到這方面的文件嗎?
  2. PortgreSQL(或任何其他開源DBMS)是否具有類似的功能?

回答

4

它被稱爲CURSOR EXPRESSION,它在明顯的地方記錄在Oracle SQL Reference中。 Find it here

至於你的第二個問題,PostgreSQL爲匹配這個功能提供的最接近的東西是「標量子查詢」。不過,正如@tbrugz所指出的,這些只返回一行和一列,所以它們不像光標表達式。 Read about them in the documentation here。 MySQL也有標量子查詢,同樣限於一列和一行。 Docs here。同樣SQL Server和DB2(不是開源的,但爲了完整性)。

這排除了所有明顯的競爭者。所以,似乎不太可能有任何其他的DBMS提供我們從Oracle的遊標表達式得到的鋸齒結果集。

+1

很好的參考,謝謝。但PostgreSQL的「標量子查詢」與「遊標表達式」不同:遊標表達式可以返回多個行和列,而標量子查詢只能返回一行(或無)和一列 – tbrugz 2011-12-27 12:49:26

2

Postgres提供了遊標表達式,但是它的語法比Oracle更不方便。

首先,你需要創建功能陣列REFCURSOR轉換:

create or replace function arr2crs(arr anyarray) returns refcursor as $$ 
declare crs refcursor; 
begin 
    open crs for select * from unnest(arr); 
    return crs; 
end; 
$$ language plpgsql volatile; 

現在讓我們創建一些測試數據

create table dep as 
select 1 depid, 'Sales' depname 
union all 
select 2 depid, 'IT' depname; 

create table emp as 
select 1 empid, 1 depid, 'John' empname union all 
select 2 empid, 1 depid, 'James' empname union all 
select 3 empid, 2 depid, 'Rob'; 

可以查詢它像這樣

select 
    dep.*, 
    arr2crs(array(
     select row(emp.*)::emp from emp 
     where emp.depid = dep.depid 
    )) emps 
from dep 

而且在這樣的客戶端處理(Java)

public static List Rs2List(ResultSet rs) throws SQLException{ 
    List result = new ArrayList(); 
    ResultSetMetaData meta = rs.getMetaData(); 
    while(rs.next()){ 
     Map row = new HashMap(); 
     for (int i = 1; i <= meta.getColumnCount(); i++){ 
      Object o = rs.getObject(i); 
      row.put(
        meta.getColumnName(i), 
        (o instanceof ResultSet)?Rs2List((ResultSet)o):o); 
     } 
     result.add(row); 
    } 
    return result; 
} 

請注意,您必須將行顯式投射到特定類型。您可以使用CREATE TYPE來創建必要的類型。