Курсор внутри SQL-запроса - PullRequest
       8

Курсор внутри SQL-запроса

4 голосов
/ 26 декабря 2011

В Oracle можно вернуть cursor внутри запроса SQL, используя ключевое слово cursor, например:

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 (или любая другая СУБД с открытым исходным кодом) похожую функцию?

Ответы [ 2 ]

4 голосов
/ 23 апреля 2012

Postgres предоставляет выражения курсора, но синтаксис немного менее удобен, чем у Oracle.

Сначала вам нужно создать функцию для преобразования массива в прекурсор:

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;

Теперь давайте создадим некоторый тестdata

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 для создания необходимых типов.

4 голосов
/ 26 декабря 2011

Это называется CURSOR EXPRESSION, и оно задокументировано в очевидном месте, Oracle SQL Reference. Найдите здесь .

Что касается вашего второго вопроса, то, что предлагает PostgreSQL для соответствия этой функциональности, это «скалярные подзапросы». Однако, как указывает @tbrugz, они возвращают только одну строку и один столбец, поэтому они не очень похожи на выражения курсора. О них читайте в документации здесь . MySQL также имеет скалярные подзапросы, опять же ограниченные одним столбцом и одной строкой. Документы здесь . Аналогично SQL Server и DB2 (не с открытым исходным кодом, но для полноты).

Это исключает всех очевидных претендентов. Таким образом, кажется маловероятным, что любая другая СУБД предлагает зубчатый набор результатов, который мы получаем из выражения курсора Oracle.

...