Postgresql 如何在postgres中创建表并插入具有动态值的数据

Postgresql 如何在postgres中创建表并插入具有动态值的数据,postgresql,stored-procedures,plpgsql,Postgresql,Stored Procedures,Plpgsql,我正在尝试编写一个存储过程,其中表名是动态出现的。 它还必须检查表是否已经存在,并仅在不存在时创建 然后,稍后我尝试将数据插入表中,如下所示。 这里我将pkey和filedata作为参数传递给插入查询,其中pkey是一个字符串,filedata是一个json数据,看起来像{“客户”:“约翰·多伊”,“物品”:{“产品”:“啤酒”,“数量”:6} 我已经尝试了下面的查询,但是表没有被创建,而是给出了消息 注意:标识符public.tablename_11111将被截断为public.tablena

我正在尝试编写一个存储过程,其中表名是动态出现的。 它还必须检查表是否已经存在,并仅在不存在时创建

然后,稍后我尝试将数据插入表中,如下所示。 这里我将
pkey
filedata
作为参数传递给插入查询,其中
pkey
是一个字符串,
filedata
是一个json数据,看起来像
{“客户”:“约翰·多伊”,“物品”:{“产品”:“啤酒”,“数量”:6}

我已经尝试了下面的查询,但是表没有被创建,而是给出了消息

注意:标识符public.tablename_11111将被截断为public.tablename_11111

这里的表名是public.tablename\u11111

    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$;

第一:
%I
,当与类似于
public.tablename_11111
的名称一起使用时,将不会执行您想要的操作

您将得到一个名为“public.tablename\u11111”的表,而不是架构
public
中的表
tablename\u11111
。为此,应将架构和表名分开,并使用格式
%I.%I

EXECUTE
   format(
      'CREATE TABLE %I.%I (...)',
      schema_name, tb_name || '_pk'
   );

其次,您的
INSERT
语句容易受到SQL注入的攻击。您还必须使用
format
函数,就像在
CREATE TABLE
中一样,理想情况下,您应该将schema name和TABLE name作为两个单独的值传递。最好不要将值连接到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$;
创建或替换函数public.generate_表(tb_架构文本,tb_名称文本,?)
返回文本

语言plpgsql--我尝试将%I替换为%I。%n我得到以下错误:format()的参数太少。对,我说过应该将架构和表名分开。我应该说:让schema和table成为两个不同的函数参数,并将它们都输入到
格式中。格式字符串中的每个
%
模式必须有相应的参数。请键入它。我不明白你到底想说什么。我尝试了您的代码存储过程现在运行正常,但是当我尝试运行select*from public.tablename_11111时,我得到的错误类似于关系“public.tablename_11111”不存在否,不能。您真正运行的必须是“public.tablename_11111”中的
select*。请注意,双引号使PostgreSQL将其视为单个标识符,而不是模式限定表。也许你正在使用某种工具,误导性地为你添加这些引用。