Postgresql中如何执行动态DDL语句

什么是动态SQL

在执行PL/pgSQL函数或SQL时,有时需要生成动态命令,因为命令涉及不同表或数据类型,仅在运行时才能确定具体对象或值。这时就很适合使用动态SQL。这里不过多解释,看下实例就很好理解了。

生成动态SQL的几种方式
  1. 使用 || 进行拼接
#查看序列当前使用值并加1
postgres=# select 'ALTER SEQUENCE '||sequencename||' RESTART '||last_value+1 from pg_sequences where last_value is not null;
                 ?column?                 
------------------------------------------
 ALTER SEQUENCE tb3_a_seq RESTART 4
 ALTER SEQUENCE products_id_seq RESTART 3
 ALTER SEQUENCE accounts_id_seq RESTART 6
  1. 使用format函数
postgres=# select format('ALTER SEQUENCE %s  RESTART %s',sequencename,last_value + 1) from pg_sequences where last_value is not null;
                  format                   
-------------------------------------------
 ALTER SEQUENCE tb3_a_seq  RESTART 4
 ALTER SEQUENCE products_id_seq  RESTART 3
 ALTER SEQUENCE accounts_id_seq  RESTART 6
  1. 使用quote_ident和quote_literal,使用这两个函数可以自动根据需要给相关的值转义,并加上单引号或者双引号。
    quote_ident用于构造数据库对象名, 例如表名, 列名
    quote_literal用于构造字符串,比如插入或者更新的值
#quote_ident和quote_literal对应format中的%I和%L
postgres=#  select 'ALTER SEQUENCE '||quote_ident(sequencename)||' RESTART '||last_value+1 from pg_sequences where last_value is not null;
                  ?column?                  
--------------------------------------------
 ALTER SEQUENCE tb3_a_seq RESTART 4
 ALTER SEQUENCE products_id_seq RESTART 3
 ALTER SEQUENCE accounts_id_seq RESTART 6
如何执行动态DDL

上面介绍了如何写动态SQL,下面进入今天的重点,看看如何自动执行动态DDL

  1. 在psql中,可以通过变量引入执行
#tb3_a_seq是一个序列
postgres=# select * from tb3_a_seq \gset 
postgres=# select :last_value;
 ?column? 
----------
        3
postgres=# alter sequence tb3_a_seq restart :last_value;
ALTER SEQUENCE
  1. 使用psql中的\gexec 命令执行
#拼接动态DDL
postgres=#  select 'ALTER SEQUENCE '||sequencename||' RESTART '||last_value+1 from pg_sequences where last_value is not null;
                 ?column?                 
------------------------------------------
 ALTER SEQUENCE tb3_a_seq RESTART 5
 ALTER SEQUENCE products_id_seq RESTART 4
 ALTER SEQUENCE accounts_id_seq RESTART 7
(3 rows)

#执行动态DDL
postgres=#  select 'ALTER SEQUENCE '||sequencename||' RESTART '||last_value+1 from pg_sequences where last_value is not null \gexec
ALTER SEQUENCE
ALTER SEQUENCE
ALTER SEQUENCE


#使用quote函数一样的效果
postgres=# select nextval('tb3_a_seq');
 nextval 
---------
      21
(1 row)
postgres=# select 'ALTER SEQUENCE '||quote_ident(sequencename)||' RESTART '||last_value+5 from pg_sequences where last_value is not null \gexec
ALTER SEQUENCE
postgres=#  select nextval('tb3_a_seq');
 nextval 
---------
      26
(1 row)
  1. 使用匿名块执行
postgres=# select nextval('tb3_a_seq');
 nextval 
---------
       7
(1 row)
DO $$
declare
seqname varchar;
my_value bigint;
BEGIN
for seqname,my_value in select sequencename, last_value+1 from pg_sequences where last_value is not null
	loop
    EXECUTE format('ALTER SEQUENCE %s  RESTART %s;',seqname,my_value);
    end loop;
END
$$
LANGUAGE plpgsql;
#执行完成
DO
#查看序列值已增加1
postgres=# select nextval('tb3_a_seq');
 nextval 
---------
       8
(1 row)
  1. 通过自定义函数执行
postgres=# select nextval('tb3_a_seq');
 nextval 
---------
      10
(1 row)

CREATE OR REPLACE FUNCTION exec(raw_query text) RETURNS text AS $$
BEGIN
  EXECUTE raw_query;
  RETURN raw_query;
END
$$
LANGUAGE plpgsql;

#方便观察起见,我们last_value加5
select exec(format('ALTER SEQUENCE %s  RESTART %s',(select sequencename from pg_sequences where last_value is not null),(select last_value+5 from pg_sequences where last_value is not null)));

postgres=# select nextval('tb3_a_seq');
 nextval 
---------
      15
(1 row)
  1. 当然也可以通过format和\gexec命令执行

postgres=# select nextval('tb3_a_seq');
 nextval 
---------
      16
(1 row)

postgres=# select format('ALTER SEQUENCE %s  RESTART %s',sequencename,last_value + 5) from pg_sequences where last_value is not null \gexec
ALTER SEQUENCE
postgres=# select nextval('tb3_a_seq');
 nextval 
---------
      21
(1 row)

参考:
https://www.postgresql.org/docs/14/functions-string.html#FUNCTIONS-STRING-FORMAT
https://blog.crunchydata.com/blog/dynamic-ddl-in-postgresql

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是使用 Java 和 DBeaver 拉取 DDL 语句的示例代码: ```java import java.sql.*; import java.util.*; public class DDLExtractor { public static void main(String[] args) { // 配置数据库连接信息 String url = "jdbc:postgresql://localhost:5432/mydatabase"; String user = "myusername"; String password = "mypassword"; try (Connection conn = DriverManager.getConnection(url, user, password)) { // 获取数据库元数据 DatabaseMetaData metadata = conn.getMetaData(); // 获取所有的表 ResultSet tables = metadata.getTables(null, null, "%", new String[] {"TABLE"}); while (tables.next()) { String tableName = tables.getString("TABLE_NAME"); // 获取表的 DDL 语句 String createTableSQL = getCreateTableSQL(conn, tableName); // 输出 DDL 语句 System.out.println(createTableSQL); } } catch (SQLException e) { e.printStackTrace(); } } private static String getCreateTableSQL(Connection conn, String tableName) throws SQLException { // 创建一个 Statement 对象 Statement stmt = conn.createStatement(); // 执行 SHOW CREATE TABLE 命令获取 DDL 语句 ResultSet rs = stmt.executeQuery("SHOW CREATE TABLE " + tableName); String createTableSQL = ""; while (rs.next()) { createTableSQL = rs.getString("Create Table"); } rs.close(); stmt.close(); return createTableSQL; } } ``` 该示例使用 Java 的 JDBC API 连接到数据库,然后使用 DBeaver 支持的 `SHOW CREATE TABLE` 命令获取表的 DDL 语句。在实际使用时,需要替换代码数据库连接信息和需要拉取 DDL 语句的表。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值