向H2数据库中的所有表添加列而不手动列出表

Posted

技术标签:

【中文标题】向H2数据库中的所有表添加列而不手动列出表【英文标题】:Add columns to all tables in H2 database without manually listing tables 【发布时间】:2017-09-27 11:17:43 【问题描述】:

我有一个包含大约 70 个表的 PostgreSQL 数据库,我想为每个表添加两列,created_byupdated_by。由于我们使用的是 Liquibase,因此我编写了一个在 PostgreSQL 中运行良好的更新脚本:

DO $$
DECLARE
  tables CURSOR FOR
    SELECT tablename
    FROM pg_tables
    WHERE schemaname = 'myschema'
    ORDER BY tablename;
BEGIN
  FOR table_record IN tables LOOP
    EXECUTE
      'ALTER TABLE ' || table_record.tablename || ' ADD COLUMN created_by BIGINT; ' ||
      'ALTER TABLE ' || table_record.tablename || ' ADD COLUMN updated_by BIGINT;';
  END LOOP;
END$$;

但是,对于集成测试,我们使用的是 H2 内存数据库,它不接受此 SQL,即使在 PostgreSQL 兼容模式下也是如此。 From this question,我知道如何选择所有表:

SELECT * FROM INFORMATION_SCHEMA.TABLES

但这对myschema 也有效吗?有没有办法存储结果并循环它们以添加列?如答案中所述,我也不明白如何使用或编写准备好的语句。

基本问题是:如何在不手动列出所有表的情况下为 H2 数据库编写等效的更新脚本?

【问题讨论】:

【参考方案1】:

我还没有找到使用 H2 语法的方法。相反,我使用 SQL 使用 PostgreSQL 语法创建适当的查询:

SELECT 'ALTER TABLE ' || tablename || ' ADD COLUMN created_by BIGINT; ' || 
       'ALTER TABLE ' || tablename || ' ADD COLUMN updated_by BIGINT;'
        FROM pg_tables
        WHERE schemaname = 'myschema'
        ORDER BY tablename;

这将返回所有表的ALTER TABLE 查询列表,例如:

ALTER TABLE first_table ADD COLUMN created_by BIGINT;
ALTER TABLE first_table ADD COLUMN updated_by BIGINT;

这不适用于一组变化的表,但我只需要为一组固定的表执行此操作,因此它适用于我的情况。

(我在连接到我的 PostgreSQL 数据库的 SQL Workbench 中执行了查询。结果视图列出了已创建的查询,然后可以将它们复制到在测试期间执行的脚本文件中。)

【讨论】:

【参考方案2】:

试试这样的:-)

DECLARE @Schema VARCHAR(20),
    @Table  VARCHAR(50),
    @Query  VARCHAR(4000),
    @Column VARCHAR(100) = 'Column',
    @Column_props VARCHAR(1000) = 'INT NOT NULL DEFAULT 0'
DECLARE c_cursor CURSOR FAST_FORWARD LOCAL FOR
SELECT TABLE_SCHEMA, TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE             
TABLE_TYPE='BASE TABLE'
OPEN c_cursor
FETCH NEXT FROM c_cursor INTO @Schema, @Table
WHILE @@FETCH_STATUS = 0 BEGIN
    SET @Query = '
    IF COL_LENGTH('''+@Schema+'.'+@Table+''', '''+@Column+''') IS NULL  BEGIN
      ALTER TABLE '+@Schema+'.'+@Table+'
      ADD ['+@Column+'] '+@Column_props+'
    END'
    EXEC(@Query)
    FETCH NEXT FROM c_cursor INTO @Schema, @Table
END
CLOSE c_cursor
DEALLOCATE c_cursor

【讨论】:

我没有使用 Postgre 的经验。这将是我在 MSSQL 上的解决方案 实际上,我需要它用于 H2。执行这个给我Syntax error in SQL statement: "..." expected "OR, FORCE, VIEW, ALIAS, SEQUENCE, USER, TRIGGER, ROLE, SCHEMA, CONSTANT, DOMAIN, TYPE, DATATYPE, AGGREGATE, LINKED, MEMORY, CACHED, LOCAL, GLOBAL, TEMP, TEMPORARY, TABLE, PRIMARY, UNIQUE, HASH, SPATIAL, INDEX"; 我在 while 循环中错过了“获取下一个”。它现在已编辑。但我认为这不是你的问题.. sry,不太了解 h2 db 系统

以上是关于向H2数据库中的所有表添加列而不手动列出表的主要内容,如果未能解决你的问题,请参考以下文章

SQL 从多个表中选择列而不重复数据

如何向现有的 Azure 表存储添加新列

如何使用Scala的DataFrame比较表中的每一列而不关心列是啥? [重复]

Toad for Oracle - 从列选项卡中复制列而不包含所有详细信息

如何定义游标,当我们在两个表之间有一个公共列而不给出别名时

选择多个列而不进行多个查询 php mysql