如何在 postgres 中创建表并插入具有动态值的数据
Posted
技术标签:
【中文标题】如何在 postgres 中创建表并插入具有动态值的数据【英文标题】:How to create a table and insert data with dynamic values in postgres 【发布时间】:2020-02-06 10:34:22 【问题描述】:我正在尝试编写一个表名动态出现的存储过程。 还要检查表是否已经存在,如果不存在就创建。
然后我尝试将数据插入到下表中,如下所示。
在这里,我将pkey
和filedata
作为参数传递以插入查询,其中pkey
是一个字符串,filedata
是一个json 数据,看起来像 "customer": "John Doe", "items": "product": "Beer","qty": 6
我已经尝试了下面的查询,但是表没有被创建它正在给出消息
注意:标识符 public.tablename_11111 将被截断为 public.tablename_11111
这里的表名是public.tablename_11111
CREATE OR REPLACE FUNCTION public.generate_table(tb_name text)
RETURNS text LANGUAGE 'plpgsql'
COST 100 VOLATILE AS $BODY$
BEGIN
EXECUTE format('
CREATE TABLE IF NOT EXISTS %I(
id serial PRIMARY KEY,
pkey VARCHAR (250) NULL,
fpo_data TEXT NULL
)', tb_name || '_pk');
EXECUTE 'INSERT INTO' || tb_name || '_pk (pkey, fpo_data) VALUES
('|| pkey ||', '|| filedata ||')';
END;
$BODY$;
【问题讨论】:
【参考方案1】:首先:%I
,当与 public.tablename_11111
这样的名称一起使用时,不会做你想做的事。
您最终会得到一个名为 "public.tablename_11111"
的表,而不是架构 public
中的表 tablename_11111
。为此,您应该将架构和表名分开,并使用格式%I.%I
:
EXECUTE
format(
'CREATE TABLE %I.%I (...)',
schema_name, tb_name || '_pk'
);
其次,您的 INSERT
语句容易受到 SQL 注入的攻击。您还必须在那里使用format
函数,就像在CREATE TABLE
中一样。
【讨论】:
我尝试将 %I 替换为 %I。%我收到以下错误错误:format() 的参数太少 对,我说你应该分开模式和表名。我应该说:使模式和表成为两个不同的函数参数,并将两者都提供给format
。格式字符串中的每个%
模式都必须有一个对应的参数。
你能输入吗?我没有完全理解你想说的话
谢谢。我尝试了您的代码,存储过程现在运行良好,但是当我尝试从 public.tablename_11111 运行 select * 时,我收到类似关系“public.tablename_11111”不存在的错误
不,那不可能。您真正运行的必须是select * from "public.tablename_11111";
。请注意使 PostgreSQL 将其视为单个标识符而不是模式限定表的双引号。也许您正在使用某些工具错误地为您添加这些引号。【参考方案2】:
理想情况下,您应该将架构名称和表名称作为两个单独的值传递。最好不要将值连接到 SQL 字符串中,而是使用占位符。主要是这样您就不必担心正确格式化它们。
类似于以下内容:
CREATE OR REPLACE FUNCTION public.generate_table(tb_schema text, tb_name text, ???)
RETURNS text
LANGUAGE plpgsql --<< the language name is an identifier, don't quote it
COST 100 VOLATILE
AS $BODY$
BEGIN
tb_name := tb_name ||'_pk';
EXECUTE format('
CREATE TABLE IF NOT EXISTS %I.%I (
id serial PRIMARY KEY,
pkey VARCHAR (250) NULL,
fpo_data TEXT NULL
)', tb_schema, tb_name);
-- where do pkey and filedata come from?
EXECUTE format('INSERT INTO %I.%I (pkey, fpo_data) VALUES (:1, :2)',
tb_schema, tb_name)
using pkey, filedata;
END;
$BODY$;
【讨论】:
以上是关于如何在 postgres 中创建表并插入具有动态值的数据的主要内容,如果未能解决你的问题,请参考以下文章