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

Nul*_*lik 3 postgresql types information-schema plpgsql

我收到此错误:

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
Run Code Online (Sandbox Code Playgroud)

要解决此问题,我需要知道查询中column_name,ordinal_position和的类型。data_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;
Run Code Online (Sandbox Code Playgroud)

Erw*_*ter 6

问题1

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

您可以在手册中查找:

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

SELECT attname, atttypid::regtype
FROM   pg_attribute
WHERE  attrelid = 'information_schema.columns'::regclass
ORDER  BY attnum;
Run Code Online (Sandbox Code Playgroud)
 attname       | atttypid
---------------+----------------------------------
 table_catalog | information_schema.sql_identifier
 table_schema  | information_schema.sql_identifier
 table_name    | information_schema.sql_identifier
...
Run Code Online (Sandbox Code Playgroud)

问题2

如何转换sql_identifier为“可输出”格式以将其从我的函数中取出?

要找出任何数据类型的细节:

SELECT typname, typtype  -- 'd' is for 'domain'
     , typbasetype::regtype
FROM   pg_type
WHERE  oid = 'information_schema.sql_identifier'::regtype;
Run Code Online (Sandbox Code Playgroud)
 typname        | typtype | typbasetype
----------------+---------+-----------
 sql_identifier | d       | character varying
Run Code Online (Sandbox Code Playgroud)

所以数据类型information_schema.sql_identifier是DOMAINon varchar。要找出可能的演员表:

SELECT casttarget::regtype, castcontext
FROM   pg_cast
WHERE  castsource = 'character varying'::regtype;
Run Code Online (Sandbox Code Playgroud)
 casttarget | castcontext
------------+------------
 regclass   | i
 text       | i
 character  | i
 ...
Run Code Online (Sandbox Code Playgroud)

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

更简单的解决方案

你不需要知道这些。只需引用列的数据类型即可。该手册关于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;
Run Code Online (Sandbox Code Playgroud)

列引用在函数创建时转换为基础类型。您会看到通知您相关信息的通知。