Npgsql 7.0后,PostgreSQL PROCEDURE如何返回记录集兼容多库应用?
PostgreSQL PROCEDURE 返回记录集的实现方案
针对你的问题,PostgreSQL 的 PROCEDURE 确实可以返回记录集,以下是几种适配 Npgsql 7.0+ 且能和其他数据库厂商行为对齐的方案:
1. 使用 PL/pgSQL 编写 PROCEDURE,通过 RETURN QUERY 返回结果集
PostgreSQL 的 PL/pgSQL 过程支持用 RETURN QUERY 语句直接返回查询结果,这是最直观的方式,也能被 Npgsql 正确捕获。
示例代码:
CREATE OR REPLACE PROCEDURE public."AttributeSelect"() LANGUAGE plpgsql AS $$ BEGIN RETURN QUERY SELECT "Id" FROM "Attribute"; END; $$;
在你的通用 .NET 代码中,调用该 PROCEDURE 时,只需正常使用 DbCommand.ExecuteReader() 即可读取返回的记录集,和调用其他数据库存储过程的逻辑完全一致。
2. 带 SETOF 类型的 OUT 参数
通过定义 SETOF 类型的 OUT 参数,可以让 PROCEDURE 返回多条记录。这种方式更贴合传统存储过程的参数输出模式,和其他数据库的 OUT 参数行为更一致。
单列返回示例:
CREATE OR REPLACE PROCEDURE public."AttributeSelect"(OUT "Id" integer) LANGUAGE plpgsql AS $$ BEGIN RETURN QUERY SELECT "Id" FROM "Attribute"; END; $$;
多列返回(需先定义自定义记录类型):
-- 定义自定义记录类型 CREATE TYPE public."AttributeType" AS ("Id" integer, "Name" varchar); CREATE OR REPLACE PROCEDURE public."AttributeSelect"(OUT result public."AttributeType") LANGUAGE plpgsql AS $$ BEGIN RETURN QUERY SELECT "Id", "Name" FROM "Attribute"; END; $$;
3. 兼容 SQL 语言 PROCEDURE 的直接 SELECT 输出
如果坚持使用 SQL 语言编写 PROCEDURE(如你提供的示例),Npgsql 7.0+ 默认不会自动捕获 PROCEDURE 中直接执行的 SELECT 结果,需要调整调用方式:
创建 DbCommand 时,直接构造 CALL 语句并设置 CommandType.Text,再执行 ExecuteReader():
var cmd = connection.CreateCommand(); cmd.CommandText = "CALL public.\"AttributeSelect\"()"; cmd.CommandType = CommandType.Text; using (var reader = cmd.ExecuteReader()) { // 读取记录集逻辑 }
不过这种方式会破坏通用代码的适配性,因此更推荐前两种 PL/pgSQL 的实现方案。
关键注意事项
- 确保 PostgreSQL 版本在 11 及以上(PROCEDURE 特性从 11 开始支持)。
- Npgsql 7.0+ 调用 PROCEDURE 时默认使用 PostgreSQL 的
CALL语法,只要 PROCEDURE 正确返回结果集,ExecuteReader()就能正常读取,无需额外配置。
内容的提问来源于stack exchange,提问作者Chris C.
相关产品推荐
相关产品推荐

