在 PostgreSQL 中使用存储过程动态传递数据库和 table 名称
Dynamically passing db and table names using stored procedure in PostgreSQL
我正在 PostgreSQL
中创建一个存储过程,它将首先根据 'ID'
检查给定 table 中是否存在数据。如果是,则将其移动到其他 table 并在给定的 table 名称中插入最新记录。我写了一个存储过程,我在其中使用硬编码值对其进行了尝试,它可以按我的需要工作,但是当我试图使其通用时,即创建变量,然后将这些变量传递到查询中,然后它会抛出错误。我在下面提到 SO links
和 official documentation link 并且能够修改我的存储过程:
- First SO link
- 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 name
的 actualtablename
字符串来修复上述代码。因此,我在过程中添加了一个 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');
我正在 PostgreSQL
中创建一个存储过程,它将首先根据 'ID'
检查给定 table 中是否存在数据。如果是,则将其移动到其他 table 并在给定的 table 名称中插入最新记录。我写了一个存储过程,我在其中使用硬编码值对其进行了尝试,它可以按我的需要工作,但是当我试图使其通用时,即创建变量,然后将这些变量传递到查询中,然后它会抛出错误。我在下面提到 SO links
和 official documentation link 并且能够修改我的存储过程:
- First SO link
- 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 name
的 actualtablename
字符串来修复上述代码。因此,我在过程中添加了一个 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');