昨天我们将PostgreSQL数据库升级到版本9.1.3。我们认为我们已经测试并准备好了所有内容,但我们错过了一项功能。它返回一个这样的表类型:
CREATE OR REPLACE FUNCTION myfunc( patient_number varchar
, tumor_number_param varchar, facility_number varchar)
RETURNS SETOF patient_for_registrar
LANGUAGE plpgsql
AS
$body$
BEGIN
RETURN QUERY
SELECT cast(nfa.patient_id_number as varchar),
...
我只提供select的第一列,因为这是错误发生的地方。在今天之前这个函数运行正常,但现在它给出了这个错误:
错误:查询结构与功能结果类型不匹配
细节:返回的类型字符变化与预期类型不匹配 第1列中的字符变化(8)其中:PL / pgSQL函数 RETURN QUERY中的“getwebregistrarpatient_withdeletes”第3行[SQL 状态= 42804]
列nfa.patient_id_number
是文字,正在为patient_id_number
patient_for_registrar
中的varchar(8)
列投射。substring(cast(nfa.patient_id_number as varchar) from 1 for 8),
cast(substring(nfa.patient_id_number from 1 for 8) as varchar),
cast(substring(nfa.patient_id_number from 1 for 8) as varchar(8)),
。在阅读了一些之后我认为问题是因为从文本转换时没有指定列长度。但问题是我已经尝试了各种子串组合来解决这个问题,但没有人解决这个问题:
{{1}}
有没有人有任何指示?
答案 0 :(得分:10)
你的功能..
RETURNS SETOF patient_for_registrar
返回的行类型必须与声明的类型完全匹配。您没有透露patient_for_registrar
的定义,可能是表的关联复合类型。我引用了关于Declaration of Composite Types的手册:
每当您创建表时,也会自动生成复合类型 使用与表相同的名称创建,以表示表的行 类型。
如果定义了该类型(表)的第一列varchar(8)
(带有长度修饰符) - 如错误消息所示,则必须使用相同的长度修饰符返回varchar(8)
; varchar
不会这样做。对于这个问题,字符串长度是否只有8个字符,数据类型必须匹配是无关紧要的。
varchar
, varchar(n)
and varchar(m)
是PostgreSQL的不同的数据类型。
旧版本没有强制使用类型修饰符,而是with PostgreSQL 9.0 this was changed for plpgsql:
PL / pgSQL现在要求复合结果列匹配 预期的类型修饰符以及基类型(Pavel Stehule,Tom Lane)
例如,如果结果类型的列声明为 NUMERIC(30,2),返回一些NUMERIC是不可接受的 该列中的其他精度。以前的版本忽略了检查 类型修饰符,因此允许结果行没有 实际上符合声明的限制。
您可以转换返回的值以匹配patient_for_registrar
的定义:
nfa.patient_id_number::varchar(8)
或者您可以更改RETURNS
子句。我会使用RETURNS TABLE
并声明匹配的复合类型。这是一个example。
RETURNS TABLE (patient_for_registrar varchar, col2 some_type, ...)
顺便说一下:如果我可以避免,我从不使用varchar
- 特别是不使用长度修饰符。它几乎不提供类型text
无法做到的任何事情。如果我需要长度限制,我使用一个列约束,可以在不重写整个表的情况下进行更改。