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

Returned data type information_schema.identifier does not match expected type

我收到这个错误:

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 转换为 'outputable' 格式以将其从我的函数中取出?

这是我的功能:

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;

您最简单(也可能是最安全)的解决方案是 CAST 将列return 设置为您希望的类型(使用 :: 运算符,或 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

What is the data type of columns in information_schema.columns?

您可以在手册中查找:

或者你可以直接问 Postgres(使用目录 table 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

And how do I convert sql_identifier to an 'outputable' format to get it out of my function?

要找出 any 数据类型的细节:

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

The type of a column is referenced by writing 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<b>%TYPE</b>
              , ordinal_position information_schema.columns.ordinal_position<b>%TYPE</b>
              , field_type       information_schema.columns.data_type<b>%TYPE</b>) 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;

列引用在函数创建时转换为基础类型。您会看到通知,通知您。