如何从不同的数据库复制或更新表索引和约束?

Posted

技术标签:

【中文标题】如何从不同的数据库复制或更新表索引和约束?【英文标题】:How to copy or update table indexes and constraints from different database? 【发布时间】:2019-10-03 09:17:56 【问题描述】:

我们有一个生产 Oracle 11g 数据库,该数据库是由试图集成到内部 Web 应用程序的开发人员删除的表。他说他忘记了他已连接到生产数据库并运行他的命令php artisan migrate:fresh,我搜索了它,它会删除所有表并重新创建它。

然后他尝试使用 flashback 命令恢复所有表。一切都恢复了,但索引、键和约束被重命名了。

是否可以将我们备份数据库的表结构(索引、键、约束)复制/更新到受影响的数据库?

【问题讨论】:

【参考方案1】:

我认为没有直接的方法来获得所需的约束和索引名称,但是你可以通过一些手动工作来实现它,如下所示。

首先,您可以使用以下命令更改约束名称:

alter table <table_name> rename constraint <constarint_name> to <new_constarint_name>;

同样的方法,你可以使用以下命令更改索引名称:

ALTER INDEX <index_name> RENAME TO <new_index_name>;

在您的情况下,您需要某种方法将错误(约束/索引)名称与正确名称联系起来。然后用正确的名称重命名约束/索引。要实现它,您可以尝试以下步骤。 (我给出了约束的例子,你可以为索引实现同样的效果)

第 1 步

使用以下查询从生产数据库获取约束名称及其数据,并使用该数据在备份数据库中创建一个表。 (您可以使用SQL LoaderExternal table。)将此表命名为PROD_DB_CONS

SELECT
    C.TABLE_NAME,
    C.CONSTRAINT_NAME,
    C.CONSTRAINT_TYPE,
    LISTAGG(CC.COLUMN_NAME, ',') WITHIN GROUP(
            ORDER BY
                COLUMN_NAME
        ) CONS_COLUMNS
FROM
    USER_CONSTRAINTS C
    JOIN USER_CONS_COLUMNS CC ON ( C.CONSTRAINT_NAME = CC.CONSTRAINT_NAME )
GROUP BY
    C.TABLE_NAME,
    C.CONSTRAINT_NAME,
    C.CONSTRAINT_TYPE;
第 2 步

使用以下查询在备份数据库中创建相同类型的表:

CREATE TABLE BACKUP_DB_CONS AS
SELECT
    C.TABLE_NAME,
    C.CONSTRAINT_NAME,
    C.CONSTRAINT_TYPE,
    LISTAGG(CC.COLUMN_NAME, ',') WITHIN GROUP(
            ORDER BY
                COLUMN_NAME
        ) CONS_COLUMNS
FROM
    USER_CONSTRAINTS C
    JOIN USER_CONS_COLUMNS CC ON ( C.CONSTRAINT_NAME = CC.CONSTRAINT_NAME )
GROUP BY
    C.TABLE_NAME,
    C.CONSTRAINT_NAME,
    C.CONSTRAINT_TYPE;
第 3 步

Backup DB中执行以下查询,将生成一系列命令来更改生产数据库的所有约束的名称

SELECT
    'ALTER TABLE '
    || B.TABLE_NAME
    || ' RENAME CONSTRAINT '
    || P.CONSTRAINT_NAME
    || ' TO '
    || B.CONSTRAINT_NAME
    || ';'
FROM
    BACKUP_DB_CONS B
    JOIN PROD_DB_CONS P ON ( B.TABLE_NAME = P.TABLE_NAME
                             AND B.CONS_COLUMNS = P.CONS_COLUMNS );
第 4 步

复制所有命令并在生产数据库中执行所有命令。

干杯!!

【讨论】:

谢谢你。对于Step 3,查询输出已经具有相同constraint_name、正确名称的记录。我想查询由于丢弃而更改了 contraint_names 的记录。对于我的表,它们以 BIN$ 开头。我做了一些更改,但不确定它是否正确。 ``` 这是我更新的代码。你能检查一下'SELECT'ALTER TABLE'|| B.TABLE_NAME || '重命名约束' || P.CONSTRAINT_NAME || '到' || B.CONSTRAINT_NAME || ';'从 BACKUP_DB_CONS B JOIN PROD_DB_CONS P ON(B.TABLE_NAME = P.TABLE_NAME AND B.CONSTRAINT_TYPE = P.CONSTRAINT_TYPE AND B.CONS_COLUMNS = P.CONS_COLUMNS); ` 试试这个:SELECT 'ALTER TABLE ' || B.TABLE_NAME || ' RENAME CONSTRAINT ' || P.CONSTRAINT_NAME || ' TO ' || B.CONSTRAINT_NAME || ';' FROM BACKUP_DB_CONS B JOIN PROD_DB_CONS P ON ( B.TABLE_NAME = P.TABLE_NAME AND B.CONSTRAINT_TYPE = P.CONSTRAINT_TYPE AND B.CONS_COLUMNS = P.CONS_COLUMNS AND B.CONSTRAINT_NAME &lt;&gt; P.CONSTRAINT_NAME); 非常感谢。对于索引,我应该使用什么表? USER_INDEXESUSER_IND_COLUMNS

以上是关于如何从不同的数据库复制或更新表索引和约束?的主要内容,如果未能解决你的问题,请参考以下文章

冲突部分索引的 Postgres 唯一或排除约束无法更新票证

复制或克隆带有约束的 SQL 表

如何将一个数据库中的一个表复制到另一个数据库中去

如何在 SQL Server 中将索引从一个表复制到另一个表

我如何提取合并的数据并将其放入不同的工作表中?

约束和索引