如何在Postgres的PL / pgSQL函数中编写动态SELECT INTO
查询?
假设我有一个名为tb_name
的变量,它填充在FOR
的{{1}}循环中。现在我有一个名为information_schema.tables
的变量,它将获取每个表的行数。我想要以下内容:
tc
在这种情况下,FOR tb_name in select table_name from information_schema.tables where table_schema='some_schema' and table_name like '%1%'
LOOP
EXECUTE FORMAT('select count(*) into' || tc 'from' || tb_name);
END LOOP
和tb_name
的数据类型应该是什么?
答案 0 :(得分:4)
CREATE OR REPLACE FUNCTION myfunc(_tbl_pattern text, _schema text = 'public')
RETURNS void AS -- or whatever you want to return
$func$
DECLARE
_tb_name information_schema.tables.table_name%TYPE; -- currently varchar
_tc bigint; -- count() returns bigint
BEGIN
FOR _tb_name IN
SELECT table_name
FROM information_schema.tables
WHERE table_schema = _schema
AND table_name ~ _tbl_pattern -- see below!
LOOP
EXECUTE format('SELECT count(*) FROM %I.%I', _schema, _tb_name)
INTO _tc;
-- do something with _tc
END LOOP;
END
$func$ LANGUAGE plpgsql;
我使用下划线(_
)添加所有参数和变量,以避免与表列发生命名冲突。只是一个有用的约定。
_tc
应为 bigint
,因为这是汇总函数count()
返回的内容。
_tb_name
的数据类型是动态地从其父列派生的:information_schema.tables.table_name
%TYPE
。请参阅Copying Types in the manual一章。
您确定只需要information_schema.tables
中列出的表吗?有道理,但要注意其含义。参见:
a_horse已经pointed to the manual和Andy provided a code example。这就是分配从具有EXECUTE
的动态查询返回的单个行或值到(行)变量的方式。 单个列(例如示例中的count
)会自动从行类型中分解,因此我们可以直接分配给标量变量tc
- 就像我们一样将整行分配给记录或行变量。相关:
架构限定动态查询中的表名称。当前search_path
中可能存在其他同名的表,这会导致完全错误(并且非常令人困惑!)的结果而没有架构限定。偷偷摸摸的虫子!或此架构根本不在search_path
中,这会使该函数立即引发异常。
始终 引用标识符,以防范SQL注入和随机错误。架构和表格必须单独引用 !参见:
我使用~
中的正则表达式运算符table_name ~ _tbl_pattern
而不是table_name LIKE ('%' || _tbl_pattern || '%')
,这更简单。无论如何都要警惕模式参数中的特殊字符!参见:
我在函数调用中设置了模式名称的默认值:_schema text = 'public'
。为方便起见,您可能想要也可能不想要。参见:
解决your comment:传递 值 ,使用USING
子句,如:
EXECUTE format('SELECT count(*) FROM %I.%I
WHERE some_column = $1', _schema, _tb_name,column_name)
USING user_def_variable;
相关:
答案 1 :(得分:1)
您似乎想要const OnboardingComplete = ({ first_name, last_name, id, mutate }) => {
的{{1}}占位符,以便将您的变量视为标识符。另外,%I
子句应该在之外准备好的语句。
FORMAT