【问题标题】:Cast produces 'Returned type character varying does not match expected type character varying(8)'Cast产生'返回的类型字符变化不匹配预期的类型字符变化(8)'
【发布时间】:2012-06-01 06:09:28
【问题描述】:

昨天我们有一个 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),
    ...

我只给出选择的第一列,因为那是发生错误的地方。在今天之前,这个函数运行良好,但现在它给出了这个错误:

错误:查询结构与函数结果类型不匹配
详细信息:返回的类型字符变化与预期类型不匹配 第 1 列中的字符变化(8)。其中:PL/pgSQL 函数 “getwebregistrarpatient_withdeletes”第 3 行,返回查询 [SQL 状态=42804]

nfa.patient_id_number 列是文本,正在为patient_for_registrar 中的patient_id_number 列转换,即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)),

有人指点一下吗?

【问题讨论】:

    标签: postgresql types plpgsql varchar postgresql-9.1


    【解决方案1】:

    你的功能..

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

    【讨论】:

    • 有趣... Patient_for_registrar 是一个专门为这个函数的返回类型创建的表。有问题的列是:patient_id_number varchar(8)。您的第一个建议正是我遇到麻烦的地方,转换为适当的类型给了我同样的错误。我会尝试你的第二个建议,也许它会证明更灵活的解决方案。一旦我试一试,我会更新这个。谢谢。
    • @user720956:在PostgreSQL中,每当您创建表时,系统都会创建一个同名的复合类型(行类型)。我用更多信息修改了我的答案并澄清了一点。
    • 这都是很好的信息——我正在更改为表返回类型,它就像一个魅力。非常感谢您的帮助。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-03-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-17
    • 1970-01-01
    相关资源
    最近更新 更多