PostgreSQL存储过程报错:无法打开关系tempinforme求助
问题分析
你碰到的错误根源很明确:tempInforme是你定义的复合类型,不是数据库表(或临时表)。PostgreSQL里复合类型只用来定义数据结构,不能当数据存储容器用,所以直接往它里面插数据肯定会报错。另外还有个潜在问题:每次调用这个存储过程都会执行CREATE TYPE,第二次调用时会因为类型已经存在而报错。
解决方案
根据你的需求——接收车牌参数,返回符合tempInforme结构的查询结果——用返回集合的函数比存储过程更合适,下面是两种可行的修正方案:
方案1:创建函数直接返回结果集
先单独创建自定义类型(只需要执行一次,不用放在函数里重复创建):
CREATE TYPE public.tempInforme AS ( radicado nchar(10), fecha date, codMarca nchar(20), codLinea int, numMotor varchar(20), numChasis varchar(20), codVehi nchar(20), codColor int );
再创建返回该类型集合的函数:
CREATE OR REPLACE FUNCTION public."GuardarPorPlca"(IN "Placa" character varying) RETURNS SETOF public.tempInforme LANGUAGE 'plpgsql' AS $BODY$ BEGIN RETURN QUERY SELECT radicado, fecha, codMarca, codLinea, numMotor, numChasis, codVehi, codColor FROM Informe WHERE placa LIKE $1; END; $BODY$;
调用时直接查询函数就行:
SELECT * FROM public."GuardarPorPlca"('XYZ-23A');
方案2:用临时表存储结果(如果需要临时保存数据)
要是你确实需要临时存储查询结果,而不是直接返回,可以在存储过程里创建临时表代替复合类型:
CREATE OR REPLACE PROCEDURE public."GuardarPorPlca"(IN "Placa" character varying) LANGUAGE 'plpgsql' AS $BODY$ BEGIN -- 创建会话级临时表,会话结束自动销毁,加IF NOT EXISTS避免重复创建报错 CREATE TEMP TABLE IF NOT EXISTS tempInforme ( radicado nchar(10), fecha date, codMarca nchar(20), codLinea int, numMotor varchar(20), numChasis varchar(20), codVehi nchar(20), codColor int ); -- 清空临时表,防止多次调用累积旧数据 TRUNCATE TABLE tempInforme; -- 插入查询结果到临时表 INSERT INTO tempInforme SELECT radicado, fecha, codMarca, codLinea, numMotor, numChasis, codVehi, codColor FROM Informe WHERE placa LIKE $1; END; $BODY$;
调用后查询临时表就能拿到结果:
CALL public."GuardarPorPlca"('XYZ-23A'); SELECT * FROM tempInforme;
重要提示
- 复合类型只能用来定义数据结构,比如作为函数返回类型、表的字段类型,不能直接存储数据。
- 存储过程主要用来执行无返回值的操作(比如修改数据、执行DDL),如果需要返回查询结果,优先用函数。
- 临时表是会话级别的,只会在当前数据库连接里存在,断开连接后自动删除,适合存放中间结果。
内容的提问来源于stack exchange,提问作者Juan Pablo Montoya
相关产品推荐
相关产品推荐

