Java/Oracle :查找所有相关行并更新它们

Java/Oracle : Find all Dependent Rows and Update Them

我有一个 Oracle table (COMBO_VALUES),它已被许多其他 table 引用。例如 COMBO_VALUES 中的 1 条记录可能已被 100 个不同的 table 引用。

我想找到指向 COMBO_VALUES 记录的所有相关记录(他们的 ID 和 Table 姓名),以便稍后更新它们。

我更喜欢在这个问题中使用 Java 代码,它可以利用 Oracle 元数据来收集我正在寻找的数据(我不精通 PL/SQL)。

顺便说一句,我不想​​改变我的 table 以拥有 "CASCADE" 选项。我想要的(至少现在)是找到依赖行 ID 和 Table 名称。

谢谢...

Oracle 不支持 当 main 中的 pk 发生变化时更新外部表中值的机制。您需要在整个参考表中手动更新值。阅读 documentation.

虽然这是一种丑陋的方式,但这是您所要求的。您可以加入 all_cons_columnsall_constraints 视图以获得 parent-child 基于主键-外键关系的信息。一旦你得到父 table、子 table 和引用列名,你可以稍后在子 table 上使用匹配的 MERGE父行 table.

例如,

SQL> column owner format a10
SQL> column parent_table format a15
SQL> column child_table format a15
SQL> column column_name format a15
SQL> column constraint_name format a15
SQL> column referenced_key format a15
SQL> column constraint_type format a15
SQL> set linesize 200
SQL> SELECT a.owner,
  2    a.table_name parent_table,
  3    b.table_name child_table,
  4    a.column_name,
  5    a.constraint_name,
  6    b.constraint_name referenced_key,
  7    b.constraint_type
  8  FROM all_cons_columns a ,
  9    all_constraints b
 10  WHERE a.owner           ='SCOTT'
 11  AND a.constraint_name = b.r_constraint_name
 12  AND a.table_name      ='DEPT';

OWNER PARENT_TABLE CHILD_TABLE COLUMN_NAME CONSTRAINT_NAME REFERENCED_KEY  CONSTRAINT_TYPE
----- ------------ ----------- ----------- --------------- --------------- ---------------
SCOTT DEPT         EMP         DEPTNO      PK_DEPT         FK_DEPTNO       R

SQL>

所以,上面的查询给了我父子 table 信息以及引用的列名。根据这些信息,使用MERGE语句:

MERGE child_table c
USING parent_table p
ON (p.key = c.key)
WHEN MATCHED THEN
UPDATE SET...

请记住,您不能合并您用于加入 ON 子句的列。

我刚刚写了一个 class,它完全符合我的要求:

  1. 尝试删除可能已被其他记录引用的记录
  2. 查找所有子项并将其引用更改为新 ID
  3. 最后删除记录

这是我想出的代码(抱歉,它可能不够好):

public class RowFinder {
    boolean autoCommit;

    public RowFinder(boolean autoCommit) {
        this.autoCommit = autoCommit;
    }

    public static void main(String[] args) {
        RowFinder rowFinder = new RowFinder(false);
        rowFinder.findRows("YOUR_TABLE_NAME", "PRIMARY_KEY_FIELD_NAME", "OLD_ID", "NEW_ID_FOR_CHILDREN");
    }

    public void findRows(String tableName, String columnName, String oldId, String newId) {

        Connection connection = null;
        java.sql.Statement statement = null;
        try {
            Class.forName("oracle.jdbc.OracleDriver");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }


        try {
            connection = DriverManager.getConnection("jdbc:oracle:thin@DB_IP_ADDRESS:1521:SID", "USER", "PASS");
            connection.setAutoCommit(autoCommit);
            statement = connection.createStatement();

            System.out.println(String.format("\nTrying to Delete %s with Old ID: '%s' and Update Children with New ID: '%s'", tableName, oldId, newId));

            boolean flag = true;
            long counter = 1;
            while (flag) {

                try {
                    String deleteQuery = String.format("delete from %s where %s = %s", tableName, columnName, oldId);
                    statement.executeUpdate(deleteQuery);
                    flag = false;
                } catch (SQLException e) {

                    String errorMessage = e.getMessage();
                    //TRYING TO FIND THE CONSTRAINT NAME FROM ERROR - YOU CAN CHANGE IT ACCORDING TO YOUR PROJECT SETTINGS
                    Pattern pattern = Pattern.compile("\(PROJECT_NAME\.(.*)\)");
                    Matcher matcher = pattern.matcher(errorMessage);
                    String referenceName;
                    if (matcher.find()) {
                        referenceName = matcher.group(1);
                        String constraintTableQuery = String.format("SELECT ucc.table_name,ucc.column_name FROM user_cons_columns ucc WHERE ucc.constraint_name = '%s'", referenceName);
                        try {
                            ResultSet resultSet = statement.executeQuery(constraintTableQuery);
                            resultSet.next();
                            String constraintTableName = resultSet.getString(1);
                            String constraintColumnName = resultSet.getString(2);
                            String updateQuery = String.format("UPDATE %s SET %s = '%s' WHERE %s = '%s'", constraintTableName, constraintColumnName, newId, constraintColumnName, oldId);
                            statement.executeUpdate(updateQuery);
                            System.out.println(String.format("%s. Updated Child Located at : %s => %s",counter++,constraintTableName,constraintColumnName));
                        } catch (SQLException e1) {
                            e1.printStackTrace();
                        }
                    } else {
                        System.out.println("Matcher didn't find anything... Exiting...");

                        if (autoCommit)
                            connection.commit();
                        else
                            connection.rollback();

                        statement.close();
                        connection.close();
                        System.exit(0);
                    }
                }
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            try {

                if (autoCommit){                
                    System.out.println("Deleted the Record and Changed its Children.");
                    connection.commit();    
                }
                else{
                    System.out.println("Rolling Back Changes...");
                    connection.rollback();
                }

                statement.close();
                connection.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

    }
}