返回的数据类型information_schema.identifier与预期类型不匹配

时间:2017-02-24 23:15:25

标签: postgresql types plpgsql information-schema

我收到此错误:

ERROR:  structure of query does not match function result type
DETAIL:  Returned type information_schema.sql_identifier does not match expected type character varying in column 1.
CONTEXT:  PL/pgSQL function app.get_custom_task_fields(integer,character varying,integer) line 10 at RETURN QUERY

要解决此问题,我需要知道查询中column_nameordinal_positiondata_type的类型。或者更一般地说,information_schema.columns中列的数据类型是什么?如何将sql_identifier转换为'可输出'格式以使其脱离我的函数?

这是我的功能:

CREATE OR REPLACE FUNCTION app.get_custom_task_fields(sess_identity_id int
                                                     ,session_code_str varchar
                                                     ,sess_company_id int)
RETURNS TABLE(field_name varchar,ordinal_position integer,field_type varchar) 
AS $$
DECLARE

BEGIN

    RETURN QUERY
    SELECT t.column_name,t.ordinal_position,t.data_type
    FROM INFORMATION_SCHEMA.COLUMNS as t
    WHERE table_name = 'task_custom' order by t.ordinal_position;
END;
$$ LANGUAGE PLPGSQL;

2 个答案:

答案 0 :(得分:1)

您最简单(也可能是最安全)的解决方案是CAST要返回的类型的列(使用::运算符或CAST(xx AS type)函数):

CREATE OR REPLACE FUNCTION get_custom_task_fields(sess_identity_id int,session_code_str varchar,sess_company_id int)
RETURNS TABLE(field_name varchar,ordinal_position integer,field_type varchar) 
AS $$
BEGIN
    RETURN QUERY 
        SELECT t.column_name    :: varchar
           , t.ordinal_position :: integer
           , t.data_type        :: varchar
        FROM INFORMATION_SCHEMA.COLUMNS as t 
        WHERE table_name = 'task_custom' 
        ORDER BY t.ordinal_position;
END;
$$ LANGUAGE PLPGSQL;

答案 1 :(得分:1)

问题1

  

information_schema.columns中的列的数据类型是什么?

您可以在手册中查找:

或者您可以直接询问Postgres(使用目录表pg_attribute):

SELECT attname, atttypid::regtype
FROM   pg_attribute
WHERE  attrelid = 'information_schema.columns'::regclass
ORDER  BY attnum;
 attname       | atttypid
---------------+----------------------------------
 table_catalog | information_schema.sql_identifier
 table_schema  | information_schema.sql_identifier
 table_name    | information_schema.sql_identifier
...

问题2

  

如何将sql_identifier转换为'可输出'格式以使其脱离我的功能?

要了解任何数据类型的具体信息:

SELECT typname, typtype  -- 'd' is for 'domain'
     , typbasetype::regtype
FROM   pg_type
WHERE  oid = 'information_schema.sql_identifier'::regtype;
 typname        | typtype | typbasetype
----------------+---------+-----------
 sql_identifier | d       | character varying

因此数据类型information_schema.sql_identifiervarchar上的DOMAIN。要找出可能的演员阵容:

SELECT casttarget::regtype, castcontext
FROM   pg_cast
WHERE  castsource = 'character varying'::regtype;
 casttarget | castcontext
------------+------------
 regclass   | i
 text       | i
 character  | i
 ...

您可以强制转换为所需的输出类型。但是有一个......

更简单的解决方案

您不需要知道任何这些。只需引用列的数据类型。 The manual about CREATE FUNCTION

  

通过编写table_name.column_name%TYPE来引用列的类型。

像这样编写你的函数,你就不会出错:

CREATE OR REPLACE FUNCTION app.get_custom_task_fields(sess_identity_id int
                                                    , session_code_str varchar
                                                    , sess_company_id int)
  RETURNS TABLE(field_name       information_schema.columns.column_name%TYPE
              , ordinal_position information_schema.columns.ordinal_position%TYPE
              , field_type       information_schema.columns.data_type%TYPE) AS
$FUNC$
BEGIN
   RETURN QUERY
   SELECT t.column_name, t.ordinal_position, t.data_type
   FROM   information_schema.columns t
   WHERE  t.table_name = 'task_custom'
   ORDER  BY t.ordinal_position;
END
$FUNC$  LANGUAGE plpgsql;

在函数创建时将列引用转换为基础类型。你会看到告知你的通知。