【问题标题】: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 命令恢复所有表。一切都恢复了,但索引、键和约束被重命名了。

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

【问题讨论】:

    标签: sql oracle


    【解决方案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
    猜你喜欢
    • 2010-12-08
    • 1970-01-01
    • 1970-01-01
    • 2023-02-13
    • 1970-01-01
    • 2012-12-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多