【问题标题】:Derby - replace view from which other views dependDerby - 替换其他视图所依赖的视图
【发布时间】:2016-09-13 12:49:26
【问题描述】:
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 不会改变任何东西。
【问题讨论】:
标签:
java
sql
database
derby
ddl
【解决方案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;
}