Skip to content
项目
群组
代码片段
帮助
正在加载...
帮助
为 GitLab 提交贡献
登录/注册
切换导航
H
h2database
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分枝图
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
计划
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
分枝图
统计图
创建新议题
作业
提交
议题看板
打开侧边栏
Administrator
h2database
Commits
8382475f
提交
8382475f
authored
6月 19, 2010
作者:
sainsbury.kerry
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
DROP VIEW now supports the CASCADE and RESTRICT clauses
CREATE VIEW now supports the OR REPLACE clause
上级
63264225
全部展开
隐藏空白字符变更
内嵌
并排
正在显示
11 个修改的文件
包含
461 行增加
和
121 行删除
+461
-121
help.csv
h2/src/docsrc/help/help.csv
+1
-1
changelog.html
h2/src/docsrc/html/changelog.html
+3
-1
Parser.java
h2/src/main/org/h2/command/Parser.java
+29
-7
CreateView.java
h2/src/main/org/h2/command/ddl/CreateView.java
+104
-11
DropView.java
h2/src/main/org/h2/command/ddl/DropView.java
+17
-0
help.csv
h2/src/main/org/h2/res/help.csv
+1
-1
TableView.java
h2/src/main/org/h2/table/TableView.java
+22
-2
SimpleResultSet.java
h2/src/main/org/h2/tools/SimpleResultSet.java
+98
-98
TestAll.java
h2/src/test/org/h2/test/TestAll.java
+2
-0
TestViewDropView.java
h2/src/test/org/h2/test/db/TestViewDropView.java
+181
-0
test-1.2.txt
h2/src/test/org/h2/test/test-1.2.txt
+3
-0
没有找到文件。
h2/src/docsrc/help/help.csv
浏览文件 @
8382475f
...
...
@@ -748,7 +748,7 @@ DROP USER TOM
"
"Commands (DDL)","DROP VIEW","
DROP VIEW [ IF EXISTS ] viewName [RESTRICT | CASCADE ]
DROP VIEW [ IF EXISTS ] viewName [
RESTRICT | CASCADE ]
","
Drops a view, and all dependent views if the CASCADE clause is used.
The command will fail if dependent views exist and the RESTRICT clause is used. This is the default.
...
...
h2/src/docsrc/html/changelog.html
浏览文件 @
8382475f
...
...
@@ -35,6 +35,8 @@ Change Log
</li><li>
Version 1.2.137 could still not be converted to Java 1.4
(because the Retrotranslator doesn't support BigDecimal.precision).
</li><li>
Cluster: non-admin users could not connect when one of the cluster node was stopped. Issue 206.
</li><li>
DROP VIEW now supports the CASCADE and RESTRICT clauses (patch from Kerry Sainsbury)
</li><li>
CREATE VIEW now supports the OR REPLACE clause (patch from Kerry Sainsbury)
</li></ul>
<h2>
Version 1.2.137 (2010-06-06)
</h2>
...
...
@@ -383,7 +385,7 @@ Change Log
This could cause the server-less multi-connection mode to fail.
</li><li>
Result sets larger than 2 GB threw an exception "Negative seek offset". Fixed.
</li><li>
If the system property h2.check was set to false, an ArrayIndexOutOfBoundsException could occur.
</li><li>
Alter table is now supported even if a table has views defined.
</li><li>
Alter table is now supported even if a table has views defined.
(Patch from Kerry Sainsbury).
</li><li>
Fulltext search: exceptions within the fulltext search package had the wrong SQL state.
</li><li>
The Lucene fulltext search ignored transaction rollback. Fixed using a trigger on rollback.
</li><li>
Trigger can now be called on rollback.
...
...
h2/src/main/org/h2/command/Parser.java
浏览文件 @
8382475f
...
...
@@ -1154,6 +1154,10 @@ public class Parser {
command
.
setViewName
(
viewName
);
ifExists
=
readIfExists
(
ifExists
);
command
.
setIfExists
(
ifExists
);
Integer
dropAction
=
parseCascadeOrRestrict
();
if
(
dropAction
!=
null
)
{
command
.
setDropAction
(
dropAction
);
}
return
command
;
}
else
if
(
readIf
(
"ROLE"
))
{
boolean
ifExists
=
readIfExists
(
false
);
...
...
@@ -3533,9 +3537,15 @@ public class Parser {
}
private
Prepared
parseCreate
()
{
boolean
orReplace
=
false
;
if
(
readIf
(
"OR"
))
{
read
(
"REPLACE"
);
orReplace
=
true
;
}
boolean
force
=
readIf
(
"FORCE"
);
if
(
readIf
(
"VIEW"
))
{
return
parseCreateView
(
force
);
return
parseCreateView
(
force
,
orReplace
);
}
else
if
(
readIf
(
"ALIAS"
))
{
return
parseCreateFunctionAlias
(
force
);
}
else
if
(
readIf
(
"SEQUENCE"
))
{
...
...
@@ -3951,7 +3961,7 @@ public class Parser {
return
query
;
}
private
CreateView
parseCreateView
(
boolean
force
)
{
private
CreateView
parseCreateView
(
boolean
force
,
boolean
orReplace
)
{
boolean
ifNotExists
=
readIfNoExists
();
String
viewName
=
readIdentifierWithSchema
();
CreateView
command
=
new
CreateView
(
session
,
getSchema
());
...
...
@@ -3959,6 +3969,8 @@ public class Parser {
command
.
setViewName
(
viewName
);
command
.
setIfNotExists
(
ifNotExists
);
command
.
setComment
(
readCommentIf
());
command
.
setOrReplace
(
orReplace
);
command
.
setForce
(
force
);
if
(
readIf
(
"("
))
{
String
[]
cols
=
parseColumnList
();
command
.
setColumnNames
(
cols
);
...
...
@@ -4613,11 +4625,11 @@ public class Parser {
}
private
int
parseAction
()
{
if
(
readIf
(
"CASCADE"
))
{
return
ConstraintReferential
.
CASCADE
;
}
else
if
(
readIf
(
"RESTRICT"
))
{
return
ConstraintReferential
.
RESTRICT
;
}
else
if
(
readIf
(
"NO"
))
{
Integer
result
=
parseCascadeOrRestrict
();
if
(
result
!=
null
)
{
return
result
;
}
if
(
readIf
(
"NO"
))
{
read
(
"ACTION"
);
return
ConstraintReferential
.
RESTRICT
;
}
else
{
...
...
@@ -4630,6 +4642,16 @@ public class Parser {
}
}
private
Integer
parseCascadeOrRestrict
()
{
if
(
readIf
(
"CASCADE"
))
{
return
ConstraintReferential
.
CASCADE
;
}
else
if
(
readIf
(
"RESTRICT"
))
{
return
ConstraintReferential
.
RESTRICT
;
}
else
{
return
null
;
}
}
private
Prepared
parseAlterTableAddConstraintIf
(
String
tableName
,
Schema
schema
)
{
String
constraintName
=
null
,
comment
=
null
;
boolean
ifNotExists
=
false
;
...
...
h2/src/main/org/h2/command/ddl/CreateView.java
浏览文件 @
8382475f
...
...
@@ -6,15 +6,21 @@
*/
package
org
.
h2
.
command
.
ddl
;
import
org.h2.command.Prepared
;
import
org.h2.command.dml.Query
;
import
org.h2.constant.ErrorCode
;
import
org.h2.engine.Constants
;
import
org.h2.engine.Database
;
import
org.h2.engine.DbObject
;
import
org.h2.engine.Session
;
import
org.h2.message.DbException
;
import
org.h2.schema.Schema
;
import
org.h2.table.Table
;
import
org.h2.table.TableView
;
import
java.util.ArrayList
;
import
java.util.List
;
/**
* This class represents the statement
* CREATE VIEW
...
...
@@ -28,6 +34,8 @@ public class CreateView extends SchemaCommand {
private
String
[]
columnNames
;
private
String
comment
;
private
boolean
recursive
;
private
boolean
orReplace
;
private
boolean
force
;
public
CreateView
(
Session
session
,
Schema
schema
)
{
super
(
session
,
schema
);
...
...
@@ -45,14 +53,49 @@ public class CreateView extends SchemaCommand {
this
.
select
=
select
;
}
public
void
setIfNotExists
(
boolean
ifNotExists
)
{
this
.
ifNotExists
=
ifNotExists
;
}
public
void
setSelectSQL
(
String
selectSQL
)
{
this
.
selectSQL
=
selectSQL
;
}
public
void
setColumnNames
(
String
[]
cols
)
{
this
.
columnNames
=
cols
;
}
public
void
setComment
(
String
comment
)
{
this
.
comment
=
comment
;
}
public
void
setOrReplace
(
boolean
orReplace
)
{
this
.
orReplace
=
orReplace
;
}
public
void
setForce
(
boolean
force
)
{
this
.
force
=
force
;
}
public
int
update
()
{
session
.
commit
(
true
);
Database
db
=
session
.
getDatabase
();
if
(
getSchema
().
findTableOrView
(
session
,
viewName
)
!=
null
)
{
Table
existingView
=
getSchema
().
findTableOrView
(
session
,
viewName
);
List
<
DependentView
>
dependentViewSql
=
new
ArrayList
<
DependentView
>();
if
(
existingView
!=
null
)
{
if
(
ifNotExists
)
{
return
0
;
}
throw
DbException
.
get
(
ErrorCode
.
VIEW_ALREADY_EXISTS_1
,
viewName
);
if
(
orReplace
&&
existingView
.
getTableType
().
equals
(
Table
.
VIEW
))
{
db
.
renameSchemaObject
(
session
,
existingView
,
db
.
getTempTableName
(
session
));
loadDependentViewSql
(
existingView
,
dependentViewSql
);
}
else
{
throw
DbException
.
get
(
ErrorCode
.
VIEW_ALREADY_EXISTS_1
,
viewName
);
}
}
int
id
=
getObjectId
();
String
querySQL
;
...
...
@@ -77,23 +120,73 @@ public class CreateView extends SchemaCommand {
// this is not strictly required - ignore exceptions, specially when using FORCE
}
db
.
addSchemaObject
(
session
,
view
);
if
(
existingView
!=
null
)
{
recreateDependentViews
(
db
,
existingView
,
dependentViewSql
,
view
);
}
return
0
;
}
public
void
setIfNotExists
(
boolean
ifNotExists
)
{
this
.
ifNotExists
=
ifNotExists
;
}
public
void
setSelectSQL
(
String
selectSQL
)
{
this
.
selectSQL
=
selectSQL
;
private
void
recreateDependentViews
(
Database
db
,
Table
existingView
,
List
<
DependentView
>
dependentViewSql
,
TableView
view
)
{
String
failedView
=
null
;
try
{
// recreate the dependent views
for
(
DependentView
dependentView
:
dependentViewSql
)
{
failedView
=
dependentView
.
viewName
;
if
(
force
)
{
execute
(
dependentView
.
createForceSql
,
true
);
}
else
{
execute
(
dependentView
.
createSql
,
true
);
}
}
// Delete the original view
db
.
removeSchemaObject
(
session
,
existingView
);
}
catch
(
DbException
e
)
{
db
.
removeSchemaObject
(
session
,
view
);
// Put back the old view
db
.
renameSchemaObject
(
session
,
existingView
,
viewName
);
// Try to put back the dependent views
for
(
DependentView
dependentView
:
dependentViewSql
)
{
execute
(
dependentView
.
createForceSql
,
true
);
}
throw
DbException
.
get
(
ErrorCode
.
CANNOT_DROP_2
,
e
,
existingView
.
getName
(),
failedView
);
}
}
public
void
setColumnNames
(
String
[]
cols
)
{
this
.
columnNames
=
cols
;
private
void
loadDependentViewSql
(
DbObject
tableOrView
,
List
<
DependentView
>
recreate
)
{
for
(
DbObject
view
:
tableOrView
.
getChildren
())
{
if
(
view
instanceof
TableView
)
{
recreate
.
add
(
new
DependentView
((
TableView
)
view
));
loadDependentViewSql
(
view
,
recreate
);
}
}
}
public
void
setComment
(
String
comment
)
{
this
.
comment
=
comment
;
// Class that holds a snapshot of dependent view information.
// We can't just work with TableViews directly because they become invalid
// when we drop the parent view.
private
class
DependentView
{
String
viewName
;
String
createSql
;
String
createForceSql
;
private
DependentView
(
TableView
view
)
{
this
.
viewName
=
view
.
getName
();
this
.
createSql
=
view
.
getCreateSQL
(
true
,
false
);
this
.
createForceSql
=
view
.
getCreateSQL
(
true
,
true
);
}
}
private
void
execute
(
String
sql
,
boolean
ddl
)
{
Prepared
command
=
session
.
prepare
(
sql
);
command
.
update
();
if
(
ddl
)
{
session
.
commit
(
true
);
}
}
}
h2/src/main/org/h2/command/ddl/DropView.java
浏览文件 @
8382475f
...
...
@@ -7,11 +7,14 @@
package
org
.
h2
.
command
.
ddl
;
import
org.h2.constant.ErrorCode
;
import
org.h2.constraint.ConstraintReferential
;
import
org.h2.engine.DbObject
;
import
org.h2.engine.Right
;
import
org.h2.engine.Session
;
import
org.h2.message.DbException
;
import
org.h2.schema.Schema
;
import
org.h2.table.Table
;
import
org.h2.table.TableView
;
/**
* This class represents the statement
...
...
@@ -21,6 +24,7 @@ public class DropView extends SchemaCommand {
private
String
viewName
;
private
boolean
ifExists
;
private
int
dropAction
=
ConstraintReferential
.
RESTRICT
;
public
DropView
(
Session
session
,
Schema
schema
)
{
super
(
session
,
schema
);
...
...
@@ -30,6 +34,10 @@ public class DropView extends SchemaCommand {
ifExists
=
b
;
}
public
void
setDropAction
(
int
dropAction
)
{
this
.
dropAction
=
dropAction
;
}
public
void
setViewName
(
String
viewName
)
{
this
.
viewName
=
viewName
;
}
...
...
@@ -46,6 +54,15 @@ public class DropView extends SchemaCommand {
throw
DbException
.
get
(
ErrorCode
.
VIEW_NOT_FOUND_1
,
viewName
);
}
session
.
getUser
().
checkRight
(
view
,
Right
.
ALL
);
if
(
dropAction
==
ConstraintReferential
.
RESTRICT
)
{
for
(
DbObject
child
:
view
.
getChildren
())
{
if
(
child
instanceof
TableView
)
{
throw
DbException
.
get
(
ErrorCode
.
CANNOT_DROP_2
,
viewName
,
child
.
getName
());
}
}
}
view
.
lock
(
session
,
true
,
true
);
session
.
getDatabase
().
removeSchemaObject
(
session
,
view
);
}
...
...
h2/src/main/org/h2/res/help.csv
浏览文件 @
8382475f
...
...
@@ -253,7 +253,7 @@ DROP USER [ IF EXISTS ] userName
","
Drops a user."
"Commands (DDL)","DROP VIEW","
DROP VIEW [ IF EXISTS ] viewName [RESTRICT | CASCADE ]
DROP VIEW [ IF EXISTS ] viewName [
RESTRICT | CASCADE ]
","
Drops a view, and all dependent views if the CASCADE clause is used."
"Commands (DDL)","TRUNCATE TABLE","
...
...
h2/src/main/org/h2/table/TableView.java
浏览文件 @
8382475f
...
...
@@ -152,11 +152,31 @@ public class TableView extends Table {
}
public
String
getDropSQL
()
{
return
"DROP VIEW IF EXISTS "
+
getSQL
();
return
getDropSQL
(
false
);
}
public
String
getDropSQL
(
boolean
cascade
)
{
StatementBuilder
buff
=
new
StatementBuilder
(
"DROP VIEW IF EXISTS "
);
buff
.
append
(
getSQL
());
if
(
cascade
)
{
buff
.
append
(
" CASCADE"
);
}
return
buff
.
toString
();
}
public
String
getCreateSQL
()
{
StatementBuilder
buff
=
new
StatementBuilder
(
"CREATE FORCE VIEW "
);
return
getCreateSQL
(
false
,
true
);
}
public
String
getCreateSQL
(
boolean
orReplace
,
boolean
force
)
{
StatementBuilder
buff
=
new
StatementBuilder
(
"CREATE "
);
if
(
orReplace
)
{
buff
.
append
(
"OR REPLACE "
);
}
if
(
force
)
{
buff
.
append
(
"FORCE "
);
}
buff
.
append
(
"VIEW "
);
buff
.
append
(
getSQL
());
if
(
comment
!=
null
)
{
buff
.
append
(
" COMMENT "
).
append
(
StringUtils
.
quoteStringSQL
(
comment
));
...
...
h2/src/main/org/h2/tools/SimpleResultSet.java
浏览文件 @
8382475f
差异被折叠。
点击展开。
h2/src/test/org/h2/test/TestAll.java
浏览文件 @
8382475f
...
...
@@ -60,6 +60,7 @@ import org.h2.test.db.TestTriggersConstraints;
import
org.h2.test.db.TestTwoPhaseCommit
;
import
org.h2.test.db.TestView
;
import
org.h2.test.db.TestViewAlterTable
;
import
org.h2.test.db.TestViewDropView
;
import
org.h2.test.jaqu.AliasMapTest
;
import
org.h2.test.jaqu.SamplesTest
;
import
org.h2.test.jaqu.UpdateTest
;
...
...
@@ -538,6 +539,7 @@ kill -9 `jps -l | grep "org.h2.test." | cut -d " " -f 1`
new
TestTwoPhaseCommit
().
runTest
(
this
);
new
TestView
().
runTest
(
this
);
new
TestViewAlterTable
().
runTest
(
this
);
new
TestViewDropView
().
runTest
(
this
);
// jaqu
new
AliasMapTest
().
runTest
(
this
);
...
...
h2/src/test/org/h2/test/db/TestViewDropView.java
0 → 100644
浏览文件 @
8382475f
/*
* Copyright 2004-2010 H2 Group. Multiple-Licensed under the H2 License,
* Version 1.0, and under the Eclipse Public License, Version 1.0
* (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package
org
.
h2
.
test
.
db
;
import
org.h2.constant.ErrorCode
;
import
org.h2.test.TestBase
;
import
java.sql.Connection
;
import
java.sql.ResultSet
;
import
java.sql.SQLException
;
import
java.sql.Statement
;
/**
* Test the impact of DROP VIEW statements on dependent views.
*/
public
class
TestViewDropView
extends
TestBase
{
private
Connection
conn
;
private
Statement
stat
;
/**
* Run just this test.
*
* @param a ignored
*/
public
static
void
main
(
String
...
a
)
throws
Exception
{
TestBase
.
createCaller
().
init
().
test
();
}
public
void
test
()
throws
Exception
{
deleteDb
(
"alter"
);
conn
=
getConnection
(
"alter"
);
stat
=
conn
.
createStatement
();
testDropViewDefaultBehaviour
();
testDropViewRestrict
();
testDropViewCascade
();
testCreateOrReplaceView
();
testCreateOrReplaceViewWithNowInvalidDependentViews
();
testCreateOrReplaceForceViewWithNowInvalidDependentViews
();
conn
.
close
();
deleteDb
(
"alter"
);
}
private
void
testDropViewDefaultBehaviour
()
throws
SQLException
{
createTestData
();
try
{
stat
.
execute
(
"drop view v1"
);
// Should fail because have dependencies
}
catch
(
SQLException
e
)
{
assertEquals
(
ErrorCode
.
CANNOT_DROP_2
,
e
.
getErrorCode
());
}
checkViewRemainsValid
();
}
private
void
testDropViewRestrict
()
throws
SQLException
{
createTestData
();
try
{
stat
.
execute
(
"drop view v1 restrict"
);
// Should fail because have dependencies
}
catch
(
SQLException
e
)
{
assertEquals
(
ErrorCode
.
CANNOT_DROP_2
,
e
.
getErrorCode
());
}
checkViewRemainsValid
();
}
private
void
testDropViewCascade
()
throws
SQLException
{
createTestData
();
stat
.
execute
(
"drop view v1 cascade"
);
try
{
stat
.
execute
(
"select * from v1"
);
fail
(
"Exception should be thrown - v1 should be deleted"
);
}
catch
(
SQLException
e
)
{
assertEquals
(
ErrorCode
.
TABLE_OR_VIEW_NOT_FOUND_1
,
e
.
getErrorCode
());
}
try
{
stat
.
execute
(
"select * from v2"
);
fail
(
"Exception should be thrown - v2 should be deleted"
);
}
catch
(
SQLException
e
)
{
assertEquals
(
ErrorCode
.
TABLE_OR_VIEW_NOT_FOUND_1
,
e
.
getErrorCode
());
}
try
{
stat
.
execute
(
"select * from v3"
);
fail
(
"Exception should be thrown - v3 should be deleted"
);
}
catch
(
SQLException
e
)
{
assertEquals
(
ErrorCode
.
TABLE_OR_VIEW_NOT_FOUND_1
,
e
.
getErrorCode
());
}
stat
.
execute
(
"drop table test"
);
}
private
void
testCreateOrReplaceView
()
throws
SQLException
{
createTestData
();
stat
.
execute
(
"create or replace view v1 as select a as b, b as a, c from test"
);
checkViewRemainsValid
();
}
private
void
testCreateOrReplaceViewWithNowInvalidDependentViews
()
throws
SQLException
{
createTestData
();
try
{
// v2 and v3 need more than just "c", so we should get an error
stat
.
execute
(
"create or replace view v1 as select c from test"
);
fail
(
"Exception should be thrown - dependent views need more columns than just 'c'"
);
}
catch
(
SQLException
e
)
{
assertEquals
(
ErrorCode
.
CANNOT_DROP_2
,
e
.
getErrorCode
());
}
// Make sure our old views come back ok
checkViewRemainsValid
();
}
private
void
testCreateOrReplaceForceViewWithNowInvalidDependentViews
()
throws
SQLException
{
createTestData
();
// v2 and v3 need more than just "c", but we want to force the creation of v1 anyway
stat
.
execute
(
"create or replace force view v1 as select c from test"
);
try
{
// now v2 and v3 are broken, but they still exist -- if there is any value to that...?
ResultSet
rs
=
stat
.
executeQuery
(
"select b from v2"
);
assertTrue
(
rs
.
next
());
assertEquals
(
1
,
rs
.
getInt
(
1
));
assertFalse
(
rs
.
next
());
}
catch
(
SQLException
e
)
{
assertEquals
(
ErrorCode
.
COLUMN_NOT_FOUND_1
,
e
.
getErrorCode
());
}
stat
.
execute
(
"drop table test"
);
}
private
void
createTestData
()
throws
SQLException
{
stat
.
execute
(
"create table test(a int, b int, c int)"
);
stat
.
execute
(
"insert into test(a, b, c) values (1, 2, 3)"
);
stat
.
execute
(
"create view v1 as select a as b, b as a from test"
);
// child of v1
stat
.
execute
(
"create view v2 as select * from v1"
);
// child of v2
stat
.
execute
(
"create view v3 as select * from v2"
);
}
private
void
checkViewRemainsValid
()
throws
SQLException
{
ResultSet
rs
=
stat
.
executeQuery
(
"select b from v1"
);
assertTrue
(
rs
.
next
());
assertEquals
(
1
,
rs
.
getInt
(
1
));
assertFalse
(
rs
.
next
());
rs
=
stat
.
executeQuery
(
"select b from v2"
);
assertTrue
(
rs
.
next
());
assertEquals
(
1
,
rs
.
getInt
(
1
));
assertFalse
(
rs
.
next
());
rs
=
stat
.
executeQuery
(
"select b from test"
);
assertTrue
(
rs
.
next
());
assertEquals
(
2
,
rs
.
getInt
(
1
));
assertFalse
(
rs
.
next
());
stat
.
execute
(
"drop table test"
);
ResultSet
d
=
conn
.
getMetaData
().
getTables
(
null
,
null
,
null
,
null
);
while
(
d
.
next
())
{
if
(!
d
.
getString
(
2
).
equals
(
"INFORMATION_SCHEMA"
))
{
fail
(
"Should have no tables left in the database, not: "
+
d
.
getString
(
2
)
+
"."
+
d
.
getString
(
3
));
}
}
}
}
h2/src/test/org/h2/test/test-1.2.txt
浏览文件 @
8382475f
...
...
@@ -5983,6 +5983,9 @@ SELECT * FROM CHILDREN_CLASS12;
> rows: 4
DROP VIEW CHILDREN_CLASS1;
> exception
DROP VIEW CHILDREN_CLASS1 CASCADE;
> ok
DROP VIEW CHILDREN_CLASS2;
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论