

 从补丁 198 开始，Amazon Redshift 将不再支持创建新的 Python UDF。现有的 Python UDF 将继续正常运行至 2026 年 6 月 30 日。有关更多信息，请参阅[博客文章](https://aws.amazon.com/blogs/big-data/amazon-redshift-python-user-defined-functions-will-reach-end-of-support-after-june-30-2026/)。

# 从存储过程中返回结果集
<a name="stored-procedure-result-set"></a>

本主题介绍存储过程如何返回数据。

您可以使用游标或临时表返回结果集。

## 返回游标
<a name="stored-procedure-return-cursor"></a>

要返回游标，请创建一个过程，该过程具有通过 `refcursor` 数据类型定义的 INOUT 参数。在调用过程时，向游标提供一个名称。然后，您就可以按名称从游标提取结果。

以下示例创建名为 `get_result_set` 的过程，该过程具有名为 `rs_out` 的 INOUT 参数，使用 `refcursor` 数据类型。该过程使用 SELECT 语句打开游标。

```
CREATE OR REPLACE PROCEDURE get_result_set (param IN integer, rs_out INOUT refcursor)
AS $$
BEGIN
  OPEN rs_out FOR SELECT * FROM fact_tbl where id >= param;
END;
$$ LANGUAGE plpgsql;
```

以下 CALL 命令打开名为 `mycursor` 的游标。仅在事务中使用游标。

```
BEGIN;
CALL get_result_set(1, 'mycursor');
```

打开游标之后，您可以从游标中提取数据，如下例所示。

```
FETCH ALL FROM mycursor;

    id | secondary_id | name
-------+--------------+---------
     1 |            1 | Joe
     1 |            2 | Ed
     2 |            1 | Mary
     1 |            3 | Mike
(4 rows)
```

最后，事务完成或回退。

```
COMMIT;   
```

存储过程返回的游标需要遵循与 DECLARE CURSOR 中所述相同的约束和性能注意事项。有关更多信息，请参阅 [游标约束](declare.md#declare-constraints)。

以下示例演示从 JDBC，使用 `get_result_set` 数据类型调用 `refcursor` 存储过程。文本 `'mycursor'`（游标的名称）传递到 `prepareStatement`。结果提取自 `ResultSet`。

```
static void refcursor_example(Connection conn) throws SQLException {
    conn.setAutoCommit(false);
    PreparedStatement proc = conn.prepareStatement("CALL get_result_set(1, 'mycursor')");
    proc.execute();
    ResultSet rs = statement.executeQuery("fetch all from mycursor");
    while (rs.next()) {
      int n = rs.getInt(1);
      System.out.println("n " + n);
    }
```

## 使用临时表
<a name="stored-procedure-return-cursor"></a>

要返回结果，您可以将句柄返回到包含结果行的临时表。客户端可以向存储过程提供名称作为参数。在存储过程内部，可以使用动态 SQL 在临时表上执行操作。下面是一个示例。

```
CREATE PROCEDURE get_result_set(param IN integer, tmp_name INOUT varchar(256)) as $$
DECLARE
  row record;
BEGIN
  EXECUTE 'drop table if exists ' || tmp_name;
  EXECUTE 'create temp table ' || tmp_name || ' as select * from fact_tbl where id <= ' || param;
END;
$$ LANGUAGE plpgsql;

CALL get_result_set(2, 'myresult');
 tmp_name
-----------
 myresult
(1 row)

SELECT * from myresult;
 id | secondary_id | name
----+--------------+------
  1 |            1 | Joe
  2 |            1 | Mary
  1 |            2 | Ed
  1 |            3 | Mike
(4 rows)
```