【问题标题】:postgres bulk data type changepostgres 批量数据类型更改
【发布时间】:2012-05-25 10:29:07
【问题描述】:

我需要将整个数据库中的所有表列从数据类型timestampwithouttime zone 更改为timestamp(0)withtime zone .
所以我创建了这个函数:

CREATE OR REPLACE FUNCTION grd_replace_datetime_with_timezone()
  RETURNS character varying AS
$BODY$

DECLARE
  old_column RECORD;  
    s text;
BEGIN

FOR old_column IN (
    SELECT
        isc.table_schema as table_schema,
        isc.table_name as table_name,
        isc.column_name as column_name
    FROM 
        information_schema.columns  isc
    INNER JOIN 
        pg_tables pt
            ON (isc.table_schema = pt.schemaname and isc.table_name = pt.tablename)
    WHERE
        isc.column_name like '%date%' and 
        isc.table_schema in ('public') and 
        isc.data_type = 'timestamp without time zone'
    ORDER BY
        isc.table_name ASC
    ) 
LOOP
    RAISE NOTICE 'Schema: %',old_column.table_schema;
    RAISE NOTICE 'Table: %',old_column.table_name;
    RAISE NOTICE 'Column %',old_column.column_name;


    EXECUTE 'ALTER TABLE '||old_column.table_schema||'.'||old_column.table_name||'
                ALTER COLUMN '||old_column.column_name||' TYPE timestamp(0) with time zone';

    RAISE NOTICE '-------------------------------------------------------------------------------';
    RAISE NOTICE '';
END LOOP;


RETURN 'S';
END;
$BODY$
  LANGUAGE plpgsql VOLATILE;

但有些视图取决于受影响的列,我得到了错误:

ERROR:  cannot alter type of a column used by a view or rule

还有关于索引的错误。

如何更改所有timestamp without time zone 列的数据类型?

【问题讨论】:

    标签: sql postgresql types timestamp database-migration


    【解决方案1】:

    据我所知,没有内置方法可以在数据类型更改时自动更改依赖视图。
    我看到了两种可能性:

    1. DROP 类型更改之前的所有依赖视图,然后重新创建它们。

    2. 完全不同的方法:转储数据库,更改转储中的表定义并恢复它。只要您在同一时区这样做,timestamp without time zone 就应该正确地强制转换为 timestamptz(0)。请注意,转换为 timestamptz(0) rounds 到整秒。

    如果您有多个对象,转储和恢复是可行的方法 - 如果您能承受停机时间。

    演示

    CREATE TEMP TABLE t  (id int, x timestamp);
    CREATE TEMP TABLE t1 (id int, x timestamptz(0);
    
    INSERT INTO t VALUES
     (1, '2019-05-25 13:23:03.123')  -- rounds down
     (1, '2019-05-25 13:23:03.987')  -- rounds up
    ,(2, '2019-05-25 23:23:03')
    ,(3, '2019-05-25 0:0:0');
    
    COPY t  TO   '/var/lib/postgres/ts_test.sql';
    COPY t1 FROM '/var/lib/postgres/ts_test.sql';
    
    SELECT t.x, t.x::timestamptz(0), t1.x
    FROM   t
    JOIN   t1 USING (id);
    

    强制自动正确地发生。

    相关:

    【讨论】:

    • 恕我直言,转储+编辑+恢复是唯一明智的做法。除了视图/规则之外,还有一些对模式“不可见”的引用,例如函数和触发器。并且:拥有单独的 --schema-only 和 --data-only 转储,编辑只不过是一个 sed 作业。
    • @wildplasser:我同意,对于一个满手的物品来说,这是要走的路。
    【解决方案2】:

    你可以用 pg_dump 试试

    首先使用 --format=plain --schema-only 进行转储

    更改转储文件中的数据类型并将其恢复到新的数据库中。

    比您使用 --data-only 进行转储并在新数据库中恢复它们。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-07-10
      • 1970-01-01
      • 1970-01-01
      • 2020-03-21
      • 2020-06-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多