Cast生成'返回类型字符变化与预期类型字符变化不匹配(8)'

时间:2012-05-25 16:31:00

标签: postgresql types plpgsql varchar postgresql-9.1

昨天我们将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}}

有没有人有任何指示?

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无法做到的任何事情。如果我需要长度限制,我使用一个列约束,可以在不重写整个表的情况下进行更改。