在 PostgreSQL 中使用存储过程动态传递数据库和 table 名称

Dynamically passing db and table names using stored procedure in PostgreSQL

我正在 PostgreSQL 中创建一个存储过程,它将首先根据 'ID' 检查给定 table 中是否存在数据。如果是,则将其移动到其他 table 并在给定的 table 名称中插入最新记录。我写了一个存储过程,我在其中使用硬编码值对其进行了尝试,它可以按我的需要工作,但是当我试图使其通用时,即创建变量,然后将这些变量传递到查询中,然后它会抛出错误。我在下面提到 SO linksofficial documentation link 并且能够修改我的存储过程:

  1. First SO link
  2. Second SO link

下面是我的存储过程:

CREATE OR REPLACE PROCEDURE compareDups(ab integer, b json, tablename varchar)
AS $$
DECLARE 
  actualTableName varchar := 'testing.'||tablename;
  histTableName varchar:= actualTableName ||'_hist';
  job_id Integer:=0;
BEGIN --<<<< HERE
  EXECUTE 'SELECT id FROM '||actualTableName||' WHERE id =' INTO job_id USING ab;
  -- if there is data for id in the table then perform below operations
  IF job_id IS NOT NULL THEN
      EXECUTE FORMAT('INSERT INTO %I as select * from %L where id = ',histTableName,actualTableName) USING ab;
      EXECUTE FORMAT('DELETE FROM %I where id = ',actualTableName) USING ab;
      EXECUTE FORMAT('INSERT INTO %I values(,)',actualTableName) USING ab,b;
  -- if id is not present then create a new record in the actualTable
  ELSE    
      EXECUTE FORMAT('INSERT INTO %I values(,)',actualTableName) USING ab,b;
  END IF;

END; --<<<< END HERE
$$
LANGUAGE plpgsql;

因此,虽然 creating variables 我只使用了 EXECUTE 选项,而 calling queries 我使用了 EXECUTE FORMAT(...) 选项。

当我尝试调用它时,出现以下错误:

ERROR:  syntax error at or near "select"
LINE 1: INSERT INTO "testing.sampletesting_hist" as select * from 't...
                                                    ^
QUERY:  INSERT INTO "testing.sampletesting_hist" as select * from 'testing.sampletesting' where id = 
CONTEXT:  PL/pgSQL function comparedups(integer,json,character varying) line 10 at EXECUTE
SQL state: 42601 

我在这里错过了什么?

所以,我想回答我自己的问题,也许它可以帮助像我这样的人。我也可以通过修改设置 schema nameactualtablename 字符串来修复上述代码。因此,我在过程中添加了一个 SET 语句,用于设置需要进行预期操作的模式名称,它对我有用。

CREATE OR REPLACE PROCEDURE compareDups(ab integer, b json, tablename varchar)
AS $$
DECLARE 
  actualTableName varchar := tablename;
  histTableName varchar:= actualTableName ||'_hist';
  job_id Integer:=0;
BEGIN --<<<< HERE
  SET search_path to testing; -- Set the schema name
  EXECUTE 'SELECT id FROM '||actualTableName||' WHERE id =' INTO job_id USING ab;
  -- if there is data for id in the table then perform below operations
  IF job_id IS NOT NULL THEN
      EXECUTE FORMAT('INSERT INTO %I select * from %I where id = ',histTableName,actualTableName) USING ab;
      EXECUTE FORMAT('DELETE FROM %I where id = ',actualTableName) USING ab;
      EXECUTE FORMAT('INSERT INTO %I values(,)',actualTableName) USING ab,b;
  -- if id is not present then create a new record in the actualTable
  ELSE    
      EXECUTE FORMAT('INSERT INTO %I values(,)',actualTableName) USING ab,b;
  END IF;

END; --<<<< END HERE
$$
LANGUAGE plpgsql;  

不知何故,此过程存储在 public 模式下。因此,在调用它时我必须使用以下命令:

set search_path to public;
call compareDups(12,'{"name":"CTTT"}','sampletesting');