【问题标题】:Cursor inside SQL querySQL 查询中的游标
【发布时间】:2022-03-05 04:09:42
【问题描述】:

在 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(或任何其他开源 DBMS)是否有类似的功能?

【问题讨论】:

    标签: sql postgresql oracle plsql database-cursor


    【解决方案1】:

    它被称为 CURSOR EXPRESSION,它被记录在明显的地方,Oracle SQL 参考。 Find it here.

    至于您的第二个问题,PostgreSQL 提供的最接近此功能的是“标量子查询”。然而,正如@tbrugz 指出的那样,它们只返回一行和一列,所以它们不像光标表达式。 Read about them in the documentation here。 MySQL 也有标量子查询,同样限制为一列一行。 Docs here。 SQL Server 和 DB2 也是如此(不是开源的,但为了完整性)。

    这排除了所有明显的竞争者。因此,任何其他 DBMS 似乎都不太可能提供我们从 Oracle 的游标表达式中获得的锯齿状结果集。

    【讨论】:

    • 很好的参考资料,谢谢。但 PostgreSQL 的“标量子查询”与“游标表达式”不同:游标表达式可以返回多行多列,而标量子查询只能返回一行(或无)一列
    【解决方案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;
    }
    

    请注意,您必须将 row 显式转换为特定类型。您可以使用 CREATE TYPE 创建必要的类型。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-23
      • 1970-01-01
      • 2022-01-22
      • 2011-08-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多