Derby - 替换其他视图所依赖的视图

时间:2016-09-13 12:49:27

标签: java sql database derby ddl

Derby数据库不支持create or replace view构造。如何替换其他视图所依赖的视图?当我在创建之前尝试删除视图时,Derby会抛出异常

Operation 'DROP VIEW' cannot be performed on object 'VIEW_NAME' because VIEW 'OTHER_VIEW_NAME' is dependent on that object.

set constraints all deferred不会改变任何内容。

1 个答案:

答案 0 :(得分:1)

在运行时用依赖项替换视图:

Pattern messagePattern = Pattern.compile(
        "Operation 'DROP VIEW' cannot be performed on object '\\w+' because VIEW '(\\w+)' is dependent on that object.");

class ViewDefinition {
    String name;
    String definition;
}

public void replaceView(ViewDefinition view, Connection conn) throws SQLException {
    Deque<ViewDefinition> viewsToDrop = new LinkedList<ViewDefinition>();
    Deque<ViewDefinition> viewsToAdd = new LinkedList<ViewDefinition>();
    viewsToDrop.push(view);
    viewsToAdd.push(view);

    Statement st = conn.createStatement();

    try {
        while (!viewsToDrop.isEmpty()) {
            ViewDefinition nextView = viewsToDrop.getFirst();
            try {
                st.execute("drop view " + nextView.name);
            } catch (SQLException e) {
                if ("X0Y23".equals(e.getSQLState())) {
                    // dependency error
                    String message = e.getMessage();
                    Matcher matcher = messagePattern.matcher(message);
                    if (matcher.matches()) {
                        ViewDefinition dependentView = new ViewDefinition();
                        dependentView.name = matcher.group(1);
                        dependentView.definition = getViewDefinition(dependentView.name, conn);
                        viewsToDrop.addFirst(dependentView);
                        viewsToAdd.addFirst(dependentView);
                        continue;
                    } else {
                        throw new RuntimeException(
                                String.format("Can't detect dependent view name for view %s", nextView.name));
                    }
                } else {
                    throw e;
                }
            }
            // view dropped
            viewsToDrop.removeFirst();
        }
        while (!viewsToAdd.isEmpty()) {
            ViewDefinition nextView = viewsToAdd.pollLast();
            st.execute(nextView.definition);
        }
    } finally {
        if (!st.isClosed())
            st.close();
    }
}

private String getViewDefinition(String viewName, Connection conn) throws SQLException {
    String definition = null;
    PreparedStatement ps = conn.prepareStatement(
            "select v.viewdefinition from sys.sysviews v inner join sys.systables t on t.tableid = v.tableid where lower(t.tablename) = lower(?) and t.tabletype = ?");
    ps.setString(1, viewName);
    ps.setString(2, "V");
    ResultSet rs = ps.executeQuery();
    if (rs.next()) {
        definition = rs.getString("viewdefinition");
    }
    rs.close();
    ps.close();
    return definition;
}