关于约束CASE语句和游标 我们的技术专家谈完整性时间和归属问题 我仔细阅读了《Oraclei 数据库概念手册(Oraclei Database Concepts Manual)》和你们的站点但对下述概念仍不明白 定义为可延迟(deferrable)的约束可以指定为 initially immediate(初始化立即执行)或 initially deferred(初始化延迟执行) 我知道什么是延迟约束但不明白什么叫初始化立即执行的可延迟约束和初始化延迟执行的可延迟约束请解释二者的区别还有这些约束有什么用途?这是通常容易混淆的问题我希望下面的例子能解释清楚初始化立即执行/延迟执行规定了在默认情况下应该如何执行约束 初始化立即执行在每条语句执行结束时检验约束 初始化延迟执行一直等到事务完成后(或者调用set constraint immediate语句时)才检验约束 来看下面的代码 SQL> create table t ( x int constraint check_x check ( x > ) deferrable initially immediate y int constraint check_y check ( y > ) deferrable initially deferred ) / Table created SQL> insert into t values ( ); row created SQL> commit; Commit complete 所以当两个约束同时满足时才能正确无误地插入行但是如果我试图插入违反CHECK_X约束(初始化立即执行的约束)的行则系统会立即检验约束并得到下面的结果 SQL> insert into t values ( ); insert into t values ( ) * ERROR at line : ORA: check constraint (OPS$TKYTECHECK_X) violated 由于CHECK_X是可延迟但初始化为立即执行的约束所以这一行立刻被拒绝了而CHECK_Y则不同它不仅是可延迟的而且初始化为延迟执行这就意味着直到我用COMMIT命令提交事务或将约束状态设置为立即执行时才检验约束 SQL> insert into t values ( ); row created 现在它是成功的(总之到目前为止是成功的)我将约束检验延迟到了执行COMMIT的时候 SQL> commit; commit * ERROR at line : ORA: transaction rolled back ORA: check constraint (OPS$TKYTECHECK_Y) violated 此时数据库将事务回滚因为违反约束导致了COMMIT语句的失败这些语句说明了初始化立即执行与初始化延迟执行约束之间的区别initially(初始化)部分指定Oracle什么时候会进行默认的约束检验是在语句结束时[immediate(立即执行)]还是在事务结束时[deferred(延迟执行)]我还要说明deferred(可延迟)子句有什么用我可以发出命令让所有可延迟的约束变为延迟执行的注意你也可以对一个约束使用该命令你不必让所有可延迟的约束都变为延迟执行的 SQL> set constraints all deferred; Constraint set SQL> insert into t values ( ); row created 由于将初始化立即执行的约束设置为延迟执行的模式这个语句似乎执行成功但是当我用COMMIT语句提交事务时看一下会发生什么 SQL> commit; commit * ERROR at line : ORA: transaction rolled back ORA: check constraint (OPS$TKYTECHECK_X) violated 事务提交失败并回滚因为在COMMIT语句之后对约束进行了检验相反我可以将初始化为延迟执行的约束变为立即执行的约束 SQL> set constraints all immediate; Constraint set SQL> insert into t values ( ); insert into t values ( ) * ERROR at line : ORA: check constraint (OPS$TKYTECHECK_Y) violated 前面在我提交前能执行的语句现在立即出了问题因为我手动修改了默认的约 束模式 延迟约束有哪些实际用处呢? 有很多它主要用于物化视图(快照)这些视图会使用延迟约束来进行视图刷新在刷新物化视图的过程中可能会破坏完整性而且将不能逐句检验约束但到执行COMMIT时数据完整性就没问题了而且能满足约束没有延迟约束物化视图的约束可能会使刷新过程不能成功进行 使用延迟约束的另一个普遍原因是当预测是否需要更新父/子关系中的主键时它有助于级联更新如果你将外键设为可延迟但初始化为立即执行那么你就可以 将所有约束设置为可延迟 将父键更新为一个新值至此子关系的完整性约束不会被验证 将子外键更新为这个新值 COMMIT只要所有受更新影响的子记录都指向现有的父记录这条命令就能成功执行 如果没有延迟约束这一更新过程将极为艰难参见/~tkyte/update_cascade/l中给出的没有这一特性时进行级联更新所必需的示例代码! 此外你可以在各种多语句事务中使用延迟约束这些事务在处理的过程中需要暂时破坏完整性但最后它们都会物归原样 如何计算时间 你是如何计算第一页中AGE列显示的时间的?我之所以问这个问题是因为我看到它有多种格式如个月小时年个小时等等我是Oracle新手想知道你们在使用哪种日期计算法 我就是使用Oraclei第版(版)中介绍的使用已久但很好用的CASE语句 Select case when sysdatetimestamp < / then round(**(sysdatetimestamp)) || minutes old when sysdatetimestamp < then round(*(sysdatetimestamp)) || hours old when sysdatetimestamp < then trunc(sysdatetimestamp) || days old when sysdatetimestamp < then trunc((sysdatetimestamp)/) || weeks old when sysdatetimestamp < then round(months_between (sysdatetimestamp)) || months old else round(months_between (sysdatetimestamp)/) || years old end age 如果你想在Oraclei的PL/SQL中使用CASE语句则会出现一个错误消息因为PL/SQL语法分析程序不识别CASE语句(请注意在Oraclei不存在这样的问题)为了避开Oraclei的限制你可以 将CASE语句隐藏在视图当中并用PL/SQL来查询视图 使用嵌套的DECODE语句来代替CASE语句 我本人愿意使用视图但读者Martin Burbridge在 网站上公布了下面这段DECODE代码 decode(sign(sysdatetimestamp/) round(**(sysdatetimestamp)) || minutes old decode(sign(sysdatetimestamp ) round(*(sysdatetimestamp)) || hours old decode(sign(sysdatetimestamp) trunc(sysdatetimestamp) || days old decode(sign(sysdatetimestamp) trunc((sysdatetimestamp)/) || weeks old decode(sign(sysdatetimestamp) round(months_between (sysdatetimestamp)) || months old round(months_between (sysdatetimestamp)/ ) || years old ))))) age 它与CASE语句的功能完全相同只是不太明显 文件放在哪? 我正在考虑为一个应用程序设计些选项利用它用户可以上传和存储可供他人下载的文档文档可以是平均大小为K的Microsoft Word文档最初需要(从CD)移植到个文档当使用该应用程序时存储数量会增加到大约个文档浏览器前端是用于上传和下载的PL/SQL插件(PL/SQL cartridge)页面一开始会有到人几乎同时访问该应用程序两周内每天将有人访问(分散访问) 文档本身在数据库中作为BLOB存储 从使用方面考虑你觉得这样的选项好吗?它会过多占用系统全局区(SGA)吗?考虑到应用程序的需求以及前端(基于浏览器)除了保存为BLOB还有没有其他选择如文件系统? 我什么都存在数据库里就是这样如果数据就是你的一切无论它们有什么样的值事实上都要放到数据库中在那里数据可以得到专业化的管理备份恢复而且安全除了这些实实在在的好处你还可以索引及搜索文档(诚然用文件系统也可以做这些但在索引和文档之间不存在完整性)在数据库中你可以转换文档格式(例如上传一个DOC文件而显示为HTML格式)你的数据是完全集成的安全的有备份的而且随时供你使用 在Oracle公司内部我们将一个几千吉字节的数据库作为整个公司的一个单一的文件服务器公司所有文档都存在那里存在这样一个单一的地方可以对这些文档进行备份搜索建立索引和访问在常规的文件系统中管理成千上万的文档是不可能的 |