#
第二十五章 SQL命令 CREATE VIEW(二) # 通过视图更新 视图可用于更新视图所基于的表。可以通过视图插入新行,更新通过视图看到的行中的数据,以及删除通过视图看到的行。如果`CREATE VIEW`语句指定了此功能,则可以为视图发出`INSERT`、`UPDATE`和`DELETE`语句。要允许通过视图进行更新,请在定义视图时指定`WITH CHECK`选项(默认值)。 注意:如果视图基于分片表,则不能通过`WITH CHECK OPTION`视图进行`INSERT`、`UPDATE`或`DELETE`操作。 尝试这样做会导致一个`SQLCODE -35`,其中`%msg INSERT/UPDATE/DELETE not allowed for view (sample.myview) based on sharded table with check option conditions`。 若要防止通过视图进行更新,请指定`WITH READ ONLY`。尝试通过使用`READ ONLY`创建的视图执行插入、更新或删除操作会生成`SQLCODE-35`错误。 要通过视图进行更新,必须具有要更新表或视图的适当权限,如`GRANT`命令所指定。 通过视图更新受以下限制: - 该视图不能是投影为视图的类查询。 - 视图的类不能包含类参数`READONLY=1`。 - 视图的SELECT语句不能包含`DISTINCT`、`TOP`、`GROUP BY`或`HAVING`子句,也不能是`UNION`的一部分。 - 视图的`SELECT`语句不能包含子查询。 - 视图的`SELECT`语句只能列出作为列引用的值表达式。 - 视图的`SELECT`语句只能有一个表引用;它不能在`SELECT-LIST`或`WHERE`子句中包含`FROM`子句、联接语法或箭头语法。表引用必须指定可更新的表或可更新的视图。 `WITH CHECK OPTION`子句导致`INSERT`或`UPDATE`操作根据视图定义的`WHERE`子句验证结果行。这可确保插入或修改的行是派生视图表格的一部分。有两个可用的检查选项: - `WITH LOCAL CHECK OPTION`-仅检查`INSERT`或`UPDATE`语句中指定的视图的`WHERE`子句。 - `WITH CASCADED CHECK OPTION`-检查`INSERT`或`UPDATE`语句中指定的视图的`WHERE`子句和所有基础视图。这将覆盖这些基础视图中的任何`WITH LOCAL CHECK OPTION`子句。对于所有可更新的视图,建议使用`WITH CASCADED CHECK`选项。 如果指定`WITH CHECK OPTION`,则`CHECK`选项默认为`CASCADED`。关键字`CASCADE`是`CASCADED`的同义词。 如果插入操作因检查选项验证失败(如上所述), IRIS将发出`SQLCODE-136`错误。 如果更新操作因检查选项验证(如上所述)而失败,则 IRIS会发出`SQLCODE-137`错误。 # 示例 下面的示例从`PhoneBook`表中创建了名为`“CityPhoneBook”`的视图: ```sql CREATE VIEW CityPhoneBook AS SELECT Name FROM PhoneBook WHERE City='Boston' ``` 下面的示例从`Guides`表中创建了一个名为`“GuideHistory”`的视图。 它列出了所有的`Title`以及这个人是否已经退休: ```sql CREATE VIEW GuideHistory AS SELECT Guides, Title, Retired, Date_Retired FROM Guides ``` 下面的嵌入式SQL示例创建表`MyTest`,然后为该表创建一个视图`MyTestView`,该视图从`MyTest`中选择一个字段: ```java ClassMethod CreateView1() { d $SYSTEM.Security.Login("_SYSTEM","SYS") &sql(DROP TABLE Sample.MyTest) &sql(DROP VIEW Sample.MyTestView) CreateTable &sql(CREATE TABLE Sample.MyTest ( TestNum INT NOT NULL, FirstWord CHAR (30) NOT NULL, LastWord CHAR (30) NOT NULL, CONSTRAINT MyTestPK PRIMARY KEY (TestNum) ) ) if SQLCODE = 0 { w !,"创建表" } else { w "创建表错误 SQLCODE=",SQLCODE } CreateView &sql( CREATE VIEW Sample.MyTestView AS SELECT FirstWord FROM Sample.MyTest WITH CASCADED CHECK OPTION ) if SQLCODE = 0 { w !,"创建视图" } else { w "创建视图错误 SQLCODE=",SQLCODE } } ``` 下面的嵌入式SQL示例创建视图`MyTestView`,该视图从`MyTest`中选择两个字段。此视图的`SELECT`查询包含一个`TOP`子句和一个`ORDER BY`子句: ```java ClassMethod CreateView2() { d $SYSTEM.Security.Login("_SYSTEM","SYS") &sql(DROP TABLE Sample.MyTest) &sql(DROP VIEW Sample.MyTestView) CreateTable &sql( CREATE TABLE Sample.MyTest ( TestNum INT NOT NULL, FirstWord CHAR (30) NOT NULL, LastWord CHAR (30) NOT NULL, CONSTRAINT MyTestPK PRIMARY KEY (TestNum) ) ) if SQLCODE = 0 { w !,"创建表" } else { w "创建表错误 SQLCODE=",SQLCODE } CreateView &sql( CREATE VIEW Sample.MyTestView AS SELECT TOP ALL FirstWord,LastWord FROM Sample.MyTest ORDER BY LastWord ) if SQLCODE = 0 { w !,"创建视图" } else { w "创建视图错误 SQLCODE=",SQLCODE } } ``` 下面的示例从三个表(`Proj`、`Staff`和`Works`)创建了一个名为“`StaffWorksDesign`”的视图。 列`Name`、`Cost`和`Project`提供数据。 ```sql CREATE VIEW StaffWorksDesign (Name,Cost,Project) AS SELECT EmpName,Hours*2*Grade,PName FROM Proj,Staff,Works WHERE Staff.EmpNum=Works.EmpNum AND Works.PNum=Proj.PNum AND PType='Design' ``` 下面的例子通过使用`UNION`从`b.table2`和`a.table1`中选择,创建了一个名为“`v_3`”的视图: ```sql CREATE VIEW v_3(fvarchar) AS SELECT DISTINCT * FROM (SELECT fVARCHAR2 FROM b.table2 UNION ALL SELECT fVARCHAR1 FROM a.table1) ```