Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/75.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/visual-studio-2008/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 液化,在Oracle中创建外键,前提条件_Java_Sql_Database_Oracle_Liquibase - Fatal编程技术网

Java 液化,在Oracle中创建外键,前提条件

Java 液化,在Oracle中创建外键,前提条件,java,sql,database,oracle,liquibase,Java,Sql,Database,Oracle,Liquibase,我有一个应用程序的生产和QA实例,我正在将Liquibase集成到其中。这意味着DDL和数据已经存在或不存在(如果在开发框中)。我必须创建一个changeLog,它记录在非空DBs上运行的所有内容,但实际上在空DBs上执行。 我在一个很好的方法,但我有点坚持创建外键。数据库是Oracle 一般来说,我创建的前提条件期望各种对象不存在,一旦失败,MARK_就会运行更改 当我不知道外键的确切名称(可能存在也可能不存在)时,我发现很难编写正确的前提条件。 liquibase前提条件中有标记,但它只接受

我有一个应用程序的生产和QA实例,我正在将Liquibase集成到其中。这意味着DDL和数据已经存在或不存在(如果在开发框中)。我必须创建一个changeLog,它记录在非空DBs上运行的所有内容,但实际上在空DBs上执行。 我在一个很好的方法,但我有点坚持创建外键。数据库是Oracle

一般来说,我创建的前提条件期望各种对象不存在,一旦失败,MARK_就会运行更改

当我不知道外键的确切名称(可能存在也可能不存在)时,我发现很难编写正确的前提条件。 liquibase前提条件中有标记,但它只接受schemaName和foreignKeyName属性,并且它们是必需的。在这些情况下,我不能确定外键的名称,因为它们超出了我的控制范围

您可以在以下前提条件下编写自定义SQL:

<changeSet id="1" author="bob">
    <preConditions onFail="WARN">
        <sqlCheck expectedResult="0">select count(*) from oldtable</sqlCheck>
    </preConditions>
    <dropTable tableName="oldtable"/>
</changeSet>
如果MY_表中引用MY_OTHER_表的MY_列上存在外键,则会打印一行。在将其重写为COUNT之后,您可以在不知道其名称的情况下检查是否存在外键

我的问题: 我有几十个外键,我真的要写这么大的SQL几十次吗?有什么建议吗,比如把这个外包给某个职能部门?谢谢


是否值得要求Liquibase开发人员将的name属性设置为可选,并在本地列名中引入referenced table属性?

如果您不知道外键约束名称,我认为您必须按照您的建议执行此操作

但若您可以修改数据库,那个么您可以准备sql脚本,该脚本将准备另一个sql脚本,该脚本将所有FK重命名为已知名称。诸如此类:

BEGIN

FOR cur IN (
    SELECT 
      c_list.CONSTRAINT_NAME as FK_NAME,
      'FK_' || c_dest.TABLE_NAME || '_' || substr(c_dest.COLUMN_NAME, 1, 20) as NEW_FK_NAME,
      c_src.TABLE_NAME as SRC_TABLE,
      c_src.COLUMN_NAME as SRC_COLUMN,
      c_dest.TABLE_NAME as DEST_TABLE,
      c_dest.COLUMN_NAME as DEST_COLUMN
    FROM ALL_CONSTRAINTS c_list, ALL_CONS_COLUMNS c_src, ALL_CONS_COLUMNS c_dest
    WHERE c_list.CONSTRAINT_NAME = c_src.CONSTRAINT_NAME
    AND c_list.R_CONSTRAINT_NAME = c_dest.CONSTRAINT_NAME
    AND c_list.CONSTRAINT_TYPE = 'R'
    AND c_src.TABLE_NAME IN ('<your-tables-here>')
    GROUP BY c_list.CONSTRAINT_NAME, c_src.TABLE_NAME, c_src.COLUMN_NAME, c_dest.TABLE_NAME, c_dest.COLUMN_NAME;
) LOOP

    -- Generate here SQL commands (by string concatenation) something like:
    -- alter table SRC_TABLE rename constraint FK_NAME to NEW_FK_NAME;
    -- then paste this sql commands to some other script and run it

END LOOP;

END;
这是一次性迁移


迁移之后,您知道FK约束名称是什么,并且可以在变更集中使用前置条件。

还有一种可能性:实现接口并将其用作自定义前置条件。更多信息:

以下是已验证的实现:

import liquibase.database.Database;
import liquibase.exception.CustomPreconditionErrorException;
import liquibase.exception.CustomPreconditionFailedException;
import liquibase.precondition.CustomPrecondition;
import liquibase.snapshot.SnapshotGeneratorFactory;
import liquibase.structure.core.ForeignKey;
import liquibase.structure.core.Schema;
import liquibase.structure.core.Table;
import liquibase.util.StringUtils;

/**
 * {@link CustomPrecondition} implementation that checks if a column on a table
 * has a foreign key constraint for some other table.
 */
public final class CheckForeignKey implements CustomPrecondition {

    /**
     * Schema.
     */
    private String schemaName;

    /**
     * Table name (that has the column).
     */
    private String tableName;

    /**
     * Column (that might have the foreign key).
     */
    private String columnName;

    /**
     * Referenced table of the foreign key.
     */
    private String foreignTableName;

    @Override
    public void check(final Database db)
            throws CustomPreconditionFailedException,
            CustomPreconditionErrorException {

        try {
            // The fkey we are looking for
            final ForeignKey fKey = new ForeignKey();

            // Schema, base table
            fKey.setForeignKeyTable(new Table());
            if (StringUtils.trimToNull(getTableName()) != null) {
                fKey.getForeignKeyTable().setName(getTableName());
            }

            final Schema schema = new Schema();
            schema.setName(getSchemaName());
            fKey.getForeignKeyTable().setSchema(schema);

            // Base column
            fKey.addForeignKeyColumn(getColumnName());

            // Referenced table
            fKey.setPrimaryKeyTable(new Table());
            if (StringUtils.trimToNull(getForeignTableName()) != null) {
                fKey.getPrimaryKeyTable().setName(getForeignTableName());
            }

            if (!SnapshotGeneratorFactory.getInstance().has(fKey, db)) {
                throw new CustomPreconditionFailedException(
                        String.format(
                                "Error fkey not found schema %s table %s column %s ftable %s",
                                getSchemaName(), getTableName(),
                                getColumnName(), getForeignTableName()));
            }
        } catch (final CustomPreconditionFailedException e) {
            throw e;
        } catch (final Exception e) {
            throw new CustomPreconditionErrorException("Error", e);
        }
    }

    public String getSchemaName() {
        return schemaName;
    }

    public void setSchemaName(final String schemaName) {
        this.schemaName = schemaName;
    }

    public String getTableName() {
        return tableName;
    }

    public void setTableName(final String tableName) {
        this.tableName = tableName;
    }

    public String getColumnName() {
        return columnName;
    }

    public void setColumnName(final String columnName) {
        this.columnName = columnName;
    }

    public String getForeignTableName() {
        return foreignTableName;
    }

    public void setForeignTableName(final String foreignTableName) {
        this.foreignTableName = foreignTableName;
    }
}

谢谢,总的来说,这可能是一个很好的解决方案。遗憾的是,我无法访问QA和生产数据库,因为它们是由指定的DBA处理的。这是一个好主意,我非常期待在Liquibase中看到它!
import liquibase.database.Database;
import liquibase.exception.CustomPreconditionErrorException;
import liquibase.exception.CustomPreconditionFailedException;
import liquibase.precondition.CustomPrecondition;
import liquibase.snapshot.SnapshotGeneratorFactory;
import liquibase.structure.core.ForeignKey;
import liquibase.structure.core.Schema;
import liquibase.structure.core.Table;
import liquibase.util.StringUtils;

/**
 * {@link CustomPrecondition} implementation that checks if a column on a table
 * has a foreign key constraint for some other table.
 */
public final class CheckForeignKey implements CustomPrecondition {

    /**
     * Schema.
     */
    private String schemaName;

    /**
     * Table name (that has the column).
     */
    private String tableName;

    /**
     * Column (that might have the foreign key).
     */
    private String columnName;

    /**
     * Referenced table of the foreign key.
     */
    private String foreignTableName;

    @Override
    public void check(final Database db)
            throws CustomPreconditionFailedException,
            CustomPreconditionErrorException {

        try {
            // The fkey we are looking for
            final ForeignKey fKey = new ForeignKey();

            // Schema, base table
            fKey.setForeignKeyTable(new Table());
            if (StringUtils.trimToNull(getTableName()) != null) {
                fKey.getForeignKeyTable().setName(getTableName());
            }

            final Schema schema = new Schema();
            schema.setName(getSchemaName());
            fKey.getForeignKeyTable().setSchema(schema);

            // Base column
            fKey.addForeignKeyColumn(getColumnName());

            // Referenced table
            fKey.setPrimaryKeyTable(new Table());
            if (StringUtils.trimToNull(getForeignTableName()) != null) {
                fKey.getPrimaryKeyTable().setName(getForeignTableName());
            }

            if (!SnapshotGeneratorFactory.getInstance().has(fKey, db)) {
                throw new CustomPreconditionFailedException(
                        String.format(
                                "Error fkey not found schema %s table %s column %s ftable %s",
                                getSchemaName(), getTableName(),
                                getColumnName(), getForeignTableName()));
            }
        } catch (final CustomPreconditionFailedException e) {
            throw e;
        } catch (final Exception e) {
            throw new CustomPreconditionErrorException("Error", e);
        }
    }

    public String getSchemaName() {
        return schemaName;
    }

    public void setSchemaName(final String schemaName) {
        this.schemaName = schemaName;
    }

    public String getTableName() {
        return tableName;
    }

    public void setTableName(final String tableName) {
        this.tableName = tableName;
    }

    public String getColumnName() {
        return columnName;
    }

    public void setColumnName(final String columnName) {
        this.columnName = columnName;
    }

    public String getForeignTableName() {
        return foreignTableName;
    }

    public void setForeignTableName(final String foreignTableName) {
        this.foreignTableName = foreignTableName;
    }
}