Thinkphp使用postgresql新库报错解决

DROP FUNCTION IF EXISTS public.table_msg(varchar) CASCADE;
DROP FUNCTION IF EXISTS public.table_msg(varchar, varchar) CASCADE;
DROP FUNCTION IF EXISTS public.pgsql_type(varchar) CASCADE;
DROP TYPE IF EXISTS public.tablestruct CASCADE;

CREATE OR REPLACE FUNCTION public.pgsql_type(a_type character varying) RETURNS character varying AS
$BODY$
DECLARE
     v_type character varying;
BEGIN
     CASE a_type
         WHEN 'int8' THEN
              v_type := 'bigint';
         WHEN 'int4' THEN
              v_type := 'integer';
         WHEN 'int2' THEN
              v_type := 'smallint';
         WHEN 'bpchar' THEN
              v_type := 'char';
         ELSE
              v_type := a_type;
     END CASE;
     RETURN v_type;
END;
$BODY$
LANGUAGE plpgsql;

-- 2. tablestruct 类型
CREATE TYPE public.tablestruct AS (
  fields_key_name varchar(100),
  fields_name varchar(200),
  fields_type varchar(20),
  fields_length bigint,
  fields_not_null varchar(10),
  fields_default varchar(500),
  fields_comment varchar(1000)
);

-- 3. table_msg 函数(带 schema 参数)
CREATE OR REPLACE FUNCTION public.table_msg(a_schema_name varchar, a_table_name varchar)
RETURNS SETOF public.tablestruct AS
$body$
DECLARE
     v_ret tablestruct;
     v_oid oid;
     v_sql varchar;
     v_rec record;
     v_key varchar;
BEGIN
     -- 获取表 oid
     SELECT c.oid INTO v_oid
     FROM pg_class c
     INNER JOIN pg_namespace n ON c.relnamespace = n.oid AND lower(n.nspname) = lower(a_schema_name)
     WHERE c.relname = a_table_name;

     IF NOT FOUND THEN
         RETURN;
     END IF;

     -- 构造动态查询
     v_sql := '
     SELECT
           a.attname AS fields_name,
           a.attnum AS fields_index,
           pgsql_type(t.typname::varchar) AS fields_type,
           a.atttypmod - 4 AS fields_length,
           CASE WHEN a.attnotnull THEN ''not null'' ELSE '''' END AS fields_not_null,
           pg_get_expr(ad.adbin, ad.adrelid) AS fields_default,
           d.description AS fields_comment
     FROM pg_attribute a
     INNER JOIN pg_class c ON a.attrelid = c.oid
     INNER JOIN pg_type t ON a.atttypid = t.oid
     LEFT JOIN pg_attrdef ad ON ad.adrelid = c.oid AND ad.adnum = a.attnum
     LEFT JOIN pg_description d ON d.objoid = c.oid AND d.objsubid = a.attnum
     WHERE a.attnum > 0 AND a.attisdropped = false AND c.oid = ' || v_oid || '
     ORDER BY a.attnum;
     ';

     -- 遍历字段
     FOR v_rec IN EXECUTE v_sql LOOP
         v_ret.fields_name := v_rec.fields_name;
         v_ret.fields_type := v_rec.fields_type;
         IF v_rec.fields_length > 0 THEN
             v_ret.fields_length := v_rec.fields_length;
         ELSE
             v_ret.fields_length := NULL;
         END IF;
         v_ret.fields_not_null := v_rec.fields_not_null;
         v_ret.fields_default := v_rec.fields_default;
         v_ret.fields_comment := v_rec.fields_comment;

         SELECT constraint_name INTO v_key
         FROM information_schema.key_column_usage
         WHERE table_schema = a_schema_name
           AND table_name = a_table_name
           AND column_name = v_rec.fields_name;

         IF FOUND THEN
             v_ret.fields_key_name := v_key;
         ELSE
             v_ret.fields_key_name := '';
         END IF;

         RETURN NEXT v_ret;
     END LOOP;

     RETURN;
END;
$body$
LANGUAGE plpgsql VOLATILE CALLED ON NULL INPUT SECURITY INVOKER;

COMMENT ON FUNCTION public.table_msg(a_schema_name varchar, a_table_name varchar) IS '获得表信息';

-- 4. table_msg 函数(简化版,只传 table_name)
CREATE OR REPLACE FUNCTION public.table_msg(a_table_name varchar)
RETURNS SETOF public.tablestruct AS
$body$
DECLARE
    v_ret tablestruct;
BEGIN
    FOR v_ret IN SELECT * FROM public.table_msg('public', a_table_name) LOOP
        RETURN NEXT v_ret;
    END LOOP;
    RETURN;
END;
$body$
LANGUAGE plpgsql VOLATILE CALLED ON NULL INPUT SECURITY INVOKER;

COMMENT ON FUNCTION public.table_msg(a_table_name varchar) IS '获得表信息';

添加新评论 »