PostgreSQL 重命名表 - 级联重命名对象,例如索引、包含表名称的约束

问题描述 投票:0回答:2

我用

ALTER TABLE _ RENAME TO _
重命名了我的表格:

ALTER TABLE foods RENAME TO food;
ALTER TABLE foods_nutrients RENAME TO food_nutrient;

它有效,但是包含这些表名的其他数据库对象(例如索引、序列和约束)没有更新。所以我必须像这样手动更新它们:

ALTER INDEX foods_pkey RENAME TO food_pkey;
ALTER SEQUENCE foods_id_seq RENAME TO food_id_seq;
ALTER TABLE food_nutrient RENAME CONSTRAINT foods_nutrients_food_id_fkey TO food_nutrient_food_id_fkey;

没有必要重命名它们,但不这样做感觉不对。我想知道是否有命令可以自动执行此操作。或者重命名所有包含旧表名的对象并不常见?

postgresql
2个回答
4
投票

索引、序列等名称与任何表名称之间没有技术关系。所以没有可靠的方法来自动重命名它们。

您可以编写一个脚本来遍历架构并通过搜索和替换来重命名事物,但这存在误报的风险。


0
投票

这将重命名任何不遵循

$tableName_$columnName
名称的索引(复合索引将使用
_
连接列组件的每个名称),
$tableName_pkey
的主键索引:

-- https://stackoverflow.com/questions/1348126/postgresql-modify-owner-on-all-tables-simultaneously-in-postgresql/37259655#37259655
DO $$DECLARE r record;
BEGIN
    FOR r IN
        WITH pkey AS (
            SELECT schema_name, table_name, constraint_name index_name, table_name || '_pkey' new_index_name
            FROM (
                SELECT n.nspname schema_name, cl.relname table_name, c.conname constraint_name, c.contype constraint_type
                FROM pg_constraint c
                JOIN pg_class cl ON c.conrelid = cl.oid
                JOIN pg_namespace n ON n.oid = cl.relnamespace
            ) t
            WHERE constraint_type = 'p'
        ), index AS (
            SELECT schema_name, table_name, index_name, new_index_name
            FROM (
                SELECT schema_name, table_name, index_name, table_name || '_' || string_agg(columns, '_') new_index_name
                FROM (
                    SELECT n.nspname schema_name, t.relname table_name, i.relname index_name, a.attname columns
                    FROM pg_index x
                    -- https://stackoverflow.com/questions/37329561/how-to-list-indexes-created-for-table-in-postgres/37330092#37330092
                    JOIN pg_class t ON t.oid = x.indrelid
                    JOIN pg_namespace n ON n.oid = t.relnamespace
                    JOIN pg_class i ON i.oid = x.indexrelid
                    -- https://stackoverflow.com/questions/55447819/how-to-get-the-list-of-column-names-for-all-indexes-on-a-table-in-postgresql/55448707#55448707
                    JOIN pg_attribute a ON a.attrelid = x.indrelid AND a.attnum = ANY(x.indkey)
                ) t
                GROUP BY schema_name, table_name, index_name
            ) t
            WHERE index_name != new_index_name
        ), rename AS (
            SELECT index.* FROM index LEFT JOIN pkey
                ON index.schema_name = pkey.schema_name
                AND index.table_name = pkey.table_name
                AND index.index_name != pkey.index_name
            WHERE index.schema_name = 'tbm' AND pkey.schema_name = 'tbm'
            UNION
            SELECT * FROM pkey WHERE schema_name = 'tbm' AND index_name != new_index_name
        )
        SELECT 'ALTER INDEX "' || schema_name || '"."' || index_name ||
               '" RENAME TO "' || new_index_name || '";' sql FROM rename
    LOOP
         EXECUTE r.sql;
    END LOOP;
END$$;
© www.soinside.com 2019 - 2024. All rights reserved.