我想通过在现有表名的基础上附加后缀来创建一个新表名。Postgres 9.5 PL/pgSQL 函数获取作为regclass
类型传入的现有表名,并以字符串形式返回新名称。我format()
用来构造新名称,通常会使用%I
占位符。只要传入的表名不匹配任何 PL/pgSQL 关键字,这就会起作用。在这种情况下,无论我选择(%I
或%s
)什么类型的组件,引用都是错误的。
考虑以下函数:
CREATE OR REPLACE FUNCTION make_name(old_name regclass)
RETURNS text
LANGUAGE plpgsql AS
$$
BEGIN
RETURN format('%I_new', old_name);
END;
$$;
Run Code Online (Sandbox Code Playgroud)
进一步假设有两个表:treenode
和overlay
。为这两个函数调用此函数会产生以下新名称:
SELECT make_name('overlay'::regclass);
make_name
-------------------
"""overlay"""_new
(1 row)
SELECT make_name('treenode'::regclass);
make_name
--------------
treenode_new
(1 row)
Run Code Online (Sandbox Code Playgroud)
事实证明overlay
它也是一个 PL/pgSQL 函数(就像format
,但treenode
不是),它似乎改变了引用行为。如果%s
与 一起使用format()
,结果将是"overlay"_new
。当我使用||
运算符时也会发生同样的情况。如果我使用text
作为输入参数类型,一切都按预期工作,但我更喜欢使用regclass
.
有没有办法用不带引号的关键字匹配regclass
表名(例如overlay …
在编写一个函数来测试表中是否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
类型不是很熟悉。我搜索但找不到如何提取模式名称,只想在重新发明轮子之前先询问。
我有一个大表(审计),其中存储架构和表的关系 ID。这可以通过触发器使用 TG_RELID 方便地填充。它也很方便,因为我可以对它建立索引,并且索引会比我单独存储“模式”(文本)和“表”(文本)列并对它们建立索引要小。另外,我可以使用它进行查询WHERE relation_id = 'myschema:mytable'::regclass
,它就可以工作。
我的问题是,这在备份/恢复方面是否“安全”(schema.table 在目标服务器中是否具有与源服务器中相同的 regclass/oid ?
我还应该注意其他问题吗?