Java / Oracle:查找所有从属行并更新它们

时间:2015-05-19 07:08:05

标签: java oracle metadata

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

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

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

顺便说一句,我不想​​改变我的桌面以获得一个" CASCADE"选项。我想要的(至少现在)是找到依赖行Id和表名。

谢谢...

3 个答案:

答案 0 :(得分:1)

虽然这是一种丑陋的方式,但这是你所要求的。您可以加入 all_cons_columns all_constraints 视图,以根据主键 - 外键关系获取父子信息。获得父表,子表和引用列名后,您可以稍后在子表上执行 MERGE ,并将匹配的行形成父表。

例如,

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>

因此,上面的查询给出了父表和子表信息以及引用的列名。根据此信息,使用 MERGE 语句:

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

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

答案 1 :(得分:0)

当pk in main发生更改时, Oracle 不支持更新外部表中值的机制。您需要在整个引用表中手动更新值。阅读documentation

答案 2 :(得分:0)

我刚写了一个完全符合我要求的课程:

  1. 尝试删除可能已被其他记录引用的记录
  2. 查找所有孩子并更改他们对新ID的引用
  3. 最后删除记录
  4. 这是我提出的代码(抱歉,这可能不够好):

    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();
                }
            }
    
        }
    }