如何在 PostgreSQL 中获取 regclass 类型表的模式名称?

tin*_*lyx 5 postgresql catalogs system-tables regclass

在编写一个函数来测试表中是否col_name存在一列时_tbl,我想提取表的模式名称,该名称作为regclass参数传递给函数(为了安全??)。

CREATE OR REPLACE FUNCTION column_exists(_tbl regclass, col_name text)
  RETURNS bool AS
$func$
  SELECT EXISTS (
    SELECT 1 FROM information_schema.columns 
    WHERE table_schema=get_schema($1) 
      AND table_name=get_table($1) 
      AND column_name=$2
    );
$func$  LANGUAGE sql;
Run Code Online (Sandbox Code Playgroud)

所以如果表名是'staging.my_table'::regclass,我想staging从一个虚构的函数中获取get_schema

我可以用 eg 来实现这个功能split_part(_tbl::text, '.', 1)吗?

此外,是否保证表名_tbl在转换为文本时始终具有模式名称?(即不省略诸如public.

我对这种regclass类型不是很熟悉。我搜索但找不到如何提取模式名称,只想在重新发明轮子之前先询问。

Eva*_*oll 6

我可以用 eg 来实现这个功能split_part(_tbl::text, '.', 1)吗?

我不确定那是否安全。相反,我会使用,

SELECT nspname
FROM pg_catalog.pg_class AS c
JOIN pg_catalog.pg_namespace AS ns
  ON c.relnamespace = ns.oid
WHERE c.oid = _tbl;
Run Code Online (Sandbox Code Playgroud)

这是保证工作。

在编写一个函数来测试表中是否col_name存在一列时_tbl,我想提取表的模式名称,该名称作为 regclass 参数传递给函数(为了安全??)。

所以你可以做类似的事情,

SELECT nspname
FROM pg_catalog.pg_attribute AS a
JOIN pg_catalog.pg_class AS c
  ON a.attrelid = c.oid
JOIN pg_catalog.pg_namespace AS ns
  ON c.relnamespace = ns.oid
WHERE c.oid = _tbl
  AND a.attname = col_name;
Run Code Online (Sandbox Code Playgroud)

更新

如果您有一个完全限定的标识符,其中包含表名和模式名,您可以使用parse_ident它来安全地解析它。


Erw*_*ter 5

为了进一步简化,您可以使用转换为regnamespace- Postgres 9.5 引入的另一种对象标识符类型

SELECT relnamespace::regnamespace::text
FROM   pg_catalog.pg_class
WHERE  oid = _tbl;
Run Code Online (Sandbox Code Playgroud)

强制转换对象标识符类型以text生成完全限定的(仅当当前search_path需要时)和双引号(仅在必要时)字符串。

但是,如果您pg_attribute直接使用,则不需要任何这些:

CREATE OR REPLACE FUNCTION pg_temp.column_exists(_tbl regclass, _col_name text)
   RETURNS bool AS
$func$
SELECT EXISTS (
   SELECT FROM pg_catalog.pg_attribute
   WHERE attrelid = _tbl
   AND   attname = _col_name
   );
$func$  LANGUAGE sql;
Run Code Online (Sandbox Code Playgroud)

更简单、更短、更快。