Postgresql

如何在 plpgsql 過程中參數化 DDL?

  • November 17, 2021

如何在 plpgsql 過程中參數化 DDL 語句?也就是說,我想使用org_label參數作為角色和模式名稱,但下面的程式碼從字面上理解它,我最終得到了角色“org_label”:

create or replace procedure create_org_schema (org_label varchar(63)) -- max identifier len in pgsql is 63
language plpgsql AS $$ BEGIN
 create role org_label IN GROUP organization;
 GRANT org_label TO ardoq_api_customers; -- so that AUTHORIZATION... below works
 CREATE SCHEMA AUTHORIZATION org_label;
 SET ROLE org_label;
 GRANT USAGE on SCHEMA org_label to ardoq_api_customers; -- so that we can list it
 RESET ROLE;
END $$;

我試圖將第一行更改為:

EXECUTE 'create role $1 IN GROUP organization' USING org_label;

但這失敗了:

ERROR:  syntax error at or near "$1" at character 13
QUERY:  create role $1 IN GROUP organization

不能手冊:

參數符號的另一個限制是它們僅適用於 SELECTINSERTUPDATEDELETE命令。在其他語句類型(通常稱為實用程序語句)中,您必須以文本方式插入值,即使它們只是數據值。

EXECUTE .. USING不適用於此。您必須在執行之前連接查詢字元串。通常,format()最方便的是安全地做到這一點:

CREATE OR REPLACE PROCEDURE create_org_schema (org_label varchar(63)) -- max identifier len in pgsql is 63
 LANGUAGE plpgsql AS
$func$
BEGIN
  EXECUTE format ('CREATE ROLE %I IN GROUP organization', org_label);
  -- ...
END
$func$;

請注意使用格式說明符%I來正確引用標識符並防止可能的 SQL 注入。使用合法的小寫名稱讓您的 Postgres 生活簡單。

看:

引用自:https://dba.stackexchange.com/questions/302794