Oracle8i/9i数据库基础


Oracle8i/9i 数据库基础 ( 初稿) 赵元杰 2003 年 01 月 4 日 2 前 言 本讲稿(ORACLE8i 数据库基础)是作者在多年的工作和授课中的总结,主要包括两个部 分,第一部分是 ORACLE SQL*PLUS基础,主要讲述 ORACLE 应用系统设计的基本知识和 给出一些有用的实例;第二部分是介绍 ORACLE PL/SQL 知识,主要讲述 ORACLE 数据库 PL/SQL 程序设计所用到基本知识,这部分给出进行应用设计所必需的基础知识。这两部分 的内容都尽可能做到内容简洁而全面。特点是,1.用简单明了的语句对解释各个部分的内容, 省去一些理论性的解释;2.给出作者在应用设计和开发中的一些具体的例子,为软件人员提 供一些借鉴,省去查阅大量资料的时间。3.给出了许多资料所没有提供的一些使用技巧,如 导出触发器等。总之,内容基本上包括当前 Oracle8I 的最新内容。同时也覆盖了最新的 ORACLE8i OCP 培训大纲的内容。不仅包含 ORACLE 程序设计人员、DBA 所必须掌握的知 识,而且还含盖了系统分析员所要求的内容。与本书(讲稿)相伴的还有《Oracle8i/9i 初级 数据库管理》和《Oracle8i/9i 高级数据库管理》。 全书内容简练实用,可作为 ORACLE 数据库管理人员参考,也可作为应用开发人员 和系统分析与设计人员以及大学计算机专业教学的参考资料。由于作者水平所限,加之 ORACLE 的产品与内容的浩瀚,在资料的整理与收集中可能有不少错误和不妥之处,希望读 者给予批评制正。 3 目 录 第一部分 Oracle SQL*PLUS基础...............................................................................................23 第一章 Oracle 数据库基础...........................................................................................................23 §1.1 理解关系数据库系统(RDBMS)............................................................................23 §1.1.1 关系模型 ............................................................................................................23 §1.1.2 Codd 十二法则...................................................................................................24 §1.2 关系数据库系统(RDBMS)的组成........................................................................24 §1.2.1 RDBMS 内核 ....................................................................................................24 §1.2.2 数据字典概念 ....................................................................................................25 §1.3 SQL、SQL*Plus 及 PL/SQL.....................................................................................25 §1.3.1 SQL 和 SQL*PLUS的差别...............................................................................25 §1.3.2 PL/SQL 语言 ......................................................................................................27 §1.4 登录到 SQL*PLUS.......................................................................................................27 §1.4.1 UNIX 环境 .........................................................................................................27 §1.4.2 Windows NT 和 WINDOWS/2000 环境 ...........................................................29 §1.5 常用SQL*PLUS 附加命令简介 .................................................................................32 §1.5.1 登录到 SQL*PLUS............................................................................................32 §1.5.2 EXIT 和 QUIT....................................................................................................32 §1.5.3 DESCRIBE(显示表、视图结构).......................................................................33 §1.5.4 LIST(列出)命令 .................................................................................................33 §1.5.5 Change(替换字符串)命令..................................................................................34 §1.5.6 Append(追加字符串)命令............................................................................34 §1.5.7 Save 保存当前缓冲区命令到文件....................................................................35 §1.5.8 GET 将命令文件读到缓冲区............................................................................35 §1.5.9 SPOOL 将信息记录到文件中...........................................................................36 §1.5.10 再运行当前缓冲区的命令...............................................................................36 §1.6 常用数据字典简介 .......................................................................................................37 §1.7 ORACLE 数据类型 ......................................................................................................38 §1.8 SQL 语句基础..............................................................................................................44 §1.8.1 SQL 语句所用符号..........................................................................................44 §1.8.2 简单 select 查询 ..............................................................................................45 §1.9 伪列及伪表 .................................................................................................................46 §1.10 使用SQL Worksheet工作 ..........................................................................................46 第二章 查询基础 ............................................................................................................................50 §2.1 SELECT 语句..............................................................................................................50 §2.2 SQL 中的单记录函数.................................................................................................50 §2.2.1 单记录字符函数...............................................................................................50 §2.2.2 单记录数字函数...............................................................................................56 §2.2.3 单记录日期函数...............................................................................................62 §2.2.4 单记录转换函数...............................................................................................65 §2.2.5 其它的单记录函数...........................................................................................68 §2.3 SQL 中的组函数.........................................................................................................73 5 §3.4.1 建立外部键 ......................................................................................................110 §3.4.2 修改外部键 ......................................................................................................112 §3.4.3 删除外部键 ......................................................................................................112 §3.5 索引 ...........................................................................................................................112 §3.5.1 建立索引 ..........................................................................................................112 §3.5.2 修改索引 ..........................................................................................................114 §3.5.3 删除索引 ..........................................................................................................115 §3.6 新索引类型 .................................................................................................................115 §3.6.1 基于函数的索引...............................................................................................115 §3.6.2 反向键索引 ......................................................................................................117 §3.6.3 索引组织表 ......................................................................................................117 §3.7 抽象数据类型的使用 .................................................................................................118 §3.8 大数据类型的使用 .....................................................................................................119 §3.8.1 可用数据类型 ..................................................................................................119 §3.8.2 为LOB 数据类型指定存储.............................................................................120 §3.8.3 操作和检索 LOB 数据.....................................................................................121 §3.9 表和索引有关的数据字典..........................................................................................124 §3.9.1 表和索引数据字典...........................................................................................124 §3.9.2 数据字典查询例子...........................................................................................125 第四章 视图、同义词和序列 ......................................................................................................128 §4.1 视图 .............................................................................................................................128 §4.1.1 使用视图来修改表中数据...............................................................................128 §4.1.2 创建一个新视图...............................................................................................128 §4.1.3 删除一个视图 ..................................................................................................130 §4.1.4 改变视图 ..........................................................................................................131 §4.2 实体视图(MATERIALIZED VIEW)..........................................................................131 §4.2.1 创建实体视图 ..................................................................................................131 §4.2.2 创建实体视图日志...........................................................................................137 §4.2.3 修改实体视图 ..................................................................................................139 §4.2.4 修改实体视图日志...........................................................................................141 §4.2.45 实体视图完整例子.........................................................................................142 §4.3 序号(sequence)............................................................................................................146 §4.3.1 建立序号 ..........................................................................................................146 §4.3.2 修改序号 ..........................................................................................................147 §4.3.3 使用序号 ..........................................................................................................147 §4.3.4 删除序号 ..........................................................................................................147 §4.4 同义词 .........................................................................................................................148 §4.4.1 建立同义词 ......................................................................................................148 §4.4.2 删除同义词 ......................................................................................................149 §4.5 视图、同义词和序列有关的数据字典......................................................................149 第五章 簇与分区 ..........................................................................................................................150 §5.1 簇( cluster )..................................................................................................................150 §5.1.0 簇概念 ..............................................................................................................150 §5.1.1 建立簇 ..............................................................................................................152 4 §2.3.1 多记录组函数...................................................................................................73 §2.3.2 带 GROUP BY 的计算................................................................................75 §2.3.3 用 HAVING 来限制分组的计算 .................................................................75 §2.4 控制和格式化输出 .....................................................................................................76 §2.4.1 用 ORDER BY 子句来对结果进行排序.......................................................76 §2.4.2 用 BREAK 命令 来对结果进行排列...........................................................76 §2.4.3 用 COMPUTE 命令对结果进行格式化........................................................79 §2.5 配置会话环境 .............................................................................................................82 §2.5.1 ARRAYSIZE(取回的行数).........................................................................82 §2.5.2 AUTOCOMMIT(自动提交)............................................................................83 §2.5.3 LINESIZE(行显示宽度)..................................................................................83 §2.5.4 LONG(长类型显示字节数).............................................................................83 §2.5.5 PAGESIZE(页行数).........................................................................................83 §2.5.6 PAUSE(暂停)....................................................................................................84 §2.5.7 SPACE(列间空格)............................................................................................84 §2.5.8 Termout (启/停屏幕显示)................................................................................84 §2.5.9 ECHO (启/停命令显示)...................................................................................84 §2.5.10 TRANSACTION (启动事务)...........................................................................85 §2.5.11 SHOW ALL(列出所有参数)............................................................................85 §2.6 格式化输出 .................................................................................................................87 §2.6.1 一般数据的格式化输出...................................................................................87 §2.6.2 日期的格式化输出...........................................................................................88 §2.7 加标题...........................................................................................................................89 §2.8 建立简单报告 ...............................................................................................................90 §2.9 输入变量 .......................................................................................................................91 第三章 表及索引的定义操作 ......................................................................................................94 §3.1 建立表结构 ...................................................................................................................94 §3.1.1 建立表结构命令.................................................................................................94 §3.1.2 建立表结构例子.................................................................................................96 §3.1.3 建立临时表结构.................................................................................................97 §3.3 修改表结构 ...................................................................................................................98 §3.3.1 修改表结构命令.................................................................................................98 §3.3.2 修改表结构例子.................................................................................................99 §3.3.3 删除表结构 ......................................................................................................101 §3.3.4 使用CHECK 作限制约束...............................................................................101 §3.3.5 使用UNRECOVERABLE 创建表..................................................................102 §3.3.6 将表移动到新的数据段或新的表空间...........................................................102 §3.3.7 手工分配表的存储空间...................................................................................104 §3.3.8 标记不使用的列和删除不使用的列...............................................................104 §3.3 主键.............................................................................................................................106 §3.3.1 创建主键 ..........................................................................................................106 §3.3.2 改变主键 ..........................................................................................................109 §3.3.3 删除主键 ..........................................................................................................109 §3.4 外部键.........................................................................................................................110 6 §5.1.2 改变簇 ..............................................................................................................155 §5.1.3 删除簇 ..............................................................................................................155 §5.1.4 删除簇索引 ......................................................................................................156 §5.1.5 收集簇信息 ......................................................................................................156 §5.2 分区.............................................................................................................................158 §5.2.1 分区的优点......................................................................................................158 §5.2.2 分区的方法......................................................................................................159 §5.2.3 创建表的分区 ..................................................................................................159 §5.2.3 创建索引的分区...............................................................................................164 §5.2.4 维护表分区和索引分区...................................................................................167 §5.3 簇与分区有关的数据字典..........................................................................................169 §5.3.1 分区、簇数据字典列表...................................................................................169 §5.3.2 基本的分区、簇信息查询...............................................................................169 第六章 使用SQL 进行数据操作..............................................................................................170 §6.1 INSERT 操作...............................................................................................................170 §6.1.1 用文字插入操作...............................................................................................171 §6.1.2 用子查询插入操作...........................................................................................171 §6.2 UPDATE 操作.............................................................................................................172 §6.2.1 用文字更新操作...............................................................................................173 §6.2.2 用查询更新操作...............................................................................................173 §6.2.3 用相关子查询更新操作...................................................................................174 §6.3 DETELE 操作 .............................................................................................................174 §6.3.1 用delete 删除全部记录的操作.......................................................................174 §6.3.2 用delete 有条件删除部分记录.......................................................................175 §6.3.3 用delete 分段删除大量记录...........................................................................175 §6.4 insert、delete 及 update 的提交和撤消.....................................................................176 §6.4.1 自动提交的设置...............................................................................................176 §6.4.2 保留点和撤消 ..................................................................................................177 第七章 复杂查询语句的使用 ....................................................................................................180 §7.1 复杂查询语句的使用 ...............................................................................................180 §7.1.1 相关子查询 ......................................................................................................180 §7.1.2 外连接 ..............................................................................................................180 §7.1.3 自我连接 ..........................................................................................................181 §7.1.4 UNION,INTERSECT 及 MINUS....................................................................182 §7.2 创建复杂的视图 .........................................................................................................183 §7.2.1 分组视图 ..........................................................................................................183 §7.2.2 合计视图 ..........................................................................................................183 §7.2.3 组合视图 ..........................................................................................................184 §7.3 家族树 .........................................................................................................................184 §7.3.1 排除单一体和分枝...........................................................................................184 §7.3.2 遍历至根 ..........................................................................................................185 §7.4 在from 中使用视图...................................................................................................187 第八章 一些高级的用法 ............................................................................................................188 §8.1 关于DECODE............................................................................................................188 7 §8.1.1 DECODE 中的 if-then-else 逻辑 ....................................................................188 §8.1.2 DECODE 的简单例子 ....................................................................................188 §8.1.3 DECODE 实现表的转置 .................................................................................189 §8.2 关于访问远程数据库 .................................................................................................192 §8.2.1 数据库链接 ......................................................................................................192 §8.2.2 使用同义词获得本地透明...............................................................................193 §8.2.3 在视图中使用 user 伪列..................................................................................194 §8.2.4 使用COPY 功能..............................................................................................195 §8.2.5 管理Oracle 名称服务器..................................................................................196 §8.3 关于上下文的使用 .....................................................................................................196 §8.3.1 设置上下文选项...............................................................................................196 §8.3.2 为上下文查询设置表.......................................................................................197 §8.3.3 优化文本索引 ..................................................................................................199 §8.4 关于维数(DIMENSION).......................................................................................199 §8.4.1 CREATE DIMENSION 语法...........................................................................200 §8.4.2 创建维的例子 ..................................................................................................201 第九章 安全管理........................................................................................................................203 §9.1 CREATE USER 命令 .................................................................................................203 §9.2 建立用户 .....................................................................................................................204 §9.2.1 外部验证(Authenticated )用户 ..................................................................204 §9.2.2 全局(Globally)验证用户-企业验证.................................................................204 §9.3 ALTER USER 命令....................................................................................................205 §9.4 DROP USER 命令......................................................................................................205 §9.5 GRANT 命令与 REVOKE 命令...............................................................................206 §9.5.1 GRANT 命令...................................................................................................206 §9.5.2 REVOKE 命令 ................................................................................................206 §9.6 权限和角色 .................................................................................................................207 §9.6.1 建立角色 ..........................................................................................................207 §9.6.2 给角色授权 ......................................................................................................208 §9.6.3 授权角色给用户...............................................................................................209 §9.7 有关的数据字典 .........................................................................................................209 §9.7.1 与用户、角色与权限有关的数据字典...........................................................209 §9.7.2 查询数据字典信息...........................................................................................209 第十章 其它一些常见问题及技巧...............................................................................................212 §10.1 一些常见问题 ...........................................................................................................212 §10.1.1 Oracle 与 2000 年问题...................................................................................212 §10.1.2 如何正确插入日期数据.................................................................................213 §10.1.3 在查询中只返回满足条件的部分记录.........................................................214 §10.1.4 快速大量删除数据 Truncate..........................................................................215 §10.1.5 Rowid 的使用.................................................................................................215 §10.1.6 在查询中不让记录被更新.............................................................................217 §10.1.7 EXCEPTIONS(违反完整性)问题 ............................................................217 §10.1.8 Not in 和 Not Exists..................................................................................218 §10.1.9 关于 COPY 命令...........................................................................................218 8 §10.1.10 列值为NULL 情形的处理..........................................................................219 §10.1.11 使用 product_user_file来限制用户使用产品............................................220 §10.2 常用技巧 ...................................................................................................................221 §10.2.1 long 类型的查询 ...........................................................................................222 §10.2.2 如何确定执行时间.........................................................................................222 §10.2.3 如何终止用户会话.........................................................................................222 §10.2.4 用TRANSLATE对数据加密和解密............................................................224 §10.2.5 如何用查询来修改数据.................................................................................225 §10.2.6 如何产生创建用户的脚本.............................................................................226 §10.2.7 如何产生创建表结构的脚本.........................................................................227 §10.2.8 如何产生创建视图的脚本.............................................................................229 §10.2.9 如何产生创建序号的脚本.............................................................................229 §10.2.10 如何为用户创建公共同义词.......................................................................229 第二部分 Oracle PL/SQL 基础...................................................................................................231 第十一章 PL/SQL 程序设计简介 .............................................................................................231 §11.1 概述...........................................................................................................................231 §11.2 SQL 与 PL/SQL.........................................................................................................231 §11.2.1 什么是 PL/SQL?...........................................................................................231 §11.2.1 PL/SQL 的好处 ............................................................................................232 §11.2.1.1 有利于客户/服务器环境应用的运行.................................................232 §11.2.1.2 适合于客户环境..................................................................................232 §11.2.1.3 客户及服务器端的好处......................................................................232 §11.2.2 PL/SQL 可用的 SQL 语句............................................................................233 §11.3 运行PL/SQL 程序 ..................................................................................................233 §11.4 PL/SQL 内置包 .......................................................................................................234 第十二章 PL/SQL 块结构和组成元素 ........................................................................................235 §12.1 PL/SQL 结构...........................................................................................................235 §12.2 PL/SQL 块...............................................................................................................236 §12.3 标识符.....................................................................................................................236 §12.4 PL/SQL 变量类型 ..................................................................................................237 §12.4.1 变量类型 ........................................................................................................237 §12.4.2 复合类型(记录和表).................................................................................238 §12.4.3 使用%ROWTYPE..........................................................................................240 §12.4.4 LOB 类型 .......................................................................................................240 §12.4.5 用户定义的子类型.........................................................................................241 §12.4.6 数据类型的转换.............................................................................................243 §12.5 运算符和表达式(数据定义)...................................................................................243 §12.5.1 关系运算符....................................................................................................243 §12.5.2 一般运算符 ....................................................................................................244 §12.5.3 逻辑运算符 ....................................................................................................244 §12.6 变量赋值 .................................................................................................................245 §12.6.1 字符及数字运算特点.....................................................................................245 §12.6.2 Boolean 赋值 .................................................................................................245 §12.6.3 数据库赋值 ....................................................................................................245 9 §12.6.4 可转换的类型赋值.........................................................................................246 §12.7 变量作用范围以可见性 ...........................................................................................248 §12.8 注释...........................................................................................................................248 §12.9 简单例子 ...................................................................................................................249 §12.9.1 简单数据插入例子.......................................................................................249 §12.9.2 简单数据删除例子.......................................................................................249 第十三章 PL/SQL 处理流程 ........................................................................................................250 §13.1 条件语句 ...................................................................................................................250 §13.2 循环...........................................................................................................................251 §13.3 标号和 GOTO...........................................................................................................254 §13.4 NULL 语句...............................................................................................................255 第十四章 光标的使用 ..................................................................................................................255 §14.1 光标概念 .....................................................................................................................255 §14.1.1 处理显式光标 ..................................................................................................255 §14.1.2 处理隐式光标 ..................................................................................................257 §14.2 光标循环 .....................................................................................................................258 §14.2.1 简单循环 ..........................................................................................................258 §14.2.2 WHILE 循环......................................................................................................259 §14.2.3 光标 FOR 循环...........................................................................................260 §14.2.4 关于 NO_DATA_FOUND 和%NOTFOUND..................................................260 §14.2.5 SELECT FOR UPDATE 光标..................................................................261 §14.3 光标变量 .....................................................................................................................262 §14.3.1 声明光标变量 ..................................................................................................262 §14.3.2 为光标变量分配存储空间...............................................................................262 §14.3.3 打开光标变量 ..................................................................................................262 §14.3.4 关闭光标变量 ..................................................................................................262 §14.3.5 光标变量例子 ..................................................................................................263 §14.3.6 光标变量 ..........................................................................................................265 第十五章 错误处理 ......................................................................................................................267 §15.1 异常处理概念 .............................................................................................................267 §15.1.1 预定义的异常处理...........................................................................................267 §15.1.2 触发异常情态 ..................................................................................................268 §15.1.3 处理异常情态 ..................................................................................................269 §15.1.4 用户定义的异常处理.....................................................................................270 §15.2 异常情态传播 .............................................................................................................271 §15.2.1 在执行部分引发异常情态...............................................................................271 §15.2.2 在声明部分引发异常情态...............................................................................272 §15.3 异常处理编程 .............................................................................................................273 §15.4 在 PL/SQL 中使用 sqlcode,sqlerrm.......................................................................273 第十六章 存储过程和函数 ..........................................................................................................276 §16.1 引言...........................................................................................................................276 §16.2 存储过程...................................................................................................................276 §16.2.1 创建过程 ........................................................................................................276 §16.2.2 使用过程........................................................................................................278 10 §16.2.3 开发存储过程步骤.........................................................................................279 §16.2.3.1 编辑存储过程源码..............................................................................279 §16.2.3.2 对存储过程程序进行解释..................................................................279 §16.2.3.3 调试源码直到正确..............................................................................279 §16.2.3.4 授权执行权给相关的用户或角色......................................................279 §16.2.4 与存储过程相关数据字典.............................................................................280 §16.3 创建函数 ...................................................................................................................281 §16.4 过程和函数中的例外处理........................................................................................282 §16.4.1 使用系统定义的例外处理.............................................................................282 §16.4.1.1 没有例外处理的缺点..........................................................................283 §16.4.1.2 使用预定义的例外处理......................................................................283 §16.4.2 使用用户定义的例外处理+..........................................................................286 §16.4.2.1 定义的用户例外处理..........................................................................286 §16.4.2.2 使用户EXCEPTION_INIT 处理.......................................................286 §16.4.2.3 使用户raise_application_error处理...................................................286 第十七章 创建包和使用包 ..........................................................................................................287 §17.1 引言...........................................................................................................................287 §17.2 包的定义 ...................................................................................................................288 §17.3 包的开发步骤 ...........................................................................................................289 §17.4 包的头部说明 ...........................................................................................................289 §17.5 包体的说明 ...............................................................................................................290 §17.6 删除过程、函数和包 ...............................................................................................293 §17.7 包的管理 ...................................................................................................................293 §17.7.1 包有关的数据字典.........................................................................................293 §17.7.2 包中无效对象的查询和编译.........................................................................294 §17.7.3 包源代码的导出.............................................................................................296 第十八章 触发器 ..........................................................................................................................297 §18.1 触发器类型 ...............................................................................................................297 §18.1.1 DML 触发器......................................................................................................297 §18.1.2 替代触发器 ......................................................................................................298 §18.1.3 系统触发器 ......................................................................................................298 §18.2 创建触发器 ...............................................................................................................298 §18.2.1 创建 DML 触发器............................................................................................299 §18.2.2 创建替代(Instead_of)触发器...........................................................................300 §18.2.3 创建系统触发器...............................................................................................300 §18.2.4 触发器触发次序...............................................................................................302 §18.2.5 使用触发器谓词...............................................................................................302 §18.3 删除和使能触发器 ...................................................................................................303 §18.4 创建触发器的限制 ...................................................................................................304 §18.5 变异表 .........................................................................................................................305 §18.5.1 变异表典型例子...............................................................................................307 §18.5.2 变异表错误的处理...........................................................................................308 §18.6 触发器数据字典与管理 ...........................................................................................309 §18.6.1 触发器数据字典.............................................................................................309 11 §18.6.2 无效触发器的编译.........................................................................................310 第十九章 外部存储过程 ..............................................................................................................311 §19.1 什么是外部例程 .........................................................................................................311 §19.2 C外部例程................................................................................................................311 §19.2.1 调用步骤 ........................................................................................................312 §19.2.2 参数映射( 转换)............................................................................................317 第二十章 会话间通信 ..................................................................................................................319 §20.1 DBMS_PIPE..............................................................................................................319 §20.1.1 发送消息 ..........................................................................................................319 §20.1.2 接收消息 ..........................................................................................................320 §20.1.3 示例 ..................................................................................................................321 §20.2 DBMS_ALERT.........................................................................................................340 §20.2.1 使用警告........................................................................................................341 §20.2.2 警告所用的各个过程.....................................................................................341 §20.2.3 警告例子........................................................................................................342 §20.3 DBMS_PIPE 和 DBMS_ALERT............................................................................343 第二十一章 数据库作业和文件 I/O............................................................................................344 §21.1 数据库作业 ...............................................................................................................344 §21.1.1 后台进程 ...........................................................................................................344 §21.1.2 运行作业 ...........................................................................................................344 §21.1.3 失效作业 ...........................................................................................................346 §21.1.4 删除作业 ...........................................................................................................347 §21.1.5 修改作业参数 ...................................................................................................348 §21.1.6 与作业参数有关数据字典................................................................................350 §21.2 文件I/O.....................................................................................................................350 §21.2.1 安全性 ..............................................................................................................351 §21.2.2 打开和关闭文件...............................................................................................351 §21.2.3 文件输出 ...........................................................................................................353 §21.2.3 文件输入 ...........................................................................................................354 §21.2.4 文件操作例子 ...................................................................................................354 第二十二章 在 PL/SQL 使用 SQL 语句.....................................................................................355 §22.1 在 PL/SQL 使用 DML 语句 .......................................................................................355 §22.2 伪列 .............................................................................................................................357 §22.3 GRANT、REVOKE 和权限.......................................................................................358 §22.3.1 对象和系统权限.............................................................................................358 §22.3.2 GRANT 和 REVOKE 命令语法....................................................................358 §22.4 事务控制 .....................................................................................................................359 §22.4.1 COMMIT 和 ROLLBACK..............................................................................359 §22.4.2 保留点 SAVEPOINT.......................................................................................360 §22.5 在 PL/SQL 中使用 SQL 函数.....................................................................................361 §22.5.1 错误处理函数 ..................................................................................................362 §22.5.2 数字函数 ..........................................................................................................362 第二十三章 PL/SQL 程序的测试和调试 ....................................................................................363 §23.1 问题诊断 .....................................................................................................................363 12 §23.1.1 调试指南 ........................................................................................................363 §23.1.2 显示在编译产生的错误.................................................................................363 §23.2 插入测试表 .................................................................................................................364 §23.3 DBMS_OUTPUT的使用 ............................................................................................364 §23.4 PL/SQL 调试器............................................................................................................365 §23.4.1 Procedure Builder调试器 .................................................................................365 §23.4.2 SQL-Station 调试器 ..........................................................................................366 §23.5 程序设计方法 ...........................................................................................................366 §23.5.1 模块化程序设计.............................................................................................366 §23.5.2 自顶向下设计.................................................................................................366 §23.5.3 数据抽象 ........................................................................................................366 第二十四章 性能及其它问题 ......................................................................................................367 §24.1 共享池 ..........................................................................................................................367 §24.1.1 共享池工作原理.............................................................................................367 §24.1.2 估计共享池大小.............................................................................................368 §24.1.3 将PL/SQL 驻留在共享池中 ........................................................................369 §24.2 SQL 语句调整..........................................................................................................370 §24.3 网络问题 ...................................................................................................................373 §24.4 PL/SQL wrap(转换器)...............................................................................................373 §24.4.1 运行 wrap 实用程序......................................................................................373 §24.4.2 输入和输出文件.............................................................................................374 §24.5 DBMS_OUTPUT 的使用 .......................................................................................374 第二十五章 对象类型 ..................................................................................................................376 §25.1 对象类型定义 .........................................................................................................376 §25.1.1 定义对象类型头...........................................................................................376 §25.1.2 定义对象类型体...........................................................................................376 §25.1.3 定义对象类型例子.......................................................................................377 §25.1.4 初始化对象类型...........................................................................................378 §25.1.5 使用对象类型...............................................................................................379 §25.2 对象类型修改 .........................................................................................................381 §25.3 对象类型删除 .........................................................................................................381 第二十六章 动态 PL/SQL 简介 ...................................................................................................383 §26.1 概述 .............................................................................................................................383 §26.1.1 静态 SQL 和动态 SQL....................................................................................383 §26.1.2 用 DBMS_SQL 包实现动态...........................................................................383 §26.1.3 用本地动态 SQL 实现动态.............................................................................385 §26.2 使用 DBMS_SQL 进行动态编程...............................................................................385 §26.2.1 执行 DML、DDL 及 Alter session语句.........................................................385 §26.2.2 示例 ..................................................................................................................388 §26.2.3 执行 DDL 语句 ...............................................................................................389 §26.2.4 执行 PL/SQL 块 ..............................................................................................390 §26.4 本地动态SQL...........................................................................................................391 §26.4.1 使用 EXECUTE IMMEDIATE 语句................................................................391 §26.4.2 向后兼容情况 ...................................................................................................392 13 §26.4.3 指定参数模式 ...................................................................................................393 第二十七章 LOB 和 DBMS_LOB 包简介 ..................................................................................394 §27.1 LOB 类型一般使用 .....................................................................................................394 §27.1.1 LOB 类型存储................................................................................................395 §27.1.2 临时LOB 类型...............................................................................................395 §27.1.3 LOB 类型的接口............................................................................................396 §27.2 一般 LOB 表与数据加载 ...........................................................................................396 §27.2.1 建立包含 LOB 的表.......................................................................................396 §27.2.2 用EMPTY_CLOB 或 EMPTY_BLOB 插入 LOB.......................................398 §27.2.3 一般的LOB 插入...........................................................................................399 §27.3 内部 LOB 和 DBMS_LOB 的使用 ............................................................................399 §27.3.1 APPEND 过程................................................................................................400 §27.3.2 CLOSE 过程...................................................................................................401 §27.3.3 COMPARE 函数.............................................................................................401 §27.3.4 COPY 过程.....................................................................................................403 §27.3.5 ERASE 过程...................................................................................................405 §27.3.6 GETCHUNKSIZE 函数 .................................................................................406 §27.3.7 GETLENGTH 函数........................................................................................407 §27.3.8 INSTR 函数....................................................................................................408 §27.3.9 READ 过程.....................................................................................................409 §27.3.10 SUBSTR 函数 ..............................................................................................410 §27.3.11 WRITE 过程.................................................................................................411 §27.3.12 WRITEAPPEND 过程 .................................................................................412 §27.4 临时 LOB.....................................................................................................................413 §27.4.1 建立临时 LOB................................................................................................413 §27.4.2 查看临时LOB................................................................................................414 §27.4.3 释放临时LOB................................................................................................414 §27.4.4 从BFILE 中加载临时 LOB...........................................................................415 §27.4.5 查看临时LOB 是否打开...............................................................................415 §27.4.6 显示临时 LOB 数据.......................................................................................416 §27.4.7 从临时LOB 读数据.......................................................................................417 §27.4.8 从临时LOB 读部分数据...............................................................................418 §27.4.9 比较两个临时 LOB 数据...............................................................................419 §27.4.10 查看临时LOB 模式的存在.........................................................................420 §27.4.11 得到临时LOB 的长度.................................................................................421 §27.4.12 拷贝部分临时 LOB 数据.............................................................................421 §27.4.13 为临时LOB 拷贝位置.................................................................................422 §27.4.14 加临时LOB 到另外的 LOB........................................................................423 §27.4.15 写追加到临时LOB......................................................................................424 §27.4.16 写数据到临时 LOB......................................................................................424 §27.4.17 修理临时LOB 数据.....................................................................................425 §27.4.18 删除临时 LOB 数据.....................................................................................426 §27.5 外部 LOB (BFILE).......................................................................................................426 §27.5.1 BFILE 目录指定 ............................................................................................426 14 §27.5.2 建立包括 BFILE 列的表 ...............................................................................427 §27.5.3 用BFILENAME()插入数据...................................................................428 §27.5.4 从另外表选择 BFILE 插入数据....................................................................429 §27.5.5 用初始化BFILE 位置来插入数据 BFILE 行...............................................429 §27.5.6 动态加载数据 BFILE 的表............................................................................429 §27.5.7 用BFILE 数据来加载 LOB 数据..................................................................430 §27.5.8 用FILEOPEN 打开 BFILE............................................................................431 §27.5.9 用OPEN 打开 BFILE....................................................................................431 §27.5.10 用FILEISOPEN 看 BFILE 是否打开 .........................................................431 §27.5.11 用ISOPEN 看 BFILE 是否打开..................................................................432 §27.5.12 显示 BFILE..................................................................................................432 §27.5.13 从BFILE 中读数据 .....................................................................................433 §27.5.14 读部分 BFILE..............................................................................................433 §27.5.15 比较 BFILE..................................................................................................434 §27.5.16 判断BFILE 是否存在模式..........................................................................434 §27.5.17 判断BFILE 是否存在 .................................................................................435 §27.5.18 得到BFILE 长度 .........................................................................................435 §27.5.19 拷贝 BFILE 的 LOB 位置............................................................................436 §27.5.20 得到目录别名和文件名字...........................................................................436 §27.5.21 用初始化BFILE 位置更新 BFILE.....................................437 §27.5.22 用FILECLOSE 关闭 BFILE.......................................................................437 §27.5.23 用CLOSE 关闭 BFILE................................................................................437 §27.5.24 用CLOSEALL 关闭所有 BFILE................................................................438 §27.5.25 用DELETE 等删除 BFILE 数据 ................................................................438 §27.6 使用SQL*loader 加载 LOB.....................................................................................438 §27.6.1 加载图象和文本文件.....................................................................................438 §27.6.2 加载文本文件.................................................................................................439 第二十八章 PL/SQL 编程技巧....................................................................................................442 §28.1 用触发器实现日期格式的自动设置...........................................................................442 §28.2 如何避免 TOO_MANY_ROWS 错误.........................................................................443 §28.3 如何解决 TOO_MANY_ROWS 问题.........................................................................446 §28.4 如何在 PL/SQL 中使用数组.......................................................................................447 §28.5 如何使用触发器完成数据复制...................................................................................448 §28.6 在 PL/SQL 中实现 Truncate........................................................................................449 §28.7 如何导出存储过程、触发器的代码...........................................................................450 附录 A:SQL 及 SQL*PLUS 命令参考......................................................................................459 %FOUND...............................................................................................................................460 %ISOPEN...............................................................................................................................460 %NOTFOUND.......................................................................................................................461 %ROWCOUNT......................................................................................................................462 %ROWTYPE..........................................................................................................................463 %TYPE...................................................................................................................................463 15 (+)...........................................................................................................................................464 @ (“at” 号).............................................................................................................................464 @@.........................................................................................................................................465 ABS........................................................................................................................................465 ACCEPT.................................................................................................................................466 ACOS......................................................................................................................................466 ADD_MONTHS.....................................................................................................................467 ALTER CLUSTER.................................................................................................................467 ALTER DATABASE..............................................................................................................468 ALTER FUNCTION...............................................................................................................469 ALTER INDEX......................................................................................................................469 ALTER PACKAGE................................................................................................................470 ALTER PROCEDURE...........................................................................................................470 ALTER PROFILE...................................................................................................................471 ALTER RESOURCE COST...................................................................................................471 ALTER ROLE........................................................................................................................472 ALTER ROLLBACK SEGMENT..........................................................................................472 ALTER SEQUENCE..............................................................................................................473 ALTER SESSION...................................................................................................................473 ALTER SNAPSHOT..............................................................................................................474 ALTER SNAPSHOT LOG.....................................................................................................475 ALTER SYSTEM...................................................................................................................475 ALTER TABLE......................................................................................................................476 ALTER TABLESPACE..........................................................................................................477 ALTER TRIGGER..................................................................................................................478 ALTER TYPE.........................................................................................................................478 ALTER USER.........................................................................................................................479 ALTER VIEW........................................................................................................................480 ANALYZE..............................................................................................................................480 APPEND.................................................................................................................................481 ASCII......................................................................................................................................481 ASIN.......................................................................................................................................482 ATAN......................................................................................................................................482 ATAN2....................................................................................................................................483 AUDIT....................................................................................................................................483 AVG........................................................................................................................................484 BFILENAME.........................................................................................................................484 BLOCK...................................................................................................................................485 BTITLE..................................................................................................................................486 CEIL.......................................................................................................................................487 CHANGE................................................................................................................................488 CHARTOROWID...................................................................................................................488 CHR........................................................................................................................................489 CLEAR...................................................................................................................................489 16 CLOSE....................................................................................................................................490 COLUMN...............................................................................................................................490 COMMENT............................................................................................................................491 COMMIT................................................................................................................................492 COMPUTE.............................................................................................................................492 CONCAT................................................................................................................................493 CONCATENATE....................................................................................................................493 CONNECT BY.......................................................................................................................494 CONVERT..............................................................................................................................494 COPY......................................................................................................................................495 COS........................................................................................................................................496 COSH......................................................................................................................................496 COUNT..................................................................................................................................497 CREATE CLUSTER..............................................................................................................497 CREATE CONTROLFILE.....................................................................................................498 CREATE DATABASE............................................................................................................499 CREATE DATABASE LINK.................................................................................................500 CREATE PROFILE................................................................................................................500 CREATE DIRECTORY..........................................................................................................501 CREATE FUNCTION............................................................................................................501 CREATE INDEX....................................................................................................................502 CREATE LIBRARY..........................................................................................................503 CREATE PACKAGE..............................................................................................................503 CREATE PACKAGE BODY............................................................................................504 CREATE PROCEDURE.........................................................................................................506 CREATE ROLE......................................................................................................................507 CREATE ROLLBACK SEGMENT.......................................................................................507 CREATE SCHEMA................................................................................................................508 CREATE SEQUENCE...........................................................................................................509 CREATE SNAPSHOT............................................................................................................509 CREATE SNAPSHOT LOG...................................................................................................510 CREATE SYNONYM............................................................................................................511 CREATE TABLE....................................................................................................................511 CREATE TABLESPACE........................................................................................................513 CREATE TRIGGER...............................................................................................................514 CREATE TYPE......................................................................................................................515 CREATE TYPE BODY..........................................................................................................516 CREATE USER......................................................................................................................516 CREATE VIEW......................................................................................................................517 CURRVAL..............................................................................................................................518 CURSOR_ALREADY_OPEN...............................................................................................518 DATATYPE............................................................................................................................519 17 DATATYPE —CHAR............................................................................................................519 DATATYPE —DATE.............................................................................................................520 DATATYPE —FLOAT...........................................................................................................520 DATATYPE —LONG............................................................................................................520 DATATYPE —LONGRAW...................................................................................................521 DATATYPE —MLSLABEL..................................................................................................521 DATATYPE —NUMBER......................................................................................................521 DATATYPE —RAW..............................................................................................................522 DATATYPE —ROWID..........................................................................................................522 DATATYPE —VARCHAR....................................................................................................522 DATATYPE —VARCHAR2...................................................................................................522 DECLARE..............................................................................................................................523 DECODE................................................................................................................................523 DEFINE..................................................................................................................................524 DEL........................................................................................................................................524 DELETE.................................................................................................................................525 DEREF....................................................................................................................................526 DESCRIBE.............................................................................................................................526 DROP CLUSTER...................................................................................................................527 DROP DATABASE LINK......................................................................................................527 DROP DIRECTORY..............................................................................................................528 DROP FUNCTION.................................................................................................................528 DROP INDEX........................................................................................................................528 DROP LIBRARY...................................................................................................................529 DROP PACKAGE..................................................................................................................529 DROP PROCEDURE.............................................................................................................530 DROP PROFILE.....................................................................................................................530 DROP ROLE..........................................................................................................................531 DROP ROLLBACK SEGMENT............................................................................................531 DROP SEQUENCE................................................................................................................532 DROP SNAPSHOT................................................................................................................532 DROP SNAPSHOT LOG.......................................................................................................532 DROP SYNONYM.................................................................................................................533 DROP TABLE........................................................................................................................533 DROP TABLESPACE............................................................................................................534 DROP TRIGGER....................................................................................................................534 DROP TYPE...........................................................................................................................535 DROP TYPE BODY...............................................................................................................535 DROP USER...........................................................................................................................536 DROP VIEW..........................................................................................................................536 DUMP.....................................................................................................................................537 DUP_VAL_ON_INDEX........................................................................................................537 EDIT.......................................................................................................................................538 EMPTY_BLOB......................................................................................................................538 18 EMPTY_CLOB......................................................................................................................539 EXCEPTION INIT Pragma....................................................................................................539 EXECUTE..............................................................................................................................540 EXISTS...................................................................................................................................540 EXIT.......................................................................................................................................541 EXIT.......................................................................................................................................542 EXIT-WHEN..........................................................................................................................542 EXP.........................................................................................................................................543 EXPLAIN PLAN....................................................................................................................543 FETCH....................................................................................................................................544 FLOOR...................................................................................................................................545 FOR-LOOP.............................................................................................................................545 FORMAT................................................................................................................................546 FORMAT —DATE.................................................................................................................546 FORMAT —NUMBER..........................................................................................................547 GET........................................................................................................................................547 GLB........................................................................................................................................548 GOTO.....................................................................................................................................548 GRANT..................................................................................................................................549 GREATEST............................................................................................................................550 GREATEST_LB.....................................................................................................................550 HEXTORAW..........................................................................................................................551 HOST......................................................................................................................................551 IF-THEN.................................................................................................................................552 IF-THEN-ELSE......................................................................................................................552 IF-THEN-ELSEIF..................................................................................................................553 INITCAP................................................................................................................................554 INPUT....................................................................................................................................554 INSERT...................................................................................................................................555 INSTR.....................................................................................................................................555 INSTRB..................................................................................................................................556 INTERSECT...........................................................................................................................557 INVALID_CURSOR..............................................................................................................557 INVALID_NUMBER.............................................................................................................558 KEYWORDS..........................................................................................................................559 LABELS.................................................................................................................................560 LAST_DAY............................................................................................................................561 LEAST....................................................................................................................................561 LEAST_LB.............................................................................................................................562 LENGTH................................................................................................................................562 LENGTHB..............................................................................................................................562 LIKE.......................................................................................................................................563 LIST........................................................................................................................................564 LN...........................................................................................................................................565 19 LOCK TABLE........................................................................................................................565 LOG........................................................................................................................................566 LOGIN_DENIED...................................................................................................................566 LOOP......................................................................................................................................567 LOWER..................................................................................................................................568 LPAD......................................................................................................................................568 LTRIM....................................................................................................................................569 LUB........................................................................................................................................569 MAKE_REF...........................................................................................................................570 MAX.......................................................................................................................................570 MIN........................................................................................................................................571 MINUS...................................................................................................................................571 MOD.......................................................................................................................................572 MONTHS_BETWEEN..........................................................................................................572 NEW_TIME...........................................................................................................................573 NEXT_DAY...........................................................................................................................574 NEXTVAL..............................................................................................................................574 NLS_CHARSET_DECL_LEN..............................................................................................575 NLS_CHARSET_ID..............................................................................................................575 NLS_CHARSET_NAME.......................................................................................................576 NLS_INITCAP.......................................................................................................................576 NLS_LOWER.........................................................................................................................577 NLS_UPPER..........................................................................................................................577 NO_DATA_FOUND..............................................................................................................578 NOAUDIT..............................................................................................................................579 NOT_LOGGED_ON..............................................................................................................579 NULL......................................................................................................................................580 NVL........................................................................................................................................581 OPEN......................................................................................................................................581 OPEN-FOR.............................................................................................................................582 运算符 ....................................................................................................................................582 运算符— < >..........................................................................................................................583 运算符—>..............................................................................................................................583 运算符—> =...........................................................................................................................584 运算符—! =............................................................................................................................584 运算符—*..............................................................................................................................585 运算符—+..............................................................................................................................586 运算符—-*.............................................................................................................................586 运算符—/...............................................................................................................................587 运算符—<=............................................................................................................................587 运算符—=..............................................................................................................................588 运算符—AND........................................................................................................................589 运算符—BETWEEN.............................................................................................................589 运算符—IN............................................................................................................................590 20 运算符—IS NOT NULL........................................................................................................590 运算符—IS NULL.................................................................................................................591 运算符—NOT........................................................................................................................591 运算符—NOT BETWEEN....................................................................................................592 运算符—NOT IN...................................................................................................................592 运算符—OR...........................................................................................................................593 PRIOR....................................................................................................................................593 PROGRAM_ERROR.............................................................................................................594 PROMPT................................................................................................................................595 PSEUDOCOLUMN...............................................................................................................595 RAISE.....................................................................................................................................595 RAWTOHEX..........................................................................................................................596 RECORD................................................................................................................................596 REFTOHEX...........................................................................................................................597 REMARK...............................................................................................................................598 RENAME...............................................................................................................................598 REPFOOTER.........................................................................................................................599 REPHEADER.........................................................................................................................599 REPLACE...............................................................................................................................600 REPLACE...............................................................................................................................601 RETURN................................................................................................................................601 REVOKE................................................................................................................................602 ROLLBACK...........................................................................................................................603 ROUND..................................................................................................................................603 ROWIDTOCHAR..................................................................................................................604 ROWTYPE_MISMATCH......................................................................................................605 RPAD......................................................................................................................................606 RTRIM....................................................................................................................................606 SAVE......................................................................................................................................607 SAVEPOINT...........................................................................................................................607 SELECT..................................................................................................................................608 SELECT INTO.......................................................................................................................608 SET.........................................................................................................................................609 SET ROLE..............................................................................................................................611 SET TRANSACTION............................................................................................................612 SHOW....................................................................................................................................612 SIGN.......................................................................................................................................613 SIN..........................................................................................................................................614 SINH.......................................................................................................................................614 SOUNDEX.............................................................................................................................615 SPOOL....................................................................................................................................615 SQLERRM.............................................................................................................................616 SQLPLUS...............................................................................................................................616 SQRT......................................................................................................................................617 21 START....................................................................................................................................617 STDDEV................................................................................................................................618 STORAGE..............................................................................................................................618 STORAGE_ERROR...............................................................................................................619 STORE....................................................................................................................................619 SUBSTR.................................................................................................................................620 SUBSTRB...............................................................................................................................620 SUM........................................................................................................................................621 SYSDATE...............................................................................................................................622 TABLE....................................................................................................................................622 TAN........................................................................................................................................623 TANH.....................................................................................................................................623 TIMEOUT_ON_RESOURCE................................................................................................624 TIMING..................................................................................................................................624 TO_CHAR (date)....................................................................................................................625 TO_CHAR (label)...................................................................................................................625 TO_CHAR (number)..............................................................................................................626 TO_DATE (char)....................................................................................................................626 TO_LABEL (char)..................................................................................................................627 TO_MULTI_BYTE (char)......................................................................................................627 TO_NUMBER (char).............................................................................................................628 TO_SINGLE_BYTE (char)....................................................................................................628 TOO_MANY_ROWS............................................................................................................629 TRANSLATE.........................................................................................................................629 TRUNC (date)........................................................................................................................630 TRUNC (number)...................................................................................................................631 TRUNCATERUNCATE.........................................................................................................631 TTITLE...................................................................................................................................632 UID.........................................................................................................................................633 UNDEFINE............................................................................................................................633 UNION...................................................................................................................................634 UNION ALL...........................................................................................................................634 UPDATE.................................................................................................................................635 UPPER....................................................................................................................................636 USER......................................................................................................................................636 USERENV..............................................................................................................................637 VALUE_ERROR....................................................................................................................638 VARIABLE.............................................................................................................................638 VARIABLE ASSIGNMENT..................................................................................................639 VARIANCE............................................................................................................................639 VSIZE.....................................................................................................................................640 RESERVED WORDS.............................................................................................................640 WHENEVER OSERROR.......................................................................................................641 WHENEVER SQLERROR....................................................................................................642 22 WHILE-LOOP........................................................................................................................642 ZERO_DIVIDE......................................................................................................................643 23 第一部分 Oracle SQL*PLUS 基础 第一章 Oracle 数据库基础 Oracle 的 SQL*PLUS 是设计所有应用系统的基础工具。要想将应用系统设计成一个健 壮的、性能优越的系统。最关键的是要理解 RDBMS 的真正含义和结构,理解 Oracle SQL*PLUS 的特点和核心,弄清关系数据库与桌面数据库的差别。比如理解数据的完整性、 一致性、索引、视图等。只有这样才能设计出符合 Oracle 特点的应用系统。从而保证系统在 提供使用后不会出现一致性、性能等问题。 §1.1 理解关系数据库系统(RDBMS) CODASYL(数据系统语言协会)是数据库任务组(Database Task Group,DBTG)创建的 一种数据库标准,这是一种基于 COBOL 的网络数据库标准。 §1.1.1 关系模型 一个描述两个集合的元素如何相互联系或如何一一对应的数学概念,对于数据库来说, 关系只是一个带有一些特殊属性的表。所以有: l 数据的基础项是关系 l 在这些表上的操作只产生关系 一个关系表必须符合某些特定条件,才能成为关系模型的一部分 l 储存在单元中的数据必须是原子的。每个单元只能存储一条数据,叫信息原则(Information Principle)。如果存储多条则违反信息原则。特舒情况下可能需要违反信息原则。 l 储存在列下的数据必须具有相同的数据类型。 l 每一行是唯一的(没有完全相同的行)。 l 列没有顺序。 l 行没有顺序 l 列有一个唯一性的名称。 关系模型的另一个是完整性原则。它包括实体完整性原则(Entity integrity rule)和引用 完整性原则( Referential integrity rule ),如: l 主键( Primary key )是能唯一标识行的一列或一组列的集合。 l 由多个列构成的主键称为连接键(Concatenated key)、 组 合键(Compound key ),或称作 24 为复合键(Composity key )。 另外就是外部键(Foreign key )是一个表中的一列或一组列,它们在其它表中作为主键而存 在。一个表中的外部键被认为是对另外一个表中主键的引用。实体完整性原则简洁地表明主 键不能全部或部分地空缺或为空,引用完整性原则简洁地表明一个外键必须为空或者它所引 用的主键当前存在值相一致。 §1.1.2 Codd 十二法则 Oracle 数据库系统是一个完美的完全符合数据库技术的关系数据库系统。要想你的应用 设计按照数据库原理来进行,最重要的就是理解 Oracle 的结构、语句和命令。Codd 提出的 十二条法则在 Oracle 系统中都可以找到: 1) 信息法则。 2) 授权存储法则,每一个数据项都通过“表名+行主键+列名”的组合形成访问。 3) 必须以一致的方法使用空值。 4) 一个活跃的、在线数据字典应作为关系型表被储存 5) 必须提供数据存取语言进行存取访问。 6) 所有能被更新的视图应当是可被更新的。 7) 必须有集合级的插入、更新和删除。 8) 物理数据的独立性。即应用不依赖物理结构。 9) 逻辑数据的独立性。如果一个表被分成两个部分,则应用视图连接在一起,以便不会对应 用产生影响。 10) 完整性的独立性。完整性规则应该储存在数据字典中。 11) 分布独立性。一个数据库即使被分布,也应该能工作。 12) 非破坏性原则。如果允许低级存取,一定不能绕过安全性和完整性原则。 §1.2 关系数据库系统(RDBMS)的组成 RDBMS 由两部分组成,即数据库系统内核(软件)和数据字典(内核用于管理数据库系 统的数据结构)两部分。 §1.2.1 RDBMS 内核 RDBMS 就是用来控制数据访问的操作系统。它的任务是按照一定的规则存储数据、检 索数据及保护数据。 25 §1.2.2 数据字典概念 数据自动存放数据库中所有对象(如表,索引,视图等)所需的信息。Oracle 8i 的数 据字典是存放数据库系统信息的一组表,从数据字典中的信息可以确认数据库中数据对象的 基本信息及存放位置。 §1.3 SQL、SQL*Plus 及 PL/SQL 下面用简单的语言解释 Oracle 的常用产品所包含的 SQL*PLUS和 PL/SQL 的关系。 §1.3.1 SQL 和 SQL*PLUS 的差别 SQL 是标准结构查询语言,而 SQL*PLUS 实际是包括标准的 SQL 和 Oracle 公司的一些命令组 成的产品,因而 Oracle 公司将其取名为 SQL*PLUS。下面是它们的解释。 1. SQL(Structured Query Language ) SQL 有许多关键字,以下语句是常用于开头的语句: Alter Insert Audit Lock Commit Noaudit Comment Rename Create Revoke Delete Select Drop Update Grant Validate 注: 1.Oracle 的 SQL 缓冲区一次只能存放一条 SQL 命令; 2.Validate ( 使生效) 在 oracle 中跟 Enable 一起用,但可以省去 Validate, 所以许多资 料都不介绍 Validate 的用法。其语法如: Enable{[Validate][Novalidate]} { [UNIQUE][PRIMARY KEY]... } ... 2. SQL*PLUS 除 SQL 外,SQL*PLUS 还包括称为 SQL*PLUS 命令的附加命令,这些命令主要用于形成复杂 报表,编辑 SQL 命令,提供帮助信息,维护系统等。SQL*PLUS 包括的命令如下: @ Connect Host Set # Copy 26 Input Show $ Define List Spool / Del Newpage Sqlplus Accept Describe Pause Start Append Disconnect Quit Timing Break Document Remark Ttitle Btitle Edit Prompt Undefine Chang Execute Print Save Clear Exit Run Column Get Runform Compute Help 3. DDL(Data Define Language ) 对于结构查询语言(有时称 SQL 命令),可以将它们分成两组,一组是数据定义语言(DDL); 另一组是数据操纵语言(DML)。其中用于数据定义的语言如下: Alter procedure 重编译过程 Alter table 修改表的属性 Analyze 统计数据库对象性能值 Alter table add Constraint 对已有的表加约束 Create table 建立表结构 Create index 建立索引 Drop table 删除表实体及相关的索引 Drop index 删除索引 Grant 授权给用户或角色 Truncate 删除表中的所有行 Revoke 从用户或角色收回权限 4.DML(Data Manipulation Language ) 对于结构查询语言的另一组是数据操纵语言(DML)。DML 其中用于数据操纵的命令如下: Insert Delete 27 Update Select Commit work Rollback §1.3.2 PL/SQL 语言 PL/SQL 是 Oracle RDBMS (Oracle 6 之后版本)的一个组成部分,PL 是“过程化语言 (Procedure Language )”的缩写。PL/SQL 语言是在 SQL 语言中结合了结构化过程语言成分 的准第四代语言 。 使用 PL/SQL 的目的: 由于大多数 PL/SQL 是在服务端来运行,这样可减少由客户端运行程序时所需的网络数 据流量。 可以使用 PL/SQL 的地方: l PL/SQL 可以单独进行程序的编写,完成一般的处理功能; l 在高级语言中可嵌入 PL/SQL 块; l 在 4GL 中可以嵌入 PL/SQL 块; l 在 PL/SQL 程序中可以嵌入 HTML 和 XML。 §1.4 登录到 SQL*PLUS 我们创建任何对象,如创建表、索引等都需要连接到 Oracle 中,这里用“登录”主要是 Oracle 的界面提供的是 Login 这样的叫法。其实就是连接的意思。在 Client/Server 结构下, Oracle 提供两种方式连接 SQL*PLUS,其中 SQL*NET V2.x 版本(目前版本不再使用 SQL*NET V2.x)提供在字符方式下连接到 SQL*PLUS,SQL*NET V2. x 版 本 提供在图形方式(Window) 使用,目前版本的 ORACLE8/8i 都使用 NET8 连接.(NET8 不再支持字符终端) §1.4.1 UNIX 环境 在 UNIX 下,要确保客户端或服务器端与 Oracle 服务器系统进行连接,必须保证 tnsnames.ora 和 listener.ora 两个参数文件的正确配置。详细的配置解释在 DBA 章节里解 释。下面是 tnsnames.ora 和 listener.ora 两个参数文件的内容显示。 1. tnsnames.ora 参数文件: INST1_HTTP = (DESCRIPTION = (ADDRESS_LIST = (ADDRESS = (PROTOCOL = TCP)(HOST = dbsvr)(PORT = 1521)) 28 ) (CONNECT_DATA = (SERVER = SHARED) (SERVICE_NAME = s450) (PRESENTATION = http://admin) ) ) EXTPROC_CONNECTION_DATA = (DESCRIPTION = (ADDRESS_LIST = (ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC)) ) (CONNECT_DATA = (SID = PLSExtProc) (PRESENTATION = RO) ) ) S450 = (DESCRIPTION = (ADDRESS_LIST = (ADDRESS = (PROTOCOL = TCP)(HOST = dbsvr)(PORT = 1521)) ) (CONNECT_DATA = (SERVICE_NAME = s450) ) ) 2. listener.ora 参数文件: LISTENER = (DESCRIPTION_LIST = (DESCRIPTION = (ADDRESS_LIST = (ADDRESS = (PROTOCOL = TCP)(HOST = dbsvr)(PORT = 1521)) ) (ADDRESS_LIST = (ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC)) ) ) ) SID_LIST_LISTENER = (SID_LIST = 29 (SID_DESC = (SID_NAME = PLSExtProc) (ORACLE_HOME = /home/oracle/app/oracle/product/8.1.7) (PROGRAM = extproc) ) (SID_DESC = (GLOBAL_DBNAME = s450) (ORACLE_HOME = /home/oracle/app/oracle/product/8.1.7) (SID_NAME = s450) ) ) 如果安装后已经正确地对上面的两个参数文件进行配置,则可以按照下面步骤进行登录: 1)先启动服务器端监听器: lsnrctl start 2)用下面命令显式登录到 SQL*PLUS: $sqlplus username/password 或 $SQLPLUS username/password@connect_string 3)用下面命令隐式登录到 SQL*PLUS: $sqlplus [enter] Enter user name:scott Enter password:****** §1.4.2 Windows NT 和 WINDOWS/2000 环境 在 NT/2000 环境下,要使客户端能与 Oracle 服务器进行连接,tnsnames.ora 和 listener.ora 参数文件的配置如下: 1. tnsnames.ora 参数文件: ORA816.TAIJI.COM.CN = (DESCRIPTION = (ADDRESS_LIST = (ADDRESS = (PROTOCOL = TCP)(HOST = zhao)(PORT = 1521)) ) (CONNECT_DATA = (SERVICE_NAME = ora816) ) ) 30 EXTPROC_CONNECTION_DATA.TAIJI.COM.CN = (DESCRIPTION = (ADDRESS_LIST = (ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC1)) ) (CONNECT_DATA = (SID = PLSExtProc) (PRESENTATION = RO) ) ) S450 = (DESCRIPTION = (ADDRESS_LIST = (ADDRESS = (PROTOCOL = TCP)(HOST = dbsvr)(PORT = 1521)) ) (CONNECT_DATA = (SERVICE_NAME = s450) ) ) 2. listener.ora 参数文件: LISTENER = (DESCRIPTION_LIST = (DESCRIPTION = (ADDRESS_LIST = (ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC1)) ) (ADDRESS_LIST = (ADDRESS = (PROTOCOL = TCP)(HOST = zhao)(PORT = 1521)) ) ) (DESCRIPTION = (PROTOCOL_STACK = (PRESENTATION = GIOP) (SESSION = RAW) ) (ADDRESS = (PROTOCOL = TCP)(HOST = zhao)(PORT = 2481)) ) ) SID_LIST_LISTENER = (SID_LIST = 31 (SID_DESC = (SID_NAME = PLSExtProc) (ORACLE_HOME = D:\oracle) (PROGRAM = extproc) ) (SID_DESC = (GLOBAL_DBNAME = ora816) (ORACLE_HOME = D:\oracle) (SID_NAME = ora816) ) ) Windows NT/2000 字符方式登录步骤: 1)先启动服务器端监听器: lsnrctl start 2)用下面命令显式登录到 SQL*PLUS: $sqlplus username/password 或 $SQLPLUS username/password@connect_string Windows NT/2000 图形方式登录步骤: 1)点击“开始”=》“程序”=》“Oracle –OraHome81”=》“Application on Development”=》 “SQL Plus”进入如下屏幕: 32 在WINDOWS NT/98/2000 上的登录界面(sqlplus 图) 可以在用户名框内输入用户、口令及主机字串;也可以分别进行输入。 §1.5 常用 SQL*PLUS 附加命令简介 Oracle 公司提供的附加语句(或称命令),可 以 满足程序人员和管理员的一些特殊操作要 求。比如,在显示超过上百行记录信息时,可以采用每屏“暂停”来实现。要达到这样的目 的,就要在 SQL>下发 set pause on 命令。由于 SQL*PLUS命令较多,下面仅给出最常用的 几个命令的说明,详细的请参考附录。 §1.5.1 登录到 SQL*PLUS 可以用下面命令登录到 SQL*PLUS,SQL*PLUS命令的简单语法如下: SQLPLUS [ [logon] | [start] ] logon可以是: {username[/password][@connect_identifier]|/} [AS {SYSOPER|SYSDBA}] |/NOLOG 注1:SQLPLUS 主要是在命令方式下使用,在NT、WINDOWS/2000、UNIX的用法都一样。 注2:如果在UNIX下,SQLPLUS命令不被识别(不存在),则问题在环境变量PATH没有设 置正确或者没有设置。SQLPLUS 可执行程序在$ORACLE_HOME/bin 目录下。 §1.5.2 EXIT 和 QUIT 可以用 exit 或quit 来终止SQL*PLUS的操作(会话)。语法如下: {EXIT|QUIT} [SUCCESS|FAILURE|WARNING ] {EXIT|QUIT} 可以用exit 或quit ,目前它们的功能一样。 SUCCESS 正常退出 FAILURE 带提示错误代码的退出 33 WARNING 带提示警告代码的退出 COMMIT 退出前将未提交进行保存 例如: SQL>exit §1.5.3 DESCRIBE(显示表、视图结构) DESCRIBE可以用(只要用DESC即可)来显示表、视图的列的定义,也可以显示同义词、函 数或存储过程的说明。语法如下: DESC[RIBE] {[schema.]object[@connect_identifier]} Schema:用户名,如果省去,则为对象的所有者。 object 可以是 表(table), 视图(view),类型( type), 存储过程(procedure),函数( function), 包(package)或同义词( synonym) @connect_identifier 数据库连接字串 例:显示emp 表的结构: SQL>desc emp §1.5.4 LIST(列出)命令 可以用 LIST 命令来列出当前 SQL 缓冲区中的一行或多行命令语句。 L[IST] [n|n m|n *|n LAST|*|* n|* LAST|LAST] n 列出第n行 n m 列出n到m行 n * 列出第n行到当前行 n LAST 列出第n行到最末行 * 列出所有行 * n 列出当前行到第n行 34 * LAST列出当前行到最末行 LAST 列出最末行 例: SQL> LIST 1 SELECT ENAME, DEPTNO, JOB 2 FROM EMP 3 WHERE JOB = ’CLERK’ 4* ORDER BY DEPTNO §1.5.5 Change(替换字符串)命令 可以用Change 命令来改变字符串(即替换字符串)。语法如下: C[HANGE] sepchar old [sepchar [new [sepchar]]] Sepchar 为分隔符,可以是 ”/” 或”!” -- 请使用者特别注意 Old 旧字串 New 新字串 例:将 除号(/)改为 乘号( * ),则需要命令为 c !/!*! 。即: SQL> l 1* select sal,sal/100 from emp SQL> c !/!*! 提醒:对于修改 / 字符的只能用 ! 来作分隔符(上例)。 例:将乘号( * )改为 加号( + ),则需要命令为 c !/!*! 。即: SQL> l 1* select sal,sal*100 from emp SQL> c/*/+/ 1* select sal,sal+100 from emp SQL> §1.5.6 Append(追加字符串)命令 35 可以用 Append 命令来完成在当前行的末尾追加字符串。语法如下: A[PPEND] text Text 所要求追加的字符串 例:在当前行select sal,sal+100 from emp 后加 where sal>=2000,则: SQL> l 1* select sal,sal+100 from emp SQL> a where sal>=2000 1* select sal,sal+100 from emp where sal>=2000 SQL> §1.5.7 Save 保存当前缓冲区命令到文件 可以用 SAVE 命令将当前的命令行保存到操作系统的文件中。语法如下: SAV[E] filename[.ext] [CRE[ATE]|REP[LACE]|APP[END]] 其中: filename:你将把缓冲区中的内容存入到操作系统目录的文件名。 ext:若使用文件后缀,缺省的文件后缀为SQL。 例: SQL>select table_name from dict where table_name like ‘%ROLE%’; SQL>save c:\get_role §1.5.8 GET 将命令文件读到缓冲区 可以用GET 命令将操作系统的目录下的命令文件读到缓冲区(但不执行)。语法如下: GET filename [.ext] [LIS[T]|NOL[IST]] 其中: filename: 希望加载到SQL缓冲区的文件名 ext: 文件的扩展名,缺省为 SQL. 例: SQL>get c:\get_role 36 §1.5.9 SPOOL 将信息记录到文件中 Oracle的SPOOL 命令可以实现将屏幕所出现的一切信息记录到操作系统的文件中直到 SPOOL OFF为止。语法如下: SPO[OL] [filename[.ext] | OFF | OUT] 其中: filename:你想输出(spool)的文件名。 ext:文件的后缀。缺省的后缀是LST(或LIS)。 SQL>col table_name for a20 SQL>col comments for a80 SQL>set linesize 110 SQL>SPOOl c:\all_dict SQL>select table_name,comments from dict; . . . . . . (系统查询信息) SQL>SPOOL OFF §1.5.10 再运行当前缓冲区的命令 在 SQL>方式下,如果希望在运行当前的命令,可用 Run(或 R)或用 / 来实现,如: SQL> set lin 120 SQL> select table_name from dict where table_name like '%ROLE%'; TABLE_NAME ------------------------------ DBA_ROLES DBA_ROLE_PRIVS USER_ROLE_PRIVS ROLE_ROLE_PRIVS ROLE_SYS_PRIVS ROLE_TAB_PRIVS SESSION_ROLES 已选择 7 行。 SQL> l 1* select table_name from dict where table_name like '%ROLE%' 37 SQL> / TABLE_NAME ------------------------------ DBA_ROLES DBA_ROLE_PRIVS USER_ROLE_PRIVS ROLE_ROLE_PRIVS ROLE_SYS_PRIVS ROLE_TAB_PRIVS SESSION_ROLES 已选择 7 行。 §1.6 常用数据字典简介 ORACLE 提供许多内部数据字典, 用以管理系统的各种信息和参数(即数据库对象),下 面列出几个常用的数据字典供初学者参考,其它方面的数据字典将在 DBA 管理中介绍。 ORACLE 数据字典的命名说明: USER 为前缀----记录用户的所有对象信息 ALL 为前缀----记录包括 USER 记录和授权给 PUBLIC 或该用 户的所有对象的信息。 DBA 为前缀----记录关于数据库对象(非用户对象)的信息。 V$ 公共系统动态视图,用于系统优化和调整参考. V_$ 动态性能视图,你可用 CATALOG.SQL 脚本建立动态视图建立同义词。 GV$ 新(oracle 8)的附加的固定视图(Global V$).在并行环境下反应的是 V$视图的信息。如: SELECT * FROM GV$LOCK WHERE INST_ID = 2 OR INST_ID = 5 ; 返回的是 instances 2 和 5 的 V$的信息。所以 GV$反应一组 Instances 的参数. GV$视图的 限制是参数 PARALLEL_MAX_SERVERS 必须大于 0 。 详见 Oracle Enterprise Manager Administrator's Guide. 注:请注意下面的总结: l 一般 DBA_ 的视图内容都包含 USER_和 ALL_为前缀的视图; l DBA_为前缀的视图的内容基本上是大写; l 以 V$_为前缀的视图的内容基本上是小写。 1. USER_TABLEs(=TABS) 用户的所有表的信息。 38 2.USER_TAB_COLUMNS(=COLS) 有关各表的列(字段)的信息 3.USER_VIEWS 用户的所有视图 4.USER_SYNONYMS(=SYN) 用户同义词 5.USER_SEQUENCES(=SEQ) 用户序列 6.USER_CONSTRAINTS 记录创建表结构时建立的限制。 7.USER_TAB_COMMENTS 表的注释。如: Comment on table emp is '职工表'; 8. USER_COL_COMMENTS 列(字段)注释。如: Comment on column emp.ename is '姓名'; 9. USER_INDEXES(=IND) 用户索引的简要信息 10. USER_IND_COLUMNS 用户索引的列信息 11. USER_TRIGGERS 用户触发器信息 12. USER_SOURCE 用户存储过程 13. USER_TABLESPACE 用户可以使用的表空间信息 14. USER_TS_QUOTAS 用户使用系统资源的信息 15. USER_SEGMENTS 用户对象所使用空间信息 16. USER_EXTENTS 用户的扩展段信息 17. USER_OBJECTS 用户对象 =USER_TABLES+USER_VIEWS+USER_INDEXES+ USER_SOURCE+USER_TRIGGERS+USER_JAVA 18. USER_PART_TABLES 用户分区信息 19. USER_TAB_PARTITIONS 20. USER_PART_COL_STATISTICS 21. USER_IND_PARTITIONS 22. USER_FREE_SPACE 23. CAT(=USER_CATALOG) 用户可以访问的所有的基表。 24. TAB 用户创建的所有基表,视图,同义词等。 25. DICT(=DICTIONARY) 构成数据字典的所有表的信息。 提示:虽然 Oracle 提供可以用 Comment on column tablename.column is 'xxxx'; 等来实现对表 或列进行注释,但不建议设计者采用这样的工作方式。而建议将注释写到脚本中更为直观。 §1.7 ORACLE 数据类型 Oracle 数据库的数据类型与其它的数据库系统相比,它的数据类型不多,Oracle 在表示 数据方面比其他数据库系统来说要省去许多关键字。Oracle 只用 NUMBER(m,n)就可以表示 任何复杂的数字数据。其它如日期类型等也简单得多,只 DATE 就表示日期和时间。下面以 列表形式给出各个版本的 Oracle 系统数据类型的表示方法。下面给出 Oracle 旧版本的数据类 39 型的目的是让读者了解 Oracle 的变化,另外就是你在对旧版本进行升级或数据转换时要注意 各个版本的差别。 ORACLE5、ORACLE6 数据类型 数据类型 说明 Char 可变长字符型,≤254 Varchar2 可变长字符型,≤2000 Number(m,n) 数字类型,含整数、小数等 Date 日期型,含时间,缺省格式为 mmm-dd-yyyy hh:mi:ss(占 7 字节) Long 存储大型可变长字符串,≤2GB Raw 存储短二进制串,≤2GB Long raw 存储长二进制串,≤2GB ORACLE7 数据类型 数据类型 说明 Char 定长字符,≤255 个字符 Varchar 变长字符,≤2000 个字符 Varchar2 变长字符,≤2000 个字符 Number(m,n) 数字类型,含整数、浮点、双精度等 Long 存储大型可变长字符串,≤2GB Raw 存储可变短二进制数,≤2000 Long raw 存储大型可变长二进制数,≤2GB ORACLE8/8i 数据类型 数据类型 说明 Char 定长字符,≤2000 个字符 Varchar (同 Varchar2)可变字符,≤4000 个字符 Varchar2 变长字符,≤4000 个字符 Date 固定长度(7 字节)的日期型 Number 数字型,可存放实型和整型 Long 可变字符,≤2GB 个字符 Raw 可变二进制数据,≤4000 字节 Long raw 可变二进制数据,≤2GB MLSLABEL 仅 Trusted Oracle 用长度在 2~5 字节间 Blob 大二进制对象,≤4GB Clob 大字符串对象,≤4GB Nclob 多字节字符集的 Clob,≤4GB Bfile 外部二进制文件,大小由 OS 决定 CHAR() 定长字符型(在 Oracle5 、Oracle6 是变长),字符长度不够自动在右边加空格符号。当字 40 符长度超出 2000 个则错误。不指定大小缺省为 1。 VARCHAR() 可变字符型,当前与 VARCHAR2()相同。 VARCHAR2() 可变字符型,当前与 VARCHAR()相同。VARCHAR2 类型的字段(列)可存放 4000 个字 符;但是 VARCHAR2 变量可以存放 32,767 个字符。大小必须指定。 NCHAR() 和 NVARCHAR2() NCHAR 和 NVARCHAR2 分别与 CHAR 和 VARCHAR2 有相同的大小。并用于于存放 National Language Support (NLS)数据,Oracle 允许以本地语言存放数据和查询数据。 如果将列名声明成 NCHAR、NVARCHAR2 这样的类型,则 insert 和 select 等语句中的具体值 前加 N,不能直接按照普通字符类型进行操作。看下面例子: SQL> create table nchar_tst(name nchar(6),addr nvarchar2(16),sal number(9,2)); 表已创建。 SQL> insert into nchar_tst values(N'赵元杰',N'北京市海淀区',9999.99); 已创建 1 行。 SQL> select * from nchar_tst where name like N'赵%'; NAME ADDR SAL ------ ---------------- ---------- 赵元杰 北京市海淀区 9999.99 SQL> select * from nchar_tst where name like '赵%'; select * from nchar_tst where name like '赵%' * ERROR 位于第 1 行: ORA-12704: 字符集不匹配. 提示:虽然 Oracle 可以使用 nchar, nvarchar2 类型来存放字符数据,但建议设计者不要使 用 NCHAR 和 NVARCHAR2。因为 CHAR 和 VARCHAR2 就能存放汉字。 NUMBER(

,)

是数据的整数部分,是数据的精度(即小数)部分,注意,部分可以表示负的精度。 用可以表示从小数点往右或往左保留多少位。如下表: 实际值 数据类型 存储值 41 1234567.89 Number 1234567.89 1234567.89 Number(8) 1234568 1234567.89 Number(6) 出错 1234567.89 Number(9,1) 1234567.9 1234567.89 Number(9,3) 出错 1234567.89 Number(7,2) 出错 1234567.89 Number(5,-2) 1234600 1234511.89 Number(5,-2) 1234500 1234567.89 Number(5,-4) 1230000 1234567.89 Number(*,1) 1234567.9 Sal number(7,2), --表示 5 位整数,2 位小数. DATE Oracle 的日期型用 7 个字节表示,每个日期型包含如下内容: l Century (世纪) l Year (年) l Month(月) l Day (天) l Hour (小时) l Minute (分) l Second (秒) 日期型字段有下面特点: l 日期型字段的插入和更新可以数据型或字符并带 to_date 函数说明即可。 l 缺省的日期格式有 NLS_DATE_FORMAT 参数控制,它的缺省格式为 DD-MON-YY。 l 缺省的时间是夜里 00:00:00 (即 0 点 0 分 0 秒)。 l sysdate 返回的是服务器的时间,见下面例子。 l 日期格式的显示可以设置,见下面例子。 l 日期型可以运算,见下面例子。见下面例子。 l 世纪用 cc 表示;年用 yyyy 表示,月用 mm 表示,日用 dd 表示,小时用 hh24 表示,分用 mi 表示,秒用 ss 表示。 例子: SQL> create table save_info(per_id varchar2(20),name varchar2(20),tran_date date, 2 tran_val number(12,2)); 表已创建。 SQL> insert into save_info values ( '110105540609811','赵元杰', 2 to_date('2001.06.18','yyyy.mm.dd'),12345.66); 已创建 1 行。 42 SQL> select * from save_info; PER_ID NAME TRAN_DATE TRAN_VAL -------------------- -------------------- ---------- ---------- 110105540609811 赵元杰 18-6 月 -01 1234.66 SQL> select per_id,name,to_char(tran_date,'yyyy/mm/dd'),tran_val from save_info; PER_ID NAME TO_CHAR(TR TRAN_VAL -------------------- -------------------- ---------- ---------- 110105540609811 赵元杰 2001/06/18 12345.66 SQL> show parameter nls_date_format NAME TYPE VALUE ------------------------------------ ------- ------------------------------ nls_date_format string SQL> alter session set nls_date_format= 2 '"公元"yyyy"年"mm"月"dd"日"'; 会话已更改。 SQL> select sysdate from dual; SYSDATE ------------------ 公元 2001 年 05 月 18 日 SQL> select to_char(sysdate,'cc yyyy.mm.dd') from dual; TO_CHAR(SYSDA ------------- 21 2001.05.18 关于日期型的使用方法详细请参考《 Oracle8i National Language Support Guide 》。 BLOB 大二进制对象,每条记录可存储达 4GB 的数据,详细见后面章节。 43 CLOB 大字符对象,每条记录可存储达 4GB 的数据,详细见后面章节。 BFILE 外部二进制文件,每条记录可存储达 4GB 的数据(与 OS 有关),详细见后面章节。 RAW 非结构的二进制数据,这些数据不被数据库系统解释。RAW 可以存储达 2,000 字节。 LONGRAW 大的二进制类型数据,LONGRAW 是非结构的二进制数据,这些数据不被数据库系统解释。 LONGRAW 可以存储达 2GB 字节。LONGRAW 不能被索引,而 RAW 可以被索引。 ROWID ROWID 在 Oracle 数据库中是一个虚的列,即系统用的特殊的列,不是我们建立的列。用于对 数据库中的每条记录进行定位。详细见“Rowid 的使用”章节。 UROWID UROWID 是 Universal ROWID 的意思。即全球 ROWID,它支持逻辑和物理 ROWID,也作为外部 表的(通过 getway 访问的非 Oracle 表)的 ROWID。UROWID 类型可以存储所有的 ROWID 类型 的数据。 %TYPE 类型的匹配: books_printed number(6); books_sold books_printed%TYPE; books_sold 的数据类型与 book_printed 的类型一致; ( %TYPE 类型 在 PL/SQL 中介绍 )。 空值与字符型、数字型的 运算: null + <数字>=null (空值+数字仍是空值) null > <数字>=null (空值与数字比较结果为空值) null || '字符串' = 字符串 number 类型与以下类型具有同等的值域: DEC Decimal Double PREcision Float Integer Int Numeric 44 Real Smallint 提示:虽然 Oracle 可以使用上面的子数据类型,但建议还是采用 NUMBER(n,m)为好。因为如 果使用子数据类型定义字段类型不当,可能引起数据在运算方面的问题。 Long 数据类型的限制: l select 中可以用 long; l update 中可以用 select 子句; l insert 中可以用 Valus 子句; l 每个表只能允许一个 long 列; l long 列不能列出完整性约束(null、not null 除外); l long 列不能被索引; l 过程或存储函数不能接收 long 型函数; l 存储函数不能返回 long 型值。 long 目前不能出现在以下情况中: l select 中的 Where,Group by,order by,Connect by,distinct; l 不能对 long 列作 substr,instr; l 表达式或条件; l 子查询或集合中不能用 long; l Create table ...as select 中不能用 long; §1.8 SQL 语句基础 下面给出 SQL 语句的基本介绍,更详细的描述见后面的章节。 §1.8.1 SQL 语句所用符号 操作符 用途 例子 + - 表示正数或负数,正数可省去 + -1234.56 + 将两个数或表达式进行相加 A=c+b - 将两个数或表达式进行相减 34-12 * 将两个数或表达式进行相乘 12*34 / 除以一个数或表达式 18*11 NULL 空值判断 Where name is null; || 字符串连接 ‘101-’||tel_num = 等于测试 Select * from emp where name=’赵元杰’; != 或<>或^= 不等于测试 Select * from emp where name !=’赵元杰’; 45 < 小于测试 Select * from emp Where sal < 5000; > 大于测试 Select * from emp Where sal > 5000; <= 小于等于测试 Select * from emp Where sal <= 5000; >= 大于等于测试 Select * from emp Where sal >= 5000; Not in 测试某值是否在一个指定的结果集中 Select name,addr from expert where local not in(‘北京’,’上 海’); ANY 将一个值与一组值进行比较,返回满足条 件的结果。必须跟!=,<,>,<=,>= select ename,sal from emp where sal<= any(select sal from emp where deptno=10) SOME 同 ANY,必须跟!=,<,>,<=,>= ALL 将一个值与一组值比较,返回满足条件的 所有列值。必须跟!=,<,>,<=,>= Select name,sal from emp Where sal<= all ( 500,800,1200); Not between A and B 判断某个值是否界于两者之间。 Select name,sal from emp Where sal between 500 and 1200; [not]exists 判断某个列是否存在于一组值中。 select dname,deptno from dept where exists (select * from emp where dept.deptno=emp.deptno) A[not]like b [Escape ‘char’] 比较两个模式是否相似,当使用 like 语句 时 Oracle 不去访问索引。 Select * from emp Where ename like ‘TH%’; Is [not] null 测试值是否为空。 Select ename,deptno from emp Where comm. Is null or comm.=0; Not 对结果的否定。 Select * from emp Where sal not(sal<1000); 等价 于 select ename,sal from emp where sal>=1000; AND 用于判断两个条件十分都满足。 Select * from emp where Ename=’SIMTH’ and sal>=1000; OR 用于判断两个条件中是否有一个满足。 Select * from emp where Ename=’SIMTH’ or ename=’SCOTT’; UNION 用于返回(组合)两个查询中所有唯一的 行。 Select ename from emp union Select ename from emp; UNION ALL 用于返回(组合)两个查询中所有所有的 行。 INTERSECT 用于返回两个查询中相同的行。 Select ename from emp1 intersect select ename from emp2; MINUS 用于返回两个查询中的不同的行。 §1.8.2 简单select 查询 当我们可以用SQL*PLUS登录到 SQL>下后,我们可以用 DESC 显示某表的结构,也可以用 46 select 语句简单查询表中的一些列的内容。 例:要查询 EMP 表中员工的姓名、工资及出生日期,则: SQL>select ename, sal, hiredate from emp; §1.9 伪列及伪表 Oracle系统为了实现完整的关系数据库功能,系统专门提供了一组称为伪列 (Pseudocolumn)的数据库列,这些列不是在建立对象(如建表)时由我们完成的,而是 在我们建立对象时由自动Oracle完成的。Oracle目前有以下的伪列: l CURRVAL and NEXTVAL 使用序列号的保留字 l LEVEL 查询数据所对应的级 l ROWID 记录的唯一标识 l ROWNUM 限制查询结果集的数量 有关伪列的详细解释和使用见相关章节。 Oracle 还提供了一个DUAL 的伪表,该表主要目的是保证在使用SELECT 语句中语句 的完整性而提供的,如:我们要查询当前的系统日期及时间,而系统的日期和时间并是放在 一个指定的表里。所以在 from 语句后就没有表名给出。为了使用 from 后有个表名,我们 就用DUAL代替。如: 例1:查询Oracle系统日期及时间: SQL> select to_char( sysdate,'yyyy.mm.dd hh24:mi:ss') from DUAL; TO_CHAR(SYSDATE,'YY ------------------- 2001.06.02 07:28:09 例2:计算一下 5000+5000*0.1 的结果是多少,则: SQL> select 5000+5000*0.1 from DUAL; 5000+5000*0.1 ------------------- 5500 §1.10 使用 SQL Worksheet 工作 在新的 Oracle 版本里,系统提供了一个叫 SQL Worksheet 的图形 SQL 工作环境,它是 47 ORACLE Enterprise Manager 的一部分。使用它可以免去在 SQL>下编辑行命令的不便。它完 全是在图形方式进行。它的启动有以下几种方法: l 从 ORACLE Enterprise Manager中启动 l 从 Administrtor 工具中启动 l 从操作系统中启动 下面给出在操作系统下启动SQL Worksheet 工具工作的步骤: 1) 点击 SQL Worksheet 图标,即选择 开始->程序->Oracle-OraHome81->database Administration->SQLPLUS Worksheet。选中SQLPLUS Worksheet后出现如下画面: 图 1.10-1 使用SQL Worksheet 的登录画面 在用户名、口令及服务输入ORACLE的有效用户名、口令及连接字串再点击确定后进入如图 1.10-2所示的画面。 2)当进入图1.10-2 所示的画面后。你就可以工作了。目前的版本是在屏幕的上方输入命令, 屏幕的下方是系统显示结果。 3)我们将光标点击到屏幕上方,输入SQL命令,如输入: select ename, sal from scott.emp; 输入完成命令后,用光标点击 左边的执行图标,Oracle 会结果显示在屏幕的下方: 48 图 1。10-2 登录成功后的画面 图1.10-3 查询命令及显示结果画面 49 从 SQL Worksheet 工具中可以看出,该工具提供了相当丰富的功能。下面给出个功能的简要 说明: 1.文件: l 改变数据库连接:可以连接到另外的用户和数据库上去; l 打开:可以打开现有文件; l 将输入另存为:将当前命令存为一个文件; l 将下方显示的结果存为一个文件。 2.编辑: l 剪切:将当前选中字符进行剪切; l 复制:将选中字符进行剪切; l 粘贴:将缓冲区字符进行粘贴; l 全选:对当前画面所有字符全选; l 全部清除:清除目前的所有内容。 3.工作单: l 执行:执行当前的命令; l 运行本地脚本:运行操作系统下某个.SQL 文件(点击后提示输入文件名); l 命令历史记录:查看命令历史记录; l 上一条命令:显示上一条命令。 提示:如果你的 SQL Worksheet 显示的不是汉字(出现乱字符),请你将你的 NT/2000/98 环 境下的汉字变量设置与服务器的一样就好了。在 WINDOWS NT 环境设置汉字变量步骤: 用 regedit 修改注册表中的所有 ORACLE 字符集项,如: 1)点击:开始=》运行=》输入 regedit; 2)点击“HEY_LOCAL_MACHINE”左边的“+”以展开目录; 3)点击“SOFTWARE”左边的“+”以展开目录; 4)点击“ORACLE”项; 5)修改 ORACLE 树下所有“NLS”变量与 props$中的一致。 关于汉字环境变量的设置,请参阅《Oracle8i/9I 初级数据库管理》。 50 第二章 查询基础 下面给出查询的一些基本的操作描述,如果你是位 Oracle 老手则可以跳这一章。 §2.1 SELECT 语句 在关系数据库中,使用频率最高要算 SELECT 语句了。尽管 SELECT 语句的使用非常 简单,但确很有学问。下面简单介绍有关 SELECT 语句的常用方法。 1.命令语法: SELECT 的简单语法: SELECT [DISTINCT | ALL] {* | column1[, column2]...} FROM {table_1 | (subquery)} [alias] [, {table_2 | (subquery)} [alias]]... [WHERE condition] [CONNECT BY condition [START WITH condition] [GROUP BY expn] [HAVING expn] [{ UNION [ALL] | INTERSECT | MINUS } SELECT . . . ] [ ORDER BY [expn ] [ ASC | DESC] [ FOR UPDATE [OF [user.]table | view] column ] [NOWAIT] 详细语法结构需查阅最新 ORACLE 原版《ORACLE8i SQL REFERENCE MANUAL》或 《ORACLE9i SQL REFERENCE MANUAL》 §2.2 SQL 中的单记录函数 许多资料(包括 Oracle 的资料)把 Oracle 的 SQL 语句中用到的函数分为单值函数和多 值函数,单值函数又分为字符函数和数字函数。下面分别介绍它们。 §2.2.1 单记录字符函数 函 数 说 明 ASCII 返回对应字符的十进制值 CHR 给出十进制返回字符 51 CONCAT 拼接两个字符串,与 || 相同 INITCAT 将字符串的第一个字母变为大写 INSTR 找出某个字符串的位置 INSTRB 找出某个字符串的位置和字节数 LENGTH 以字符给出字符串的长度 LENGTHB 以字节给出字符串的长度 LOWER 将字符串转换成小写 LPAD 使用指定的字符在字符的左边填充 LTRIM 在左边裁剪掉指定的字符 RPAD 使用指定的字符在字符的右边填充 RTRIM 在右边裁剪掉指定的字符 REPLACE 执行字符串搜索和替换 SUBSTR 取字符串的子串 SUBSTRB 取字符串的子串(以字节) SOUNDEX 返回一个同音字符串 TRANSLATE 执行字符串搜索和替换 TRIM 裁剪掉前面或后面的字符串 UPPER 将字符串变为大写 NVL 以一个值来替换空值 ASCII() 是字符串。返回与指定的字符对应的十进制数。 SQL> select ascii('A') A,ascii('a') a,ascii('0') zero,ascii(' ') space from dual; A a ZERO SPACE ---------- ---------- ---------- ---------- 65 97 48 32 SQL> select ascii('赵') zhao,length('赵') leng from dual; ZHAO LENG ---------- ---------- 54740 1 CHR([NCHAR]) 给出整数,返回对应字符。如: SQL> select chr(54740) zhao,chr(65) chr65 from dual; ZH C -- - 赵 A CONCAT(,) 52 SQL> select concat('010-','8801 8159')||'转 23' 赵元杰电话 from dual; 赵元杰电话 ----------------- 010-8801 8159 转 23 INITCAP() 返回字符串 c1 并第一个字母变为大写。例如: SQL> select initcap('simth') upp from dual; UPP ----- Simth INSTR(,[,[,] ] ) 在一个字符串中搜索指定的字符,返回发现指定的字符的位置。 C1: 被搜索的字符串 C2: 希望搜索的字符串 I: 搜索的开始位置,缺省是1 J: 出现的位置,缺省是1。 SQL> SELECT INSTR ('Oracle Training', 'ra', 1, 2) "Instring" FROM DUAL; Instring ---------- 9 INSTRB(,[,[,] ] ) 除了返回的字节外 ,与 INSTR 相同, LENGTH( ) 返回字符串 c 的长度。 SQL> l 53 1 select name,length(name),addr,length(addr),sal,length(to_char(sal)) 2* from nchar_tst SQL> / NAME LENGTH(NAME) ADDR LENGTH(ADDR) SAL LENGTH(TO_CHAR(SAL)) ------ ------------ ---------------- ------------ ---------- ---------------- 赵元杰 3 北京市海淀区 6 99999.99 8 LENGTHB( ) 以字节返回字符串的字节数。 SQL> select name,lengthb(name),length(name) from nchar_tst; NAME LENGTHB(NAME) LENGTH(NAME) ------ ------------- ------------ 赵元杰 6 3 LOWER ( ) 返回字符串并将所有字符变为小写。 SQL> select lower('AaBbCcDd') AaBbCcDd from dual; AABBCCDD -------- aabbccdd UPPER( ) 与 LOWER 相反,将给出字符串变为大写。如: SQL> select upper('AaBbCcDd') AaBbCcDd from dual; AABBCCDD -------- AABBCCDD 54 RPAD 和 LPAD(粘贴字符) RPAD(string,Length[,'set']) LPAD(string,Length[,'set']) RPAD 在列的右边粘贴字符; LPAD 在列的左边粘贴字符。 例 1: SQL>select RPAD(City,35,'.'),temperature from weather; RPAD(City,35,'.') temperature -------------------------- ---------------- CLEVELAND...... 85 LOS ANGELES.. 81 ......................... (即不够 35 个字符用'.'填满) LTRIM(左截断)RTRIM(右截断) 函数 LTRIM (string [,’set’]) Left TRIM (左截断)删去左边出现的任何set 字符。 RTRIM (string [,’set’]) Right TRIM (右截断)删去右边出现的任何set 字符。 例1: SELECT RTRIM (‘Mother Theresa, The’, ‘The’) “Example of Right Trimming” FROM DUAL; Example of Right ---------------- Mother Theresa, SUBSTR Substr(string,start[,Count]) 取子字符串中函数 对字串(或字段),从 start 字符 开始,连续取 count 个字符并返回结果,如果没有指 count 则一直取到尾。 select phone,substr(phone,1,3) || ‘0’ || substr(phone,4) from telecommunication where master= ’中国电信’; SUBSTRB(string ,start[,Count]) 55 对字串(或字段),从 start 字节 开始,连续取 count 个字节并返回结果,如果没有指 count 则一直取到尾。 REPLACE (‘string’ [,’string_in’,’string_out’]) String: 希望被替换的字符串或变量。 String_in: 被替换字符串。 String_out: 要替换字符串。 SQL> select replace('Informaix中国公司','Informaix','IBM Informix') 2 IBM 数据库 from dual; IBM 数据库 -------------------- IBM Informix中国公司 SOUNDEX( ) 返回一个与给定的字符串读音相同的字符串(不管拼写是否一样)。 SELECT DPL_NAME FROM DENIED_PARTIES_LIST WHERE SOUNDEX(DPL_NAME) = SOUNDEX(‘Saddam Hussain’) ; DPL_NAME ---------------------------------------------- Al Husseni Sadda Al Sada. REPLACE (‘string’ [,’string_in’,’string_out’]) String:希望被替换的字符串或变量。 String_in: 被替换字符串。 String_out: 要替换字符串。 SELECT REPLACE (‘Oracle’, ‘Or’, ‘Mir’) “Example “ FROM DUAL; Example ------- Miracle TRIM( [] FROM ) 56 TRIM可以使你对给定的字符串进行裁剪(前面,后面或前后)。 l 如果指定 LEADING, Oracle 从trim_char 中裁剪掉前面的字符; l 如果指定TRAILING, Oracle 从trim_char 中裁剪掉尾面的字符; l 如果指定两个都指定或一个都没有给出,Oracle从trim_char 中裁剪掉前面及尾面的字 符; l 如果不指定 trim_character, 缺省为空格符; l 如果只指定trim_source, Oracle Oracle从trim_char 中裁剪掉前面及尾面的字符。 例子:将下面字符串中的前面和后面的‘0‘字符都去掉: SELECT TRIM (0 FROM 0009872348900) "TRIM Example" FROM DUAL; TRIM example -------------------------------- 98723489 §2.2.2 单记录数字函数 函数 说明 Value1 + value2 Value1 - value2 Value1 * value2 Value1 / value2 ABS(value) CEIL(value) COS(value) COSH(value) EXP(value) FLOOR(value) LN(value) LOG(value) MOD(value,divisor) NVL(value,substitute) POWER(value,exponent) ROUND(value,precision) SIGN(value) SIN(value) SINH(value) SQRT(value) TAN(value) TANH(value) TRUNC(value,按 precision) VSIZE(value) 加 减 乘 除 绝对值 大于或等于 value 的最小整数 余弦 反余弦 e 的 value 次幂 小于或等于 value 的最大整数 value 的自然对数 value 的以 10 为底的对数 求模 value 为空时以 substitute 代替 value 的 exponent 次幂 按 precision 精度 4 舍 5 入 value 为正返回 1;为负返回-1;为 0 返回 0. 余弦 反余弦 value 的平方根 正切 反正切 按照 precision 截取 value 返回 value 在 ORACLE 的存储空间大小 57 ABS( ) 返回指定值的绝对值。如: SQL> select abs(100),abs(-100) from dual; ABS(100) ABS(-100) ---------- ---------- 100 100 ACOS( ) 给出反余弦的值。如: SQL> Select acos(-1) acos from dual; ACOS ---------- 3.14159265 ASIN( ) 给出反正弦的值。如: SQL> select asin(-1) "arc sine" from dual; arc sine ---------- -1.5707963 ATAN ( ) 返回一个数字的反正切值。如: SQL> select atan(-1) "arc tangent" from dual; arc tangent ----------- -.78539816 CEIL( ) 58 返回大于或等于给出数字的最小整数。如: SQL> select ceil(3.14159) from dual; CEIL(3.14159) ------------- 4 COS ( ) 返回一个数字余弦值。如: SQL> select cos(-3.1415926) from dual; COS(-3.1415926) --------------- -1 COSH ( ) 返回一个数字双曲余弦值。如: SQL> select cosh(20) cosh from dual; COSH ---------- 242582598 EXP ( ) 返回一个数字 e 的 n 次方的值。如: SQL> select exp(2),exp(1) from dual; EXP(2) EXP(1) ---------- ---------- 7.3890561 2.71828183 FLOOR ( ) 59 对给定的数字取整数,如: SQL> select floor(123.45),floor(45.56) from dual; FLOOR(123.45) FLOOR(45.56) ------------- ------------ 123 45 LN( ) 返回一个数字的对数值,n 是大于 0 的数字,如: SQL> select ln(1),ln(2),ln(3) from dual; LN(1) LN(2) LN(3) ---------- ---------- ---------- 0 .693147181 1.09861229 LOG( , ) 返回一个以 n1 为底的 n2 的对数,n1 不是 0 或 1 的正数。如: SQL> select log(2,1),log(2,2) from dual; LOG(2,1) LOG(2,2) ---------- ---------- 0 1 MOD( , ) SQL> Select mod(10,3), mod(10,2), mod(10,4) from dual; MOD(10,3) MOD(10,2) MOD(10,4) ---------- ---------- ---------- 1 0 2 POWER ( , ) 返回 n1 的 n2 次方值,如: SQL> select power(2,10),power(3,3) from dual; 60 POWER(2,10) POWER(3,3) ----------- ---------- 1024 27 ROUND(value,precision) 按照指定的精度进行舍入; select round(55.5),round(-55.5),trunc(55.5),trunc(-55.5) from dual; round(55.5) round(-55.5) trunc(55.5) trunc(-55.5) ----------- ------------ ----------- ------------- 56 -56 55 -55 SIGN() 取数字 n 的符号,大于 0 返回 1;小于 0 返回-1; 等于 0 返回 0。 如: 例: select sign(123), sign(-100),sign(0) from dual; sign(123) sign(-100) sign(0) ---------- ---------- ---------- 1 -1 0 SIN ( ) 返回一个数字的正弦值。如: SQL> select sin(1.57079) from dual; SIN(1.57079) ------------ 1 SINH( ) 返回双曲余弦的值,如: SQL> select sin(20),sinh(20) from dual; 61 SIN(20) SINH(20) ---------- ---------- .912945251 242582598 SQRT( ) 返回 数字 n 的根,如: SQL> select sqrt(64),sqrt(10) from dual; SQRT(64) SQRT(10) ---------- ---------- 8 3.16227766 TAN( ) 返回数字 n的正切值,如: SQL> select tan(20),tan(10) from dual; TAN(20) TAN(10) ---------- ---------- 2.23716094 .648360827 TANH( ) 返回数字 n的双曲正切值,如: SQL> select tanh(20),tan(20) from dual; TANH(20) TAN(20) ---------- ---------- 1 2.23716094 TRUNC(value,precision) 按照指定的截取一个数。如: SQL> SELECT TRUNC (124.16666, -2) trunc1, trunc(124.16666,2) from dual; 62 TRUNC1 TRUNC(124.16666,2) ---------- ------------------ 100 124.16 §2.2.3 单记录日期函数 Oracle 用到的日期函是: 函 数 描 述 ADD_MONTH 在日期 date 上增加 count 个月 GREATEST(date1,date2,. . .) 从日期列表中选出最晚的日期 LAST_DAY( date ) 返回日期 date 所在月的最后一天 LEAST( date1, date2, . . .) 从日期列表中选出最早的日期 MONTHS_BETWEEN(date2,date1) 给出 Date2 - date1 的月数(可以是小数) NEXT_DAY( date,’day’) 给出日期 date 之后下一天的日期,这 里 的 day 为星期, 如: MONDAY,Tuesday 等。 NEW_TIME(date,’this’,’other’) 给出在 this 时区=Other 时区的日期和时间 ROUND(date,’format’) 未指定 format 时,如果日期中的时间在中午之前,则 将日期中的时间截断为 12 A.M.(午夜,一天的开始), 否则进到第二天。时间截断为 12 A.M.(午夜,一天的 开始),否则进到第二天。 TRUNC(date,’format’) 未指定 format 时,将日期截为 12 A.M.( 午夜,一天 的开始). ADD_MONTHS( , ) 增加月份和减去月份,如: SQL> select to_char( add_months(to_date('199712','yyyymm'), 1),'yyyymm') add_month 2 from dual; ADD_MO ------ 199801 SQL> select to_char(add_months(to_date('199712','yyyymm'), -1 ),'yyyymm') add_mo 2 from dual; 63 ADD_MO ------ 199711 LAST_DAY( date ) 返回日期 date 所在月的最后一天,如: SQL> select to_char(sysdate,'yyyy.mm.dd'),to_char((sysdate)+1,'yyyy.mm.dd') 2 from dual; TO_CHAR(SY TO_CHAR((S ---------- ---------- 2001.05.18 2001.05.19 MONTHS_BETWEEN(date2,date1) 给出 Date2 - date1 的月数(可以是小数); SQL> select months_between('19-12 月-1999','19-3 月-2000') mon_betw from dual; MON_BETW ---------- -3 SQL> select months_between(to_date('2000.05.20','yyyy.mm.dd'), 2 to_date('2005.05.20','yyyy.mm.dd') ) mon_bet from dual; MON_BET ---------- -60 NEW_TIME(date, ’this’,’other’) 给出在 this 时区=Other 时区的日期和时间 This 和 other 是时区,它们可以是下面的值: 时区缩写 代表的时区 AST/ADT 大西洋标准/日期时间 BST/BDT 白令海标准/日期时间 CST/CDT 中部标准/日期时间 GMT 格林威治时间 HST/HDT 阿拉斯加-夏威夷标准/日期时间 64 MST/MDT 山区标准/日期时间 NST 新大陆标准时间 PST/PDT 太平洋标准/日期时间 YST/YDT Yukon 标准/日期时间 SQL> select to_char(sysdate,'yyyy.mm.dd hh24:mi:ss') bj_time, 2 to_char(new_time(sysdate,'PDT','GMT'),'yyyy.mm.dd hh24:mi:ss') los_angles 3 from dual; BJ_TIME LOS_ANGLES ------------------- ------------------- 2001.05.19 06:25:25 2001.05.19 13:25:25 NEXT_DAY( date, ’day’) 给出日期 date 和星期 x 之后计算下一星期 x 的日期,这 里 的 day 为星期,如: MONDAY,Tuesday 等。但在中文环境下,要写成’星期 x’这样的格式,如: 例:比如今天是 5 月 18 日星期五,计算下一个星期五是几号: SQL> select next_day('18-5 月-2001','星期五') nxt_day from dual; NXT_DAY ---------- 25-5 月 -01 SYSDATE 用来得到系统的当前日期,如: SQL> select to_char(sysdate,'dd-mon-yyyy day') from dual; TO_CHAR(SYSDATE,'DD ------------------- 18-5 月 -2001 星期五 TRUNC(,[,] ) 按照 给出的 fmt 的要求将日期截断。如果 fmt=’mi’ 则表示截断掉秒保留至分。如: SQL> select to_char(trunc(sysdate,'hh'),'yyyy.mm.dd hh24:mi:ss') hh, 2 to_char(trunc(sysdate,'mi'),'yyyy.mm.dd hh24:mi:ss') hhmm from dual; 65 HH HHMM ------------------- ------------------- 2001.05.18 22:00:00 2001.05.18 22:27:00 §2.2.4 单记录转换函数 函 数 描 述 CHARTOROWID 将 字符转换到 rowid 类型 CONVERT 转换一个字符节到另外一个字符节 HEXTORAW 转换十六进制到 raw 类型 RAWTOHEX 转换 raw 到十六进制 ROWIDTOCHAR 转换 ROWID 到字符 TO_CHAR 转换日期格式到字符串 TO_DATE 按照指定的格式将字符串转换到日期型 TO_MULTIBYTE 把单字节字符转换到多字节 TO_NUMBER 将数字字串转换到数字 TO_SINGLE_BYTE 转换多字节到单字节 CHARTOROWID() 将字符数据类型转换为 ROWID 类型,如: 1* select rowid,rowidtochar(rowid),ename from scott.emp SQL> / ROWID ROWIDTOCHAR(ROWID) ENAME ----------------------------------- ---------------------------------------- ---------- AAAFXDAABAAAHVaAAA AAAFXDAABAAAHVaAAA SMITH AAAFXDAABAAAHVaAAB AAAFXDAABAAAHVaAAB ALLEN AAAFXDAABAAAHVaAAC AAAFXDAABAAAHVaAAC WARD CONVERT( ,[,] ) 将源字符串 sset 从一个语言字符集转换到另一个目的 dset 字符集。 SELECT CONVERT (‘strutz’, ‘ WE8HP’, ‘ F7DEC ‘) “Conversion” FROM DUAL; Conversion 66 --------------- Strutz. HEXTORAW( ) 将一个十六进制构成的字符串转化为二进制。如: Insert into printers( printer_nbr,manufacturer,model,init_string) Values ( 12,’HP’,’Laserjet’,”HEXTORAW(‘1B45’)); RAWTOHEX( ) 将一个二进制构成的字符串转化为十六进制。如: select rawtohex ( init_string) hext from printers where model=LaserJet’ and manufacturer=’HP’; hext ----------- 1B45 ROWIDTOCHAR( ) 将 ROWID 数据类型转换为字符类型,见 CHARTOROWID。 TO_CHAR(date, ’format’) 根据 format 重新格式日期 date 的格式。如: SQL> select to_char(sysdate,'yyyy/mm/dd hh24:mi:ss') from dual; TO_CHAR(SYSDATE,'YY ------------------- 2001/05/18 23:05:36 日期格式比较多,详细内容请参考原版资料。下面给出常用的日期格式代码: 日期格式代码表 日期代码 格式说明 例子 AD 或 BC AD=Anno Domini 公元,BC=Before Christ 公 元前。不带点的公元或公元前 ‘YYYY AD’=1999 AD A.D. 或 B.C. 带点的公元或公元前 ‘YYYY A.D.’=1999 A.D. 67 AM 或 PM AM= ante meridiem 上午,PM=post meridiem 下午。不带点的上午或下午 ‘HH12AM’=09AM A.M.或 P.M. 带点的上午或下午 ‘HH12A.M.’=09A.M. DY 星期几的缩写 Mon,Tue,... DAY 星期几的全拼 Monday,Tuesday,... D 一周的星期几,星期天=1,星期六=7 1,2,3,4,5,6,7 DD 一月的第几天,1à31 1,2,... 31 DDD 一年的第几天,1à366 1,2,3,...366 J 公元前的第几天(从公元前 4712 起 ?) 2451514,2451515,... W 一个月的第几周,1à 5 1,2,3,4,5 WW,IW 一年的第几周,一年的 ISO 的第几周 1,2,3,4,... 52 MM 两为数的月 01,02,03,...12 MON 月份的缩写 Jan,Feb,Mar ,...Dec MONTH 月份的全拼 January,February,... RM 罗马数字的月份,I à XII I,II,III,IV,...XII YYYY,YYY,YY,Y 四位数的年,三位数的年 1999,999,99,9 YEAR 年的全拼 Nineteen Ninety-nine SYYYY 如果是公元前(BC),年份前负号 -1250 RR 当前年份的后两位数字 01 代表 2001 年 HH,HH12 12 小时制,1à12 1,2,3,...12 HH24 24 小时制,0à23 0,1,2,3,...23 MI 一小时中的第几分,0à59 0,1,2,3...59 SS 一分中的第几秒,0à59 0,1,2,3,...59 SSSSS 一天中的第几秒,0à86399 0,1,2,3,...86399 ../-;: 标点符号表示法 文字显示 ‘text’ 引号表示法 文字显示 TO_DATE(string, ’format’) 将一和字串转换为 ORACLE 的日期。如: Insert into demo(demo_key,date_col) Values(1 , to_date(’04-Oct-1999’, ‘DD-Mon-yyyy’) ); TO_MULTI_BYTE() 将字符串中的单字节字符转换为多字节字符, 如: TO_NUMBER() 将给出的字符转换为数字,如: 68 SELECT TO_NUMBER (‘1947’) “FISCAL_YEAR” FROM DUAL; FISCAL_YEAR ----------- 1947 TO_MULTI_BYTE()及 TO_SINGLE_BYTE 将单字节转换为多字节或从多字节转换为单字节。 §2.2.5 其它的单记录函数 BFILENAME(

, ) 指定一个外部二进制文件。如: INSERT INTO file_tbl VALUES (BFILENAME (’lob_dir1’, ’image1.gif’)); CONVERT (‘x’,’desc_set’ [, ‘source_set’]) 将 x 字段或变量的源 source 转换为 desc,如: select sid,serial#,username, DECODE(command, 0,’None’, 2,’Insert’, 3,’Select’, 6,’Update’, 7,’Delete’, 8,’Drop’, ‘Other’) cmd from v$session where type != ‘BACKGROUND’; 关于 DECODE 在优化方面的内容在《Oracle8i/9i 高级数据库管理》中查阅。 69 DUMP( s,[,fmt [, start [, length ] ] ] ) DUMP 函数以 fmt 指定的内部数字格式返回一个 VARCHAR2 类型的值。如: SQL> col global_name for a30 SQL> col DUMP_STRING for a50 SQL> set lin 200 SQL> select global_name,dump(global_name,1017,8,5) dump_string 2 from global_name; GLOBAL_NAME DUMP_STRING ------------------------------------- ---------------------------------------------------------------- ORA816.US.ORACLE.COM Typ=1 Len=20 CharacterSet=ZHS16GBK: U,S,.,O,R EMPTY_BLOB() 和 EMPTY_CLOB() 函数 这两个函数都是用来对大数据类型字段进行初始化操作的函数,一般有: BLOB 数据类型 --- EMPTY_BLOB() CLOB 数据类型 --- EMPTY_CLOB() NCLOB 数据类型 --- EMPTY_CLOB() Insert into proposal ( proposal_id, recipient_name,proposal_name,short_description, proposal_text,budget , cover_letter ) values(2,’BRAD OHMONT’,’REBUILD FENCE’,NULL, EMPTY_CLOB(),EMPTY_BLOB(), BFILENAME(‘proposal_dir’,’P2.DOC’) ); GREATEST( ) 返回一组表达式中的最大值,即比较字符的编码大小。如: SQL> select greatest('AA','AB','AC') from dual; GR -- AC SQL> select greatest('啊','安','天') from dual; 70 GR -- 天 即 “天”的编码比“安”和“啊”都大。 LEAST ( ) 返回一组表达式中的最小值,即比较字符的编码大小。如: SQL> select least('啊','安','天') from dual; LE -- 啊 UID 函数 返回标识当前用户的唯一整数,如: SQL> show user USER 为"SYSTEM" SQL> l 1* select username,user_id from dba_users where user_id=UID SQL> / USERNAME USER_ID ------------------------------ ---------- SYSTEM 5 USER 函数 返回当前用户的名字,如: SQL> select user from dual; USER ------------------------------ SYSTEM USERENV( ) 71 返回当前用户环境的信息,opt 选项可以是: ENTRYID 返回当前用户会话的入口 ID SESSIONID 返回当前用户会话的 ID TERMINAL 返回当前系统会话的操作系统标识 OSDBA 如果当前用户有 DBA 权限,则返回 TRUE LABLE 返回当前用户会话的标号 LANGUAGE 返回当前用户的语言和区域 CLIENT_INFO 为当前用户会话返回 client-info 域的值,这个值由 dbms_application_info,set_client_info 过程来设置。 LANG 以ISO 的三个字符表示当前用户会话所使用的语言。 VSIZE 返回表达式的字节大小。 ISDBA 函数 查看当前用户是否是 DBA ,当 SYSDBA 角色有效是才返回 TRUE,如: SQL> show user USER is "SYSTEM" SQL> select userenv('ISDBA') from dual; USEREN ------ FALSE SQL> connect sys/sys@ora816 Connected. SQL> select userenv('ISDBA') from dual; USEREN ------ FALSE SQL> connect internal Connected. SQL> select userenv('ISDBA') from dual; USEREN ------ TRUE SESSIONID 函数 72 返回审计会话标识,如: select userenv(‘SESSIONID’) aud_id from dual; aud_id --------- 47343 ENTRYID 函数 返回审计会话入口标识,当 initsid.ora 文件中的 audit_trail=TRUE 时可以用,如: select userenv(‘ENTRYID’) from dual; USERENV(‘ENTRYID’) ------------- 835641 INSTANCE 函数 返回当前 INSTANCE 的标识,如: SQL> select userenv('INSTANCE') from dual; USERENV('INSTANCE') ------------------- 1 LANGUAGE 函数 返回当前环境的语言,如: SQL> select userenv('LANGUAGE') from dual; USERENV('LANGUAGE') ---------------------------------------------------- SIMPLIFIED CHINESE_CHINA.ZHS16GBK LANG 函数 返回当前环境的语言的缩写,如: 73 SQL> l 1* select userenv('LANG') from dual SQL> / USERENV('LANG') ---------------------------------------------------- ZHS TERMINAL 函数 返回用户的终端或机器的标识,如: SQL> select userenv('TERMINAL') from dual; USERENV('TERMINA ---------------- ZHAOYUANJIE VSIZE( ) 返回 x 的大小(字节)数,如: SQL> select vsize(user),user from dual; VSIZE(USER) USER ----------- ----------------------------- 6 SYSTEM §2.3 SQL 中的组函数 §2.3.1 多记录组函数 AVG( [ { DISTINCT | ALL}] ) 求平均值,ALL 表示对所有求平均值,DISTINCT 只对不 同的求平均值,相同只取一个。 74 SQL> l 1* select avg(sal) from emp SQL> / AVG(SAL) ---------- 2073.21429 MAX( [ { DISTINCT | ALL}] ) 求最大值,ALL 表示对所有求最大值,DISTINCT 只对不 同的求最大值,相同只取一个。 SQL> select max(sal) from emp; MAX(SAL) ---------- 5000 MIN( [ { DISTINCT | ALL}] ) 求最小值,ALL 表示对所有求最小值,DISTINCT 只对不同的求最小值,相同只取一个。 SQL> select min(sal) from emp; MIN(SAL) ---------- 800 STDDEV( [ { DISTINCT | ALL}] ) 求标准差,ALL 表示对所有求标准差,DISTINCT 只对不同的求标准差,相同只取一个。 SQL> select stddev(sal) from emp; STDDEV(SAL) ----------------- 1182.50322 VARIANCE( [ { DISTINCT | ALL}] ) 求协方差,ALL 表示对所有求协方差,DISTINCT 只对不同的求协方差,相同只取一个。 SQL> select variance(sal) from emp; 75 VARIANCE(SAL) ------------------------ 1398313.87 §2.3.2 带 GROUP BY 的计算 可以用 GROUP By 来实现对一组数进行分组统计(如 SUM,count(*) 等),如: 要列出部门代码、部门人数,部门工资总和,则用到 GROUP BY : SQL> select deptno,count(*) ,sum(sal) from emp group by deptno; DEPTNO COUNT(*) SUM(SAL) ---------- --------- ---------- 10 3 8750 20 5 10875 30 6 9400 §2.3.3 用 HAVING 来限制分组的计算 在分组 GROUP BY 中,一 般 都 不管 统计的结果是多少都要全显示,我们可以在 GROUP BY 前或后加 HAVING 子句来限制结果的统计,比如要求被统计的人数有 5 个人以上,则 有两方法可以实现: SQL> select deptno,count(*) ,sum(sal) from emp group by deptno 2 having count(*)>=5; DEPTNO COUNT(*) SUM(SAL) ---------- ---------- --------- 20 5 10875 30 6 9400 SQL> select deptno,count(*) ,sum(sal) from emp having count(*)>=5 2 group by deptno; DEPTNO COUNT(*) SUM(SAL) ---------- ---------- ---------- 76 20 5 10875 30 6 9400 §2.4 控制和格式化输出 §2.4.1 用 ORDER BY 子句来对结果进行排序 Oracle 提供 ORDER BY 子句,可用于对查询到的结果进行排序输出。这样的操作是在内存 中进行的。比如按照部门代码顺序和员工的工资多少顺序进行输出,需要命令: SQL> select deptno,ename,sal from emp order by deptno,sal desc; DEPTNO ENAME SAL --------- ---------- ---------- 10 KING 5000 10 CLARK 2450 10 MILLER 1300 20 SCOTT 3000 20 FORD 3000 20 JONES 2975 20 ADAMS 1100 20 SMITH 800 30 BLAKE 2850 30 ALLEN 1600 30 TURNER 1500 30 WARD 1250 30 MARTIN 1250 30 JAMES 950 这里的 DESC 表 sal(工资) 按照降序排列。 §2.4.2 用 BREAK 命令 来对结果进行排列 一般可以用 BREAK ON column SKIP xx 来对查询结果进行排列,BREAK ON 命令的参数 如下: clear breaks 清除所有的 break 定义 77 break on column 在该列上中断 break on row 在每一行上中断 break on Page 在每一页上中断 break on report 在每一报告上中断 skip n 跳过 n 行 skip page 跳过未用完的页 使用方法请看下面例子: SQL> break on deptno SQL> set pagesize 100 SQL> select deptno,ename,sal from emp order by deptno; DEPTNO ENAME SAL ---------- ---------- ---------- 10 CLARK 2450 KING 5000 MILLER 1300 20 SMITH 800 ADAMS 1100 FORD 3000 SCOTT 3000 JONES 2975 30 ALLEN 1600 BLAKE 2850 MARTIN 1250 JAMES 950 TURNER 1500 WARD 1250 已选择 14 行。 SQL> break on deptno skip 2 SQL> select deptno,ename,sal from emp order by deptno; DEPTNO ENAME SAL ---------- ---------- ---------- 10 CLARK 2450 KING 5000 MILLER 1300 20 SMITH 800 78 ADAMS 1100 FORD 3000 SCOTT 3000 JONES 2975 30 ALLEN 1600 BLAKE 2850 MARTIN 1250 JAMES 950 TURNER 1500 WARD 1250 SQL> break on deptno skip page SQL> select deptno,ename,sal from emp order by deptno; DEPTNO ENAME SAL ---------- ---------- ---------- 10 CLARK 2450 KING 5000 MILLER 1300 DEPTNO ENAME SAL ---------- ---------- ---------- 20 SMITH 800 ADAMS 1100 FORD 3000 SCOTT 3000 JONES 2975 DEPTNO ENAME SAL ---------- ---------- ---------- 30 ALLEN 1600 BLAKE 2850 MARTIN 1250 JAMES 950 TURNER 1500 WARD 1250 已选择 14 行。 79 §2.4.3 用 COMPUTE 命令对结果进行格式化 COMPUTE 命令 的语法如下: COMP[UTE] [function [LAB[EL] text] ... OF {expr|column|alias} ... ON {expr|column|alias|REPORT|ROW} ...] function 可以是下面参数之一 AVG 数字类型平均值 COU[NT] 所有类型的个数 MIN[IMUM] NUMBER, CHAR,NCHAR, VARCHAR2(VARCHAR), NVARCHAR2 (NCHARVARYI NG) 类型的最小值 MAX[IMUM] NUMBER, CHAR,NCHAR, VARCHAR2(VARCHAR), NVARCHAR2 (NCHARVARYI NG) 类型的最大值 NUM[BER] 计算所有类型的行数 SUM 计算所有非空数字类型的总和 STD 计算数字类型的标准差 DEV[IANCE] 计算数字类型的协方差 LAB[EL] text 显示的字符串。用它可以替换掉字段的显示。 OF {expr|column|alias} ... OF子串或表达式或别名 ON {expr|column|alias|REPORT|ROW} ... ON子串或表达式或别名或REPORT或ROW 例子: 按照员工是 "clerk"、"analyst"、"analyst"及 "salesman"进行工资小计 ,并加标记"TOTAL", 则: SQL> BREAK ON JOB SKIP 1 SQL> COMPUTE SUM LABEL ’TOTAL’ OF SAL ON JOB SQL> SELECT JOB, ENAME, SAL 2 FROM EMP 3 WHERE JOB IN (’CLERK’, ’ANALYST’, ’SALESMAN’) 4 ORDER BY JOB, SAL; The following output results: JOB ENAME SAL --------- ---------- ---------- ANALYST SCOTT 3000 FORD 3000 80 ********* ---------- TOTAL 6000 CLERK SMITH 800 JAMES 950 ADAMS 1100 MILLER 1300 ********* ---------- TOTAL 4150 SALESMAN WARD 1250 MARTIN 1250 TURNER 1500 ALLEN 1600 ********* ---------- TOTAL 5600 计算工资小于 1,000 的总和: SQL> COMPUTE SUM OF SAL ON REPORT SQL> BREAK ON REPORT SQL> COLUMN DUMMY HEADING ’’ SQL> SELECT ’ ’ DUMMY, SAL, EMPNO 2 FROM EMP 3 WHERE SAL < 1000 4 ORDER BY SAL; SAL EMPNO --- ---------- ----------- 800 7369 950 7900 ---------- sum 1750 计算平均和最大工资、部门: SQL> BREAK ON DNAME SKIP 1 SQL> COMPUTE AVG LABEL ’Dept Average’ -> MAX LABEL ’Dept Maximum’ -> OF SAL ON DNAME SQL> SELECT DNAME, ENAME, SAL 2 FROM DEPT, EMP 3 WHERE DEPT.DEPTNO = EMP.DEPTNO 4 AND DNAME IN (’ACCOUNTING’, ’SALES’) 81 5 ORDER BY DNAME; DNAME ENAME SAL -------------- ---------- ----------ACCOUNTING CLARK 2450 KING 5000 MILLER 1300 ************** ----------Dept Average 2916.66667 Dept Maximum 5000 SALES ALLEN 1600 BLAKE 2850 MARTIN 1250 JAMES 950 TURNER 1500 WARD 1250 ************** ----------Dept Average 1566.66667 Dept Maximum 2850 9 rows selected. 计算部门10和20 的工资总和,不打印: SQL> COLUMN DUMMY NOPRINT SQL> COMPUTE SUM OF SAL ON DUMMY SQL> BREAK ON DUMMY SKIP 1 SQL> SELECT DEPTNO DUMMY, DEPTNO, ENAME, SAL 2 FROM EMP 3 WHERE DEPTNO <= 20 4 ORDER BY DEPTNO; DEPTNO ENAME SAL ---------- ---------- ---------- 10 CLARK 2450 10 KING 5000 10 MILLER 1300 ---------- 8750 20 SMITH 800 20 ADAMS 1100 20 FORD 3000 20 SCOTT 3000 82 20 JONES 2975 ---------- 10875 8 rows selected. 在报告结束不打印计算工资总和: SQL> COLUMN DUMMY NOPRINT SQL> COMPUTE SUM OF SAL ON DUMMY SQL> BREAK ON DUMMY SQL> SELECT NULL DUMMY, DEPTNO, ENAME, SAL 2 FROM EMP 3 WHERE DEPTNO <= 20 4 ORDER BY DEPTNO; DEPTNO ENAME SAL ---------- ---------- ---------- 10 CLARK 2450 10 KING 5000 10 MILLER 1300 20 SMITH 800 20 ADAMS 1100 20 FORD 3000 20 SCOTT 3000 20 JONES 2975 ---------- 19625 8 rows selected. §2.5 配置会话环境 一般在 SQL>下进行 SQLPLUS 操作,都需要进行必要的环境设置才能完成我们所需要 的输出。所有环境的设置由 SET 命令加相应的环境变量来完成。下面是常用的环境设置: §2.5.1 ARRAYSIZE(取回的行数) SET ARRAY[SIZE]{integer} 一次可以提取(Fetch)的行的数目,1->5000,当有较长字段时应设小些。 83 §2.5.2 AUTOCOMMIT(自动提交) SET AUTO [COMMIT] { [ OFF | ON | IMM | n] } 用于在操作中是自动提交或是部分提交或是不自动提交。 1) ON 或 IMM 使得在完成每条 SQL 语句时将未提交的改变立刻提交给数据库系统。 2) N 允许在用户发出 COMMIT 后,可以执行命令的数量(将 n 条 SQL 语句所做的改变进 行提交)。 3) OFF 停止自动提交,用户必须用 COMMIT 命令才能被提交。 §2.5.3 LINESIZE(行显示宽度) 可以设置 LINESIZE 环境变量来控制行的显示宽度,缺省是 80 个字符。 SET Lin[esize]{80|integer} Integer = 设置行宽度(字符个数),最大值 999,如: SQL>set linesize 160 §2.5.4 LONG(长类型显示字节数) 在缺省的 SQL> 状态下,SQL>缓冲区用于显示 LONG 的字节数只有 80 个字符。如果我们需要 查询的列中含有 LONG 类型的字段的话,就需要将 LONG 缓冲区设置大些。 SET LONG{80|integer} Integer 是 显示或拷贝 long 值的最大宽度, n=1->32767(但必须小于 Maxdata 值) SQL>show Maxdata (最大行宽) SQL>set long 2000 §2.5.5 PAGESIZE(页行数) 在缺省的 SQL> 状态下,SQL>缓冲区显示页的行数是 24 行,其中 22 行显示数据,2 行显示标 题和横线。我们将 pagesize 设置大些以减少提示标题和横线。 SET pag[esize] {24|integer} SQL>SET pagesize 66 84 §2.5.6 PAUSE(暂停) 可以设置 PAUSE 为 ON 或 OFF 来控制屏幕显示。当设置为 ON 时,在 select 语句发出后需 要按 Enter 键才能显示一屏。 SET PAUSE [ ON | OFF ] SQL> set pause on 提示:在发出 select 语句并按 Enter 键后 还要再按 Enter 键才能显示结果. §2.5.7 SPACE(列间空格) 可用 set space 来设置各列间的空格数,语法为: SET SPA[CE] {1|n} N 为设置输出行列间的空格数,最大为 10。 SQL>set space 2 建议:在一般情况下,不用设置 space 参数。 §2.5.8 Termout (启/停屏幕显示) TERMOUT 用于设置在屏幕上显示或不显示所输出的信息。 SET TERMOUT { ON | OFF } set termout off set termout on set termout off 常用 SPOOL XXX 时,即关闭报表在屏幕上的显示(节省时间) set termout on 常用 SPOOL off 之后,即恢复报表在屏幕上的显示 §2.5.9 ECHO (启/停命令显示) 可以用 ECHO 命令来显示或不显示所执行的 SQL 命令。语法如: SET ECHO{OFF|ON} 显示执行当中的各命令( 即用 start 时) set echo 受到 set termout 的影响 set pagesize 100 set echo on 85 select table_name from dict where rownum<20; select * from cat where rownum<30; set echo off --下面只显示结果不显示命令: select table_name from dict where rownum<20; select * from cat where rownum<30; §2.5.10 TRANSACTION (启动事务) 一个很重要的事务环境设置是 TRANSACTION。它包括两个部分的内容: SET TRANSACTION { READ ONLY | USE ROLLBACK SEGMENT segment_name } READ ONLY 是用于保证读的一致性。即其他用户的修改不影响当前查询结果。 USE ROLLBACK SEGMENT segment_name 是为当前所处理的事务指定专门的回滚段。这主 要是在进行大量的 Insert 或 Delete 或 Update 时,需要一个大的回滚段以保证事务正常完成。 详细见数据库管理员。 §2.5.11 SHOW ALL(列出所有参数) 可以用 SHOW ALL 来显示当前的所有参数情况。它的用法很简单。比如: SQL> show all appinfo为 ON 并且已设置为"SQL*Plus" arraysize 15 autocommit OFF autoprint OFF autorecovery OFF autotrace OFF blockterminator "." (hex 2e) btitle OFF and 为下一条 SELECT 语句的前几个字符 cmdsep OFF colsep " " compatibility version NATIVE concat "." (hex 2e) copycommit 0 COPYTYPECHECK 为 ON define "&" (hex 26) describe DEPTH 1 LINENUM OFF INDENT ON markup HTML OFF SPOOL OFF ENTMAP ON PREFORMAT OFF echo OFF editfile "afiedt.buf" embedded OFF 86 escape OFF flagger OFF flush ON heading ON headsep "|" (hex 7c) instance "local" linesize 80 lno 14 loboffset 1 logsource "" long 80 longchunksize 80 newpage 1 null "" numformat "" numwidth 10 pagesize 14 PAUSE 为 OFF pno 0 recsep WRAP recsepchar " " (hex 20) release 801070000 repfooter OFF and 为 NULL repheader OFF and 为 NULL serveroutput OFF shiftinout INVISIBLE showmode OFF spool OFF sqlblanklines OFF sqlcase MIXED sqlcode 0 sqlcontinue "> " sqlnumber ON sqlprefix "#" (hex 23) sqlprompt "SQL> " sqlterminator ";" (hex 3b) suffix "sql" tab ON termout ON time OFF timing OFF trimout ON trimspool OFF ttitle OFF and 为下一条 SELECT 语句的前几个字符 87 underline "-" (hex 2d) USER 为"SYS" verify ON wrap : 行将为已换行 SQL> 你可以从上面的参数中看到其当前值,也可以修改某些参数的值。 §2.6 格式化输出 §2.6.1 一般数据的格式化输出 在 Oracle 的 SQL> 下,经常用 COLUMN 命令来对所输出的列进行格式化,即按照一定 的格式进行显示。COLMUN 命令语法如下: COL[UMN] [{ column | expr } [ option_1 ... option_n ] ] column :列名 expr :有效的 SQL 表达式 option_1... option_n:可以是下列之一: ALI[AS] alias CLE[AR] FOLD_A[FTER] FOLD_B[EFORE] FOR[MAT] format HEA[DING] text JUS[TIFY] {L[EFT]|C[ENTER]|C[ENTRE]|R[IGHT]} LIKE {expr|alias} NEWL[INE] NEW_V[ALUE] variable NOPRI[NT]|PRI[NT] NUL[L] text OLD_V[ALUE] variable ON|OFF WRA[PPED]|WOR[D_WRAPPED]|TRU[NCATED] 下面给出常用的关键字的解释: Alias 给出列的别名,BREAK和COUMN可以引用所定义的别名。 CLEAR 取消列的定义。 FORMAT 列显示格式,format为: 9999990 9或0的个数决定最多显示多少位 88 9,999,999.99 按照逗号和小数点来 显示数据,若是0以空格显示 099999 显示前面补0 $999,999.99 数字前加美圆号 B99999 若为0 ,则结果为空白 99999Mi 若数字为负,则负号放在数字后(右边),缺省放在左边 99999PR 负号将以括号括起 9.999EEEE 以科学记数法表示(必须有4个E) 999V99 数字乘以 10n ,如 1234变为 123400 DATE 采用日期数字格式(MM/DD/YY) Heading 重新标记列的显示标题,如: SQL> col ename heading 姓名 format a10 SQL> select ename,sal from emp; 例子: SQL COLUMN SALARY FOR $9,999,999.99 COLUMN LAST_NAME FOR A35. §2.6.2 日期的格式化输出 Oracle 系统提供了一个 NLS_DATE_FORMAT 的环境变量来设置日期的显示格式。用 它 可以 完 成 按照不同格式要求的显示,比如按照中国的习惯为 yyyy年 mm月 dd 日等。 1.系统日期 sysdate 的显示 用 sysdate 可以显示 ORACLE RDBMS 所在机器的日期及时间,如: SQL> alter session set nls_date_format ='"公元"yyyy"年"mm"月"dd"日"'; 会话已更改。 SQL> select sysdate from dual; SYSDATE ------------------ 公元 2001 年 05 月 30 日 2.日期类型的显示 select sysdate,to_char(sysdate,’yyyy.mm.dd hh24:mi;ss’) from dual; 89 SQL> connect scott/tiger 已连接。 SQL> alter session set nls_date_format ='yyyy"年"mm"月"dd"日生"'; 会话已更改。 SQL> col HIREDATE heading 生日 SQL> col sal heading 工资 SQL> col sal ename 姓名 SQL> select ename,sal,hiredate from emp; 姓名 工资 生日 ---------- ---------- ----------------- SMITH 800 1980 年 12 月 17 日生 ALLEN 1600 1981 年 02 月 20 日生 WARD 1250 1981 年 02 月 22 日生 JONES 2975 1981 年 04 月 02 日生 MARTIN 1250 1981 年 09 月 28 日生 BLAKE 2850 1981 年 05 月 01 日生 CLARK 2450 1981 年 06 月 09 日生 SCOTT 3000 1987 年 04 月 19 日生 KING 5000 1981 年 11 月 17 日生 TURNER 1500 1981 年 09 月 08 日生 ADAMS 1100 1987 年 05 月 23 日生 JAMES 950 1981 年 12 月 03 日生 FORD 3000 1981 年 12 月 03 日生 MILLER 1300 1982 年 01 月 23 日生 已选择 14 行。 §2.7 加标题 有时在输出一些结果时,可能需要加一些标题,如表上面的顶标题,落款等。这样的要 求可由 Ttitle 和 Btitle 来完成。 ttitle 和 btitle ttitle [center|left|right]string 顶标题 btitle [center|left|right]string 底标题 ttitle center 'XX 公司人员情况表' btitle left '制表人:xxxx' right '日期:xxxx 年 xx 月' Clear ttitle 90 §2.8 建立简单报告 我们可以用 TTITLE、BTITLE、COLUMN、BREAK ON、COMPUTE SUM 及 SET LINESIZE、 SET PAGESIZE、SET NEWPAGE 来设置查询结果的显示格式;在用 SPOOL 命令将显示结 果输出到一个操作系统文件中去,一般输出文件的类型为.LST。 建立简单报告主要使用下面命令来实现: 1. SPOOL 命令 SPOOL filename 将缓冲区的内容写到文件中 SPOOL off 终止写命令 2. COLUMN 命令 column col_name[,heading] format format_spe 把字段的结果指定为一种输出格式 COL name heading '姓名' for a10 COL sal heading '工资' for 9,999.99 3.ttitle、btitle ttitle [center|left|right]string 顶标题 btitle [center|left|right]string 底标题 ttitle center 'XX 公司人员情况表' btitle left '制表人:赵元杰' right '日期:1998.11 月' Clear ttitle 4.break、compute clear breaks,clear computes break on column 在该列上中断 break on row 在每一行上中断 break on Page break on report skip n 跳过 n 行 skip page 跳过未用完的页 compute avg compute count compute max 91 compute min compute std compute sum compute var compute num 计算所有行 compute sum of sal on deptno 5.set 在报表中的设置 l set termout off、set termout on 命令 l set termout off 常用 SPOOL XXX 前,即关闭报表在屏幕上的显示(节省时 间) l set termout on 常用 SPOOL off 之后,即恢复报表在屏幕上的显示 l set ECHO{OFF|ON} 显示执行当中的各命令(即用 start 时),set echo 受 到 set termout 的影响 l set Lin[esize]{80|integer} 设置行宽度,最大值 999 l set pag[esize] {24|integer} 设置页的大小 例子: SQL>COL ename heading ‘姓名’ for a12 SQL>COL sal heading ‘工资’ for a999,999.99 SQL>COL hiredate heading ‘出生’ SQL>SET LINESIZE 200 SQL>SET PAGESIZE 60 SQL>SPOOL c:\all_emp SQL>select ename,sal,deptno,hiredate from emp order by deptno; SQL>SPOOL OFF §2.9 输入变量 Oracle 提供一种在处理 SQL 语句时可以将参数作为变量来对待的技术,即在条件句中可 以是变量而不是具体的值,这样的处理就是输入变量。这样做的目的就是可以重复使用同样 的语句,每次只要输入相应的值即可。要实现将参数写成为变量,只要在变量前加一个&号 即可。看下面语句: Select sid, serial#,username, command from v$session Where USERNAME = upper(‘&usr’); 这样的语句在运行中,系统会自动提示你回答变量的具体值,上面语句运行时提示和回答时 显示的信息如下: SQL> Select sid, serial#,username, command from v$session 2 Where USERNAME = upper('&usr'); 92 输入 usr 的值: sys 原值 2: Where USERNAME = upper('&usr') 新值 2: Where USERNAME = upper('sys') SID SERIAL# USERNAME COMMAND ---------- ---------- ------------------------------ ---------- 7 26 SYS 3 在变量说明中,可以使用多个变量,比如: Alter system kill session ‘&sid,&ser’; 或 Alter system kill session ‘&会话号,&序列号’; 它的运行情况如下: SQL> Select sid, serial#,username, command from v$session; SID SERIAL# USERNAME COMMAND ---------- ---------- ------------------------------ ---------- 1 1 0 2 1 0 3 1 0 4 1 0 5 1 0 6 1 0 7 26 SYS 3 8 16 ZHAO 0 已选择 8 行。 SQL> Alter system kill session '&sid,&ser'; 输入 sid 的值: 8 输入 ser 的值: 16 原值 1: Alter system kill session '&sid,&ser' 新值 1: Alter system kill session '8,16' 系统已更改。 一般系统缺省下是使用 “&” 符号来定义变量,你也可以使用另外的符号来代替,比如不喜 欢用 & 而要用 ?,则有: SQL> set define ? 93 SQL> select sid,serial#,username from v$session where username='?usr'; 输入 usr 的值: SYS 原值 1: select sid,serial#,username from v$session where username='?usr' 新值 1: select sid,serial#,username from v$session where username='SYS' SID SERIAL# USERNAME ---------- ---------- ------------------------------ 7 26 SYS 次时由于我们修改了会话环境的参数值,可以用下面命令查看: SQL> show define define "?" (hex 3f) 94 第三章 表及索引的定义操作 在 ORACLE 数据库系统中,表是数据库的基本对象,与桌面数据库中的文件类似,我们可 以把所有的基本实体都看成为表,不管应用中的表有多复杂,都可以使用(拆成)一个或多 个表来表示。用以存放实体的数据。下面针对建表所需要的知识作简单的介绍。 §3.1 建立表结构 建立表结构是每个应用系统都必须进行的工作。由于建立表结构是一项统一规划和统 一设计的工作。应该是由总设计师根据用户的具体应用需要来定。表的设计是否合理关系到 应用系统将来的成败与性能问题。因此,任何担当总设计师角色的人都不要轻视这项工作。 §3.1.1 建立表结构命令 由于创建表的命令非常长,这里仅给出一些主要的部分,详细的请参考《ORACLE8i SQL REFERENCE》 。 CREATE TABLE 命令简要语法如下: CREATE TABLE [USER.] table_name ( { COLUMN1 DATATYPE [DEFAULT EXPN] [COLUMN_CONSTRAINT] |TABLE_CONSTRAINT } [, { COLUMN1 DATATYPE [DEFAULT EXPN] [COLUMN_CONSTRAINT] | TABLE_CONSTRAINT }] ... ) [CLUSTER CLUSTER (COLUMN1 [,COLUMN2] ...) ] [PCTFREE N] [PCTUSED N] [INITRANS N] [MAXTRANS N] [STORAGE N] [TABLESPACE TABLESPACE] [ ENABLE | DISABLE] [ AS QUERY] 其中: schema 包括基表的模式(缺省:当前用户的帐号) table_name 表名 column 列名(字段名),ORACLE7 最多 254 列,ORACLE8 可达 1000 个列。 95 datatype 列数据类型 DEFAULT 当前列的缺省值(常数) Column constraint 列约束 Table_constraint 表约束 PCTFREE 用于更新(update)的空间百分比(1-99) 0 表示在插入时完全填满数据块,缺省为 10 PCTUSED 为表的每个数据块保留的可用空间的最小百分比. 取值 1-99,缺省为 40。 PCTFREE 和 PCTUSED 的组合决定了将插入的数据放入已存在的数据块还是放入一个新的块中。 INITRANS 指定一个在每一个数据块中分配的事务入口的初始数 1-255, 缺省为 1,每一个更新块的事务都需要在块中有一个事务入口 (大小依 OS),一般不需要指此参。 MAXTRANS 指定用于更新分配给表的数据块的并发事务的最大数,1- 255,用户一般不应改此参。 TABLESPACE 表空间。如果缺省则表建在用户缺省的表空间(如果建立用户不指定表空间 则该用户的缺省表空间为 system)。 STORAGE 存储分配参数 INITIAL integer 初始大小 NEXT integer 下一次的大小 MINEXTENTS integer 最小分配次数 MAXEXTENTS integer 最大分配次数 PCTINCREASE integer 增长百分比(>=0) ENABLE 激活完整性约束 DISABLE 取消完整性约束 As subquery 建表中查出数据给新表,此语句如果使用,则表的数据类型不需指定, 而是继承原表的类型。 FREELIST GROUP 在并行服务器中指定表或分类、索引组的列表数目。 FREEUST 在并行服务器中指定表、簇、索引的列表数。 提示 1: 一般情况下,如果表含有 long 字段,这样势必需大量 的空间,系统会在每次插入新记录时, 经常分配空间给表,不久就会出现: "ORA-01547:Failed to allocate extent of size xxxxx in tablespace 'xxxx' " 此种情况如果表空间还剩较多的连续空间的话。则可能是该表分配的空间次数已达最 大值。为了对该表能插入新数据,需对该表的存储参数作修改,比如: SQL>alter table xxx storage(MAXEXTENTS 999 ) ; 提示 2:建议不要对表结构或索引使用 pctincrease 大于 0 的参数以避免将来在运行中产生 空间超支问题. 提示 3:建立表结构最重 要的部分是存储参数(STORAGE )的说明。设置者要特别重视存储参 数的估计,设置合理的大小。详细见〈Oracle8i/9i 初级数据库管理〉 96 §3.1.2 建立表结构例子 例 1:在 SCOTT 模式下建立表 emp,并指定表空间和存储参数: Create table scott.emp ( Empno number(5) primary key, Ename varchar2(15) not null, Job varchar2(10), Mgr number(5), Hiredate date default sysdate, Sal number(7,2) CHECK(sal>100), Comm number(3) default 0.0 , Dept number constraint dept_fkey References scott.dept ) Tablespace users PCTFREE 10 PCTUSED 70 STORAGE ( INITIAL 50K NEXT 50k MAXEXTENTS 10 ); 例 2:在建立表过程中对有限制的列使用 NOT NULL: CREATE TABLE CHECKUP_HISTORY (CHECKUP_NO NUMBER(10,0) NOT NULL, ID_NO NUMBER(10,0), CHECKUP_TYPE VARCHAR2(30), CHECKUP_DATE DATE, DOCTOR_NAME VARCHAR2(50)); 本例除了要求 CHECKUP_NO 非空外,其它无任何限制. 例 3:在建立表时指定列 CHECKUP_TYPE 为外部列: CREATE TABLE SEAPARK.CHECKUP_HISTORY ( CHECKUP_NO NUMBER(10) NOT NULL, ID_NO NUMBER(10,0), 97 CHECKUP_TYPE VARCHAR2(30), CHECKUP_DATE DATE, DOCTOR_NAME VARCHAR2(50), FOREIGN KEY (CHECKUP_TYPE) REFERENCES SEAPARK.CHECKUP (CHECKUP_TYPE), PRIMARY KEY (CHECKUP_NO) ) PCTFREE 20 PCTUSED 60 INITRANS 2 MAXTRANS 255 STORAGE ( INITIAL 1250K NEXT 2K MINEXTENTS 1 MAXEXTENTS 121 Pctincrease 0) TABLESPACE user_data; 例子指定了所有者,主键,外部键,表空间及存储参数等,主键和外部键在后面章节介绍。 §3.1.3 建立临时表结构 Oracle 现在可以使用 CREATE GLOBAL TEMPORARY TABLE 命令来实现建立临时表结构。这样的 表它的数据只在用户会话期间存在,当会话完成后就自动清除。看下面例子: SQL> create global temporary table myemp as select * from emp; 表已创建。 SQL> desc myemp 名称 空? 类型 ----------------------------------------- -------- -------------- ENAME VARCHAR2(20) SAL NUMBER(9,2) DEPTNO NUMBER(4) TEL VARCHAR2(20) SQL> select * from myemp; 未选定行 SQL> insert into myemp values('赵元杰',32456.99,10,'12'); 98 已创建 1 行。 SQL> select * from myemp; ENAME SAL DEPTNO TEL -------------------- ---------- ---------- ------------------ 赵元杰 32456.99 10 12 SQL> connect sys/sys 已连接。 SQL> connect zhao/zhao 已连接。 SQL> l 1* select * from myemp SQL> / 未选定行 从上面可看出当连接到 SYS 在连接回来后数据就不存在了。对于临时表,可以用 DROP TABLE 来删除其结构。如: SQL> drop table myemp; 表已丢弃。 §3.3 修改表结构 修改表结构是对已经创建完成(实际是存放在数据库字典里)的表的结构进行修改。不同的 Oracle 版本允许对表的修改也不一样。新版的 Oracle8i 可以对表中的列进行删除。 §3.3.1 修改表结构命令 修改表结构的命令由 ALTER TABLE 来完成。该命令的参数较多,下面仅给出一些基本的部分。 详细请参考《ORACLE8i SQL REFERENCE》 。 ALTER TABLE [user.] table [ADD ({colum_element|table_constraint} [,{column_element|table_constraint}]...)] [MODIFY(column_element[,column_element]...)] [DROP CONSTRAINT constraint]... 99 [PCTFREE integer][PCTUSED integer] [INITRANS integer][MAXTRANS integer] [STORAGE storage] [BACKUP] ALTER TABLE 可以作的操作有: l 增加一个列(字段)宽度; l 减少一个列(字段)宽度(该列必须无数据); l 增加一个列(字段); l 修改列的定义 ; l 或一个限制;(如数据类型,NOT NULL);仅当某列的值为空时才能修改其类型; l 去掉限制; l 修改存储分配; l 记录表已作过 BACKUP; l 删除已存在的列(仅 Oracle8i 及以后版本); l 重新定位和组织表(仅 Oracle8i 及以后版本); l 将表标识为不可用(仅 Oracle8i 及以后版本)。 §3.3.2 修改表结构例子 例 1:对已经存在的表增加一新的列: SQL>alter table dept add ( headcount number(3) ); 例 2:对表的列修改其大小: SQL>alter table dept modify( Dname char(20) ); 如果被修改的列没有空(已有数据),则被提示: ORA-01439: Column to be modified must be empty to change datatype ORA-01441: Column to be modified must be empty to decrease column length 例 3:复制一个表: CREATE TABLE HOLD_TANK AS SELECT TANK_NO, CHIEF_CARETAKER_NAME FROM TANK; 100 例 4:参照某个已存在的表建立一个表结构(不需要数据) create table emp2 as select * from emp where rownum<1; 例 5:修改已存在表存储参数: Alter table emp2 storage( next 256k pctincrease 0 ); 例 6:删除表中的列: 这是 Oracle8i 的新功能,它的基本语法为: ALTER TABLE . . . . . . DROP COLUMN [ CASCADE CONSTRAINTS ]; 如: Alter table emp drop column comm ; 例 7:重新定位和组织表: 这是 Oracle8i 的新功能,可以实现: l 将未分区的 表从一个表空间移到另一个表空间; l 重新组织一个未分区表的存储。 它的基本语法为: ALTER TABLE . . . . . . MOVE TABLESPACE ; 如: Alter table emp move tablespace users; 例 8:将表标识为不可用: 这是 Oracle8i 的新功能,可以实现对空间的收回等。 基本语法为: ALTER TABLE . . . . . . SET UNUSED COLUMN; 如: Alter table emp set UNUSED COLUMN xyz; 提示:虽然 Oracle 允许用户对表的结构进行修改。但建议你在工作中不要采用方式。因为 表结构被多次修改会影响应用系统的性能。 101 §3.3.3 删除表结构 Oracle 提供 DROP TABLE 命令可以实现删除表数据和结构。提醒初学者,不要轻易使用 DROP TABLE 命令。DROP TABLE 命令语法: DROP TABLE [user.]table_name[CASCADE CONSTRAINTS] CASCADE CONSTRAINTS 表示所有指向本表的主键,外部键被删掉。当删除一个表时,下面的 对象也随之被删掉。 l 表的索引; l 指向本表的外部键; l 本表的触发器; l 本表中的分区; l 本表的快照; l 本表的角色和用户权限; l 加在本表的所有限制。 提示:如果你在定义表结构时,采用了主键、外部键来定义了一序列表。则在删除表结构时 要小心。不要轻易用 CASCADE 子句。 §3.3.4 使用 CHECK 作限制约束 Oracle 提供了一个很有用的子句 CHECK,它可以实现对数据的自动检查。它的用法是在创建 表结构时使用。如: Create table worker ( empno number(4) primary key, name varchar2(10), age number(2) CHECK(age between 18 and 65 ), /* age number(2) CHECK( age >=18 and age<=65 ) */ lodging char(15) References LODGING(lodging) ); Create table emp3 ( empno number(4) constraint abc primary key, ename varchar2(10), job varchar2(10), sex char(2) check ( sex=‘男’ or sex= ’女’), mgr number(4), 102 hiredate date, sal number(7,2), /* 工资 */ comm number(7,2), /* 奖金 */ deptno number(2), CHECK ( sal+comm >0 and sal+comm<=5000 ) ); 建议:在设计数据库表结构时,建议你分析用户的数据的取值范围,从而将那些取值范围一 定的字段用 CHECK 进行描述。以保证以后数据的正确性。 §3.3.5 使用 UNRECOVERABLE 创建表 对于特殊的需要,可以考虑将表创建成为不需恢复(UNRECOVERABLE)的表。如复制一 个已存在的表就可以采用这种方法以减少系统的开销。如: 例:参考 emp表创建一个新的 emp_new 表: SQL> create table new_emp as select * from emp UNRECOVERABLE; 表已创建。 或 CREATE TABLE new_emp AS select * from emp NOLOGGING; 注:虽然上面提到 UNRECOVERABLE,但是 Oracle 推荐你使用 NOLOGGING 或 LOGGING; §3.3.6 将表移动到新的数据段或新的表空间 最新的 Oracle8i 版本可以用 Alter table … MOVE 语句将表移动到一个新的段或新表空 间上,这样可以实现对不合理存储参数进行修改,包括用一般的 ALTER TABLE 不能修改的 参数。如: 例 1:通过移动来实现存储参数的修改: Alter table emp MOVE STORAGE(INITIAL 1m next 512k minextents 1 maxextents 999 pctincrease 0 ); 例 2:将那些使用 system 表空间 的对象移动到合适的表空间中: 1)移动前表所使用的表空间情况: 103 SQL> select tablespace_name,table_name,initial_extent from user_tables; TABLESPACE_N TABLE_NAME INITIAL_EXTENT ---------------------- ----------------------- ---------------------------- SYSTEM ABC 65536 SYSTEM BONUS 65536 SYSTEM DEPT 65536 SYSTEM EMP 65536 SYSTEM EMP2 65536 SYSTEM EMP3 65536 SYSTEM EMP4 65536 USERS PAY_LST_DET 1048576 SYSTEM PLAN_TABLE 65536 SYSTEM SALGRADE 65536 USERS UNIT_INF 1048576 11 rows selected. 2)用 Alter table . . . MOVE 语句对表进行移动,下面例子对表进行移动并重新指定存储参 数。 SQL> alter table emp move tablespace user_data 2 storage(initial 128k next 128k minextents 1 pctincrease 0); Table altered. SQL> alter table dept move tablespace user_data 2 storage(initial 128k next 128k minextents 1 pctincrease 0); Table altered. SQL> alter table BONUS move tablespace user_data 2 storage(initial 128k next 128k minextents 1 pctincrease 0); Table altered. 3)移动后的表及表空间的情况: SQL> select tablespace_name,table_name,initial_extent from user_tables; TABLESPACE_N TABLE_NAME INITIAL_EXTENT ----------------------- ------------------------- --------------------------- SYSTEM ABC 65536 USER_DATA BONUS 131072 104 USER_DATA DEPT 131072 USER_DATA EMP 131072 SYSTEM EMP2 65536 SYSTEM EMP3 65536 SYSTEM EMP4 65536 USERS PAY_LST_DET 1048576 SYSTEM PLAN_TABLE 65536 SYSTEM SALGRADE 65536 USERS UNIT_INF 1048576 11 rows selected. §3.3.7 手工分配表的存储空间 使用 ALTER TABLE 加 ALLOCATE EXTENT 选项来实现分配一个指定的空间。如: ALTER TABLE emp ALLOCATE EXTENT (SIZE 5K INSTANCE 4); §3.3.8 标记不使用的列和删除不使用的列 前面介绍过,新版的 Oracle8I 可以删除某个 列。如: 例:从 LONG_TAB 表中将 LONG_PICS 列删除掉: ALTER TABLE LONG_TAB DROP COLUMN LONG_PICS; 可以使用 ALTER TABLE . . . SET UNUSED 语句实现将表中的列设置为不用的状态以达 到快速处理的目的。其结果是: 1) 在显示结果时看不到该列; 2) 不删除该列的数据(但可以将该列删掉); 例: SQL> select * from emp; EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO ---------- ------------ ------------------- ---------- ---------------- ------------ ----------- ---------- 7369 SMITH CLERK 7902 17-DEC-80 800 20 105 7499 ALLEN SALESMAN 7698 20-FEB-81 1600 300 30 7521 WARD SALESMAN 7698 22-FEB-81 1250 500 30 7566 JONES MANAGER 7839 02-APR-81 2975 20 7654 MARTIN SALESMAN 7698 28-SEP-81 1250 1400 30 7698 BLAKE MANAGER 7839 01-MAY-81 2850 30 7782 CLARK MANAGER 7839 09-JUN-81 2450 10 7788 SCOTT ANALYST 7566 19-APR-87 3000 20 7839 KING PRESIDENT 17-NOV-81 5000 10 7844 TURNER SALESMAN 7698 08-SEP-81 1500 0 30 10 rows selected. SQL> alter table emp2 set unused(comm); Table altered. SQL> select * from emp; EMPNO ENAME JOB MGR HIREDATE SAL DEPTNO ------------ ----------- --------------- ---------- --------------- ---------- ---------- 7369 SMITH CLERK 7902 17-DEC-80 800 20 7499 ALLEN SALESMAN 7698 20-FEB-81 1600 30 7521 WARD SALESMAN 7698 22-FEB-81 1250 30 7566 JONES MANAGER 7839 02-APR-81 2975 20 7654 MARTIN SALESMAN 7698 28-SEP-81 1250 30 7698 BLAKE MANAGER 7839 01-MAY-81 2850 30 7782 CLARK MANAGER 7839 09-JUN-81 2450 10 7788 SCOTT ANALYST 7566 19-APR-87 3000 20 7839 KING PRESIDENT 17-NOV-81 5000 10 7844 TURNER SALESMAN 7698 08-SEP-81 1500 30 10 rows selected. SQL> desc emp Name Null? Type ----------------------------------------------------------------- -------- ------------ EMPNO NUMBER(4) ENAME VARCHAR2(10) JOB VARCHAR2(9) MGR NUMBER(4) HIREDATE DATE SAL NUMBER(7,2) DEPTNO NUMBER(2) 106 可以用 ALTER TABLE . . . DROP UNUSED COLUMNS 来删除不使用的列。它可以在物理上 删除表的未使用的列,并重新声明磁盘空间。在使用该语句时可以在后面加上 checkpoint 检 查点关键字。它可以产生一个检查点。使用检查点可以在删除数据列的操作过程中减少恢复 日志的容量积累,从而避免回滚段的空间消耗。 如: SQL> alter table emp drop unused columns checkpoint; Table altered. 注意:删除表中未使用列时不需要指定列名,它是根据 alter table emp set unused(comm); 语 句来删除未使用的列。 §3.3 主键 ORACLE 系统提供一个关键字 primary key 来建立一个主键。所 谓 主 键 ,就 是在一个表 内该列具有唯一的值。一 旦 你 为 一个表的一列或几个列建立了主键,则 ORACLE 就自动为该 表建立一个唯一索引。 §3.3.1 创建主键 要想为表的某个列建立主键,可以用 Alter table 或 CREATE TABLE 命令完成。 1 在建表结构中创建主键 CREATE TABLE [schema.]table_name … [SCOPE IS [user.]scope_table_name][column_constraint]… . . . . . . 例 1: CREATE TABLE dept (deptno number(2), dname varchar2(20), loc varchar2(20), CONSTRAINT pk_dept PRIMARY KEY (deptno) ); 107 2 用 alter table 创建主键 ALTER TABLE [schema.]tablename ADD ( constraint_name PRIMARY KEY (column1 [,column2,...]) 例 2: ALTER TABLE PARK_REVENUE ADD(park_rev_pk PRIMARY KEY ( ACCOUNT_NO)); 例 3: create table dept (deptno number(5) primary key, dname varchar2(20), loc varchar2(30)) disable primary key; 注:当主键被说明为 disable primary key 时,不能建立相应的外部键。一定先用: alter table dept enable primary key 后方可使用: deptno constraint fk_deptno References dept(deptno) 3 唯一索引和主键区别 唯一索引:唯一索引使用 CREATE UNIQUE INDEX 命令完成,能标识数据库表中一行的关键字。 在数据字典中建立了唯一索引名字。 主 键:主键使用 primary key 来指定,能标识数据库表中一行的关键字。在数据字典 中也建立了唯一索引名字。 差 别:被定义为唯一索引的列可以空,而被定义为主键的列不能空。 4 建立索引、主键的方法: 在建表命令中用 Constraint 说明详见《oracle8i sever SQL Reference》或者 Help constraint 得到语法说明。 Create table dept (deptno number(2), dname varchar2(40) constraint unq_dname unique, loc varchar2(50) ); 108 constraint unq_dname unique 可以允许 dname 没有值,这样未指定空间分配参数的语 句,oracle 采用缺省参数为 unq_dname 分配空间. 同样可以用下面命令达到如上的效果: Create table dept (deptno number(2), dname varchar2(20), loc varchar2(20), constraint unq_dname unique(dnam) using index pctfree 20 tablespace users_x STORAGE(initial 8K next 6k) ); constraint unq_dname unique 可以允许 dname 没有值,并指定空间分配参数的语 句,oracle 将根据参数为 unq_dname 分配空间. Create table dept (dept number(2) constraint pk_dept primary key, dname varchar2(20), loc varchar2(20) ); 同样可以用下面命令完成上面的说明: Create table dept (deptno number(2), dname varchar2(20), loc varchar2(20), constraint pk_dept primary key (deptno) ); 建立完表结构后再建索引、主键: 优点:索引可以放在另一表空间中,如果在表中直接写,则必须用 using index 说明分配 大小、表空间等。 Alter table ship_cont Add primary key(ship_no,container_no) Disable 一般声明主键时,可以让其有效(缺省),也可以使其无效(Disable) 建议:在程序开发调试中,经常先将主键设为 Disable ,上面的 ship_no ,container_no 一 109 起组成主键,这种两个以上的字段组成的叫组合键(最多 16 个字段),不要指定过多的组合 键以避免出现性能下降. §3.3.2 改变主键 命令语法详见 alter table 命令 限制: 不许修改作为主键的列; 不许修改作为主键的名字 可以: 可以定义一主键;或使主键无效 ALTER TABLE [schema.]tablename DISABLE constraint_name 例 1: Alter table dept Disable scott.pk_dept; 这样,如果有一外部键依赖于该主键,则系统给出下列错误: ORA-02297: Cannot disable constraint ( scott.pk_dept)- Depentencies exist. 在这种情况下,必须先删掉依赖于该主键的外部键并使该外部键无效,然后查才能使主键无 效。 §3.3.3 删除主键 ALTER TABLE [schema.]tablename DROP CONSTRAINT constraint_name [CASCADE] 删除顺序: 1) 使该外部键无效,删掉依赖于该主键的外部键; 2) 使该主键无效,删掉该主键 或: 当在删掉主键命令后加参数 CASCADE , 则在删掉主键的同时把依赖于该主键的外部键一起删 掉。 110 DROP INDEX index_name ; §3.4 外部键 建立外部键是保证完整性约束的一种唯一方法,也是关系数据库的精髓所在。许多曾使 用过桌面数据库(如 Dbase, Foxpro )的软件人员不太习惯或不使用关系数据库的主键与外 部键的方法来设计自己的数据库结构,这是很不好的方法。应该在使用关系数据库中将习惯 改过来。否则设计的应用结构和效率就不可能达到用户的要求。 §3.4.1 建立外部键 外部键的建立与主键的建立类似,都可以在 CREATE TABLE命令或 ALTER TABLE命 令中来说明,详细语法见《Oracle SQL reference 》Create table 命令 9 和 Alter table 命令。 1.在 CREATE TABLE 命令语句中建立外部键 2.用 ALTER TABLE 命令语句建立外部键 ALTER TABLE [schema.]table_name ADD ( CONSTRAINT_NAME FOREIGN KEY (Column1 [,column2,. . .]) REFERENCES [schema.]table_name (Column1 [,column2,. . .]); CREATE TABLE dept (deptno NUMBER(2), dname VARCHAR2(9), loc VARCHAR2(10), CONSTRAINT pk_dept PRIMARY KEY (deptno) ); Create table emp ( empno number(4), ename varchar2(10), job varchar2(10), mgr number(4), hiredate date, sal number(7,2), comm number(7,2), deptno constraint fk_deptno References dept(deptno) ); 111 同样下面语句的效果与上面一样: Create table emp ( empno number(4), ename varchar2(10), job varchar2(10), mgr number(4), hiredate date, sal number(7,2), comm number(7,2), deptno, constraint fk_deptno Foreign key(deptno) References dept(deptno) ); 使用 Delete cascade 管理引用完整性 Create table emp ( empno number(4), ename varchar2(10), job varchar2(10), mgr number(4), hiredate date, sal number(7,2), comm number(7,2), deptno number(2) constraint fk_deptno References dept(deptno) On Delete CASCADE ); 常用组合键的完整性约束: Alter table phone_calls ADD constraint fk_areaco_phoneno Foreign key(areaco,phoneno) References austomers(areano,phoneno) Exceptions into wrong_numbers Create table TROUBLE ( City varchar2(10), Sampledate date, Noon number(4,1), Midnight number(4,1), Precipitation number, 112 Constraint TROUBLE.PK PRIMARY KEY(city,Sampledate) ); §3.4.2 修改外部键 由于 ORACLE 不允许改变已被定义的外部键的列,也不允许改变外部键的名字,所 以 你 只 能用 ALTER TABLE 定义一个新的外部键或者使一个已存在的外部键无效: ALTER TABLE [schema.]table_name DISABLE CONSTRAINT_NAME; §3.4.3 删除外部键 要删除已定义的外部键,要用 Alter table 命令中的 DROP 关键字来实现,命令语法见 Alter table 命令。 ALTER TABLE [schema.]table_name DROP CONSTRAINT constraint_name; 提示:关系数据库的核心主要体现在主键和外部键上。在进行数据库结构设计时,建议要采 用主键和外部键来定义那些有关系的表。这样可以保证应用系统数据的完整性和一致性。 §3.5 索引 索引是关系数据库中用于存放每一条记录的一种对象,主要目的是加快数据的读取速度 和完整性检查。建立索引是一项技术性要求高的工作。一般在数据库设计阶段的与数据库结 构一道考虑。应用系统的性能直接与索引的合理直接有关。下面给出建立索引的方法和要点。 §3.5.1 建立索引 1. CREATE INDEX 命令语法: CREATE INDEX CREATE [unique] INDEX [user.]index ON [user.]table (column [ASC | DESC] [,column [ASC | DESC] ] ... ) [CLUSTER [scheam.]cluster] [INITRANS n] [MAXTRANS n] 113 [PCTFREE n] [STORAGE storage] [TABLESPACE tablespace] [NO SORT] Advanced 其中: schema ORACLE 模式,缺省即为当前帐户 index 索引名 table 创建索引的基表名 column 基表中的列名,一个索引最多有 16 列,long 列、long raw 列不能建索引列 DESC、ASC 缺省为 ASC 即升序排序 CLUSTER 指定一个聚簇(Hash cluster 不能建索引) INITRANS、MAXTRANS 指定初始和最大事务入口数 Tablespace 表空间名 STORAGE 存储参数,同 create table 中的 storage. PCTFREE 索引数据块空闲空间的百分比(不能指定 pctused) NOSORT 不(能)排序(存储时就已按升序,所以指出不再排序) 2.建立索引的目的: 建立索引的目的是: l 提高对表的查询速度; l 对表有关列的取值进行检查。 但是,对 表 进行 insert,update,delete 处理时,由于要表的存放位置记录到索引项中而会降 低一些速度。 注意:一个基表不能建太多的索引; 空值不能被索引 只有唯一索引才真正提高速度,一般的索引只能提高 30%左右。 Create index ename_in on emp (ename,sal); 例 1:商场的商品库表结构如下,我们为该表的商品代码建立一唯一索引,使得在前台 POS 收款时提高查询速度。 Create table good(good_id number(8) not null,/* 商品条码 */ Good_desc varchar2(40), /* 商品描述 */ Unit_cost number(10,2) /* 单价 */ Good_unit varchar2(6), /* 单位 */ Unit_pric number(10,2) /* 零售价 */ ); 114 注:提高查询速度的方法还有在表上建立主键,主键与唯一索引的差别 在于唯一索引可以空,主键为非空,比如: Create table good(good_id number(8) primary key, Good_desc Varchar2(40), Unit_cost number(10,2), Good_unit char(6), Unit_pric number(10,2) ); §3.5.2 修改索引 对于较早的 Oracle 版本,修改索引的主要任务是修改已存在索引的存储参数适应增长的需要 或者重新建立索引。而 Oracle8I 及以后的版本,可以对 无 用的空间进行合并。这些的工作主 要是由管理员来完成。 简要语法结构如下,更详细的语法图见电子文档 《Oracle8i Reference 》 中的 Alter index. ALTER [UNIQUE] INDEX [user.]index [INITRANS n] [MAXTRANS n] REBUILD [STORAGE n] 其中: REBUILD 是 根据原来的索引结构重新建立索引,实际是删除原来的索引后再重新建立。 提示:DBA 经常用 REBUILD 来重建索引可以减少硬盘碎片和 提高应用系统的性能。 例: alter index pk_detno rebuild storage(initial 1m next 512k); ALTER INDEX emp_ix REBUILD REVERSE; Oracle8i 的新功能可以对索引的无用空间进行合并,它由下面命令完成: ALTER INDEX . . . COALESCE; 例如: ALTER INDEX ename_idx COALESCE; 115 §3.5.3 删除索引 当不需要时可以将索引删除以释放出硬盘空间。命令如下: DROP INDEX [schema.]indexname 例如: sql> drop index pk_dept; 注:当表结构被删除时,有其相关的所有索引也随之被删除。 §3.6 新索引类型 Oracle8i 为了性能优化而提供新的创建新类型的索引。这些新索引在下面介绍: §3.6.1 基于函数的索引 基于函数的索引就是存储预先计算好的函数或表达式值的索引。这些表达式可以是算术运算 表达式、SQL 或 PL/SQL 函数、C 调用等。值得注意的是,一般用户要创建函数索引,必须具 有 GLOBAL QUERY REWRITE 和 CREATE ANY INDEX 权限。否则不能创建函数索引, 看下面例子: 例 1:为 EMP 表的 ename 列建立大写转换函数的索引 idx : CREATE INDEX idx ON emp ( UPPER(ename)); 这样就可以在查询语句来使用: SELECT * FROM EMP WHERE UPPER(ename) LIKE ‘JOH%’; 例 2:为 emp 的工资和奖金之和建立索引: 1) 查看 emp 的表结构: SQL> desc emp Name Null? Type ----------------------------------------- -------- ------------------ EMPNO NOT NULL NUMBER(4) ENAME VARCHAR2(10) JOB VARCHAR2(9) 116 MGR NUMBER(4) HIREDATE DATE SAL NUMBER(7,2) COMM NUMBER(7,2) DEPTNO NUMBER(2) 2)没有授权就创建函数索引的提示: SQL> create index sal_comm on emp ( (sal+comm)*12, sal,comm) 2 tablespace users storage(initial 64k next 64k pctincrease 0); create index sal_comm on emp ( (sal+comm)*12, sal,comm) * ERROR at line 1: ORA-01031: insufficient privileges 3) 连接到 DBA 帐户并授权: SQL> connect sys/sys@ora816 Connected. SQL> grant GLOBAL QUERY REWRITE to scott; Grant succeeded. SQL> grant CREATE ANY INDEX to scott; Grant succeeded. 4)在连接到 scott 帐户,创建基于函数的索引: SQL> connect scott/tiger@ora816 Connected. SQL> create index sal_comm on emp ( (sal+comm)*12, sal,comm) 2 tablespace users storage(initial 64k next 64k pctincrease 0); Index created. 1) 在查询中使用函数索引: SQL> select ename,sal,comm from emp where (sal+comm)*12 >5000; ENAME SAL COMM ---------------------- ---------------- ---------------- ALLEN 1600 300 117 WARD 1250 500 MARTIN 1250 1400 TURNER 1500 0 赵元杰 1234.5 54321 §3.6.2 反向键索引 反向键索引通过反向键保持索引的所有叶子键上的插入分布。有时,可用反向键索引来避免 不平衡的索引。对于反向键索引可以进行下面操作: l 通过在 ALTER INDEX 命令后加 REBUILD NOREVERSE 或 REBUILD REVERSE 子句来使索引边 为反向键索引或普通索引; l 采用范围扫描的查询不能使用反向键索引; l 位图索引不能反向; l 索引编排表不能反向。 例1:创建一个反向键索引: CREATE INDEX i ON t (a,b,c) REVERSE; 例2:使一个索引变为反向键索引: ALTER INDEX i REBUILD NOREVERSE; §3.6.3 索引组织表 与普通的索引不一样,索引组织表(Index_Organized Table)是根据表来存储数据, 即将索引和表存储在一起。这样的索引结构表(Index_organized table—IOT)的特点是: 对表数据的改变,如插入一新行、删除某行都引起索引的更新。 索引组织表就象带一个或多个列所有的普通表一样,但索引组织表在B-树索引结构的 叶节点上存储行数据。通过在索引结构中存储数据,索引组织表减少了总的存储量,此外, 索引组织表也改善访问性能。 由于表中的行与B_树索引存放在一起,每个行都没有ROWID,而是用主键来标识。但 是Oracle会“猜”这些行的位置并为每个行分配逻辑的ROWID。此外,你可以为这样的表建 立第二个索引。 创建索引结构表也是用CREATE TABLE 命令加ORGANIZATION INDEX关键字来实现。但 是,这样的表在创建完后,你还必须为该表建立一个主键。 例子: CREATE TABLE IOT_EXPAMPLE ( Pk_col1 number(4), 118 Pk_col2 varchar2(10), Non_pk_col1 varchar2(40), Non_pk_col2 date, CONSTRAINT pk_iot PRIMARY KEY ( pk_col1, pk_col2) ) ORGANIZATION INDEX TABLESPACE INDEX STORAGE( INITIAL 1M NEXT 512K PCTINCREASE 0 ); 索引组织表有些限制: l 不能使用唯一约束; l 必须具有一个主键; l 不能建立簇; l 不能包含LONG类型列; l 不支持分布和复制。 提示:如果建立了索引组织表,则会在DBA_TABLES中的IOT_TYPE和IOT_NAME列上记录有 索引组织表的信息。 例1.修改索引结构表 docindex 的索引段的INITRANS参数: ALTER TABLE docindex INITRANS 4; 例2.下面语句加一个的溢出数据段到索引组织表 docindex中: ALTER TABLE docindex ADD OVERFLOW; 例3.下面语句为索引组织表 docindex的溢出数据段修改INITRANS参数: ALTER TABLE docindex OVERFLOW INITRANS 4; §3.7 抽象数据类型的使用 Oracle 提供了一种新的类型结构,叫做抽象数据类型。用于定义许多复杂的对象。 1.创建抽象类型的命令语法: CREATE OR REPLACE TYPE [schema.]type_name [IS|AS] OBJECT ( element_list ); 详细命令语法见《ORACLE 8i SQL REFERENCE》 119 2.例子: 例:为地址建立一个抽象数据类型 add_type create type add_type as object ( street varchar2(10),--街道名 city varchar2(20), -- 城市名 state char(2), --州代码 zip number --邮编 ); 在建立表时使用 add_type 数据类型 create table customer ( name varchar2(20), address add_type ); 向具有抽象数据类型的表插入数据 insert into customer values (‘1’,add_type('mystaree','some city','st',10001)); §3.8 大数据类型的使用 除了 long 能在一行上存储多达 2GB 的字符和 long raw 能存储多达 2GB 的二进制数据 外,ORACLE 还提供四种大的数据类型来完善大数据的存储。 §3.8.1 可用数据类型 下表列出在 ORACLE8 中可用的数据类型: LOB 数据类型 描述 BLOB 二进制 LOB,最多为 4GB CLOB 字符 LOB, 最多为 4GB BFILE 二进制文件,存储在数据库之外的只读二进制文件,大小与 OS 有关 120 NCLOB 支持多字符集(Multibyte Characters)的 CLOB 列 与 LONG 数据类型不同,在一个表内可以建立多个 LOB 列,如: Create table proposal ( proposal number(10) promary key, recipient_name varchar2(25), proposal_name varchar2(25), short_description varchar2(1000), proposal_text clob, /* 提议内容 */ budget blob, /* 预算电子数据报表 */ cover_letter bfile /* 与提议有关的封面函件 */ ); §3.8.2 为LOB 数据类型指定存储 由于 LOB 占用空间较大,所以应该为 LOB 所在的表制定存储空间。如: Create table proposal ( proposal number(10) promary key, recipient_name varchar2(25), proposal_name varchar2(25), short_description varchar2(1000), proposal_text clob, /* 提议内容 */ budget blob, /* 预算电子数据报表 */ cover_letter bfile /* 与提议有关的封面函件 */ ) storage( initial 1m next 500k pctincrease 0 ) tablespace PROPOSALS; 上面例子是将整个表存储在一个表空间中,为了达到高效目的,可以将 LOB 列存储在另外的 表空间中,如: Create table proposal ( proposal number(10) promary key, recipient_name varchar2(25), proposal_name varchar2(25), short_description varchar2(1000), proposal_text clob, /* 提议内容 */ 121 budget blob, /* 预算电子数据报表 */ cover_letter bfile /* 与提议有关的封面函件 */ ) storage( initial 1m next 500k pctincrease 0 ) tablespace PROPOSALS LOB(proposal_text, budget) STORE AS ( TABLESPACE proposal_lobs STORAGE( initial 2m next 1m pctincrease 0 ) CHUNK 16k PCTVERSION 10 NOCACHE LOGGING ); 其中: LOB(proposal_text, budget) STORE AS 是将 LOB 列出并指定存储在 proposal_lobs 中。 CHUNK 16k 指出分配给 LOB 的空间,它的取值范围最小为 1k;最大为 32k。 PCTVERSION 10 创建新版本的百分比。缺省时老版本的数据不被覆盖,直到有 10%的可用 LOB 存储空间被使用。 NOCACHE 在读、写操作中数据不被存储在内存中,否则为 CACHE。 LOGGING 对于 LOB 的所有操作都被记录在重做日志文件(REDO)中,否则为 NOLOGGING。 §3.8.3 操作和检索LOB 数据 可以有多种方法来检索和操作 LOB 数据,主要有: 1)通过 DBMS_LOB 包; 2)使用 API(Application Programming Interfaces); 3)OCI(Oracle Call Interfaces)。 1.初始化值: 对于每个表中的 LOB 列,ORACLE 都有一个定位器(Locator Value)来告诉数据库在哪里可 以找到对于每个记录任意分开存储的数据。当在 包括 LOB 的表插入一个记录时,可以使用 DBMS_LOB 包来告诉 Oracle 对于内部存储的 LOB 列,生成一个空的定位器值。 例如我们要向 PROPOSAL 表插入一个记录,但还没有 Budget 电子表格和信函封面,则可以使 用下面命令: Insert into proposal ( proposal_id, recipient_name,proposal_name,short_description, proposal_text,budget , cover_letter ) values(1,’DOT PHILLIPS’,’CLEAR PHILLIPS FIELD’,NULL, ‘This is the text of a proposal to clear Phillips field.’, EMPTY_BLOB(), NULL ); 为了将 budget 设置为一个空的定位器值,使用了 EMPTY_BLOB 函数,如果希望将 CLOB 数据 类型设置为一个空的定位器,则可使用 EMPTY_CLOB 函数。由于 cover_letter 是一个外部存 储的 BFILE 值,所以设置为 NULL。 122 BLOB 数据类型 --- EMPTY_BLOB() CLOB 数据类型 --- EMPTY_CLOB() NCLOB 数据类型 --- EMPTY_CLOB() 可以使用 BFILENAME 来指向目录和文件(需要有 DBA 角色或 CREATE DIRECTORY 权限)。为 了创建一个目录,要使用 Create directory 命令。如: Create directory ‘proposal_dir’ for ‘/u01/proposal/letters’; 当插入数据项时可以使用 proposal_dir 逻辑目录(而不使用/u01/proposal/letters)。 现在可以向 proposal 表输入第二条带有 cover_letter 的记录: Insert into proposal ( proposal_id, recipient_name,proposal_name,short_description, proposal_text,budget , cover_letter ) values(2,’BRAD OHMONT’,’REBUILD FENCE’,NULL, EMPTY_CLOB(),EMPTY_BLOB(), BFILENAME(‘proposal_dir’,’P2.DOC’) ); 2.带子查询的数据插入 与 LONG 类型不一样,LOB 数据类型可以使用 select 语句来进行数据的插入。如: Insert into proposal ( proposal_id, recipient_name,proposal_name,short_description, proposal_text,budget , cover_letter ) select 3,’SKIP GATES’,’CLEAR GATES FIELD’,NULL, proposal_text,buaget,cover_letter from proposal where proposal_id = 1; 3.更新 LOB 值 update proposal set proposal_text=’This is the new proposal text.’ Where proposal_id=3; Update proposal Set cover_letter=BFILENAME(‘proposal_dir’,’P3.DOC’) Where proposal_id = 3; 4.使用 DBMS_LOB 来操作 LOB 值 123 可以用 DBMS_LOB 来改变或检索 LOB 列值。在 DBMS_LOB 包中可以使用下面过程或函数来对 LOB 进行操作: 过程或函数 描述 READ 用来读入一个 LOB 值的过程 SUBSTR 用来在 LOB 值上执行 SQL 语句的 SUBSTR 函数 INSTR 用来在 LOB 值上执行 SQL 语句的 INSTR 函数 GETLENGTH 用来在 LOB 值上执行 SQL 语句的 GETLENGTH 函数 COMPARE 比较两个 LOB 值的函数 WRITE 用于将一个 LOB 值的指定点写入数据到表的 LOB 列值中 APPEND 用来将 LOB 值添加到表的 LOB 中(追加在后面) ERASE 用来删除所有的 LOB 值 TRIM 用来在一个 LOB 值中执行 TRIM(裁剪)函数 COPY 用来将一个 LOB 值从一个列拷贝到另一个 LOB 列 BFILE 使用的附加函数: 在使用 BFILE 类型时还要另外一些附加的函数。并且要在 INITsid.ora 参数文件中修改: SESSION_MAX_OPEN_FILES xxx 缺省时,只允许打开 10 个 BFILE 文件。 BFILE 用的函数和过程如下: 过程或函数 描述 FILEOPEN 用于打开所需读入的文件的过程 FILECLOSE 用于关闭所需读入的文件的过程 FILECLOSEALL 用于关闭所有打开的文件的过程 FILEEXISTS 用来确认所打开的文件是否存在的函数 FILEGETNAME 用来得到一个 BFILE 定位器值所引用的外部文件名的过程 FILEISOPEN 用来确认一个外部文件是否已打开 用 DBMS_LOB 包来读入 LOB 的 PL/SQL 例子: 先看 PL/SQL 读入 LOB 的结构: declare locator value 变量; amount 总字节变量; offset 偏移量变量; output 输出变量; begin set amount :=…; set offset := . . .; select locator_value into locator from table; DBMS_LOB.READ(locator_value,amount,offset, output ); 124 DBMS_OUTPUT.PUT_LINE(‘output:’||output ); end; 例子: declare locator_var CLOB; amount_var integter; offset_var integer; output_var varchar2(10); begin amunt_var :=10; offset_var := 1; select proposal_text into locator_var from PROPOSAL where proposal_id=1; DBMS_LOB.READ(locator_var,amount_var,offset_var,output_var); DBMS_OUTPUT.PUT_LINE(‘Start of proposal text:’||output_var); End; / §3.9 表和索引有关的数据字典 当我们创建了表、主键、外部键和索引后,相关的信息就被记录到 Oracle 的数据字典中,应用 系统设计人员、程序人员和数据库管理员,应该了解有关数据字典的基本查询方法.下面给出 表和索引有关的数据字典的简单介绍,更详细的内容请参考《Oracle8i/9I 数据库管理》。 §3.9.1 表和索引数据字典 l DBA_TABLES,ALL_TABLES,USER_TABLES 存放表的基本信息,主要包括创建表结构时描述 的信息,如表名,表空间,存储参数等;此外,还有一些信息是在分析表时由系统 自动 写进去的,比如,表的行数量、行平均字节等。 l DBA_INDEXES,ALL_INDEXES,USER_INDEXES 存放索引的基本信息,主要包括创建索引时描 述的信息和用 ANALYZE 分析索引由系统自动写进去的信息。 l DBA_IND_COLUMNS 存放有索引的列的信息,因为 Oracle 在分析创建索引的命令正确后 就 将表名、索引名等存放到 DBA_INDEXES 数据字典中,而将索引的列名存放到 DBA_IND_COLUMNS 数据字典中。所 以 ,查 询 者需要了解两个数据字典才能查到索引的详细 信息。 l ALL_CONSTRAINTS 存放表的限制信息。 l ALL_CONS_COLUMNS 存放表的列的限制信息。 125 §3.9.2 数据字典查询例子 了解数据字典的目的就是查询有关表和索引的信息,下面是简单的查询例子。 例 1.查询当前用户的表的基本信息,包括表名、存放的表空间、存储参数: SQL> select table_name ,tablespace_name,initial_extent,next_extent 2* from user_tables SQL> TABLE_NAME TABLESPACE_NAME INITIAL_EXTENT NEXT_EXTENT ------------------ ------------------ -------------- ----------- ACCESS$ SYSTEM 16384 106496 AQ$_MESSAGE_TYPES SYSTEM 65536 65536 AQ$_PENDING_MESSAGES SYSTEM 65536 65536 . . . . . . 例 2.查询当前用户的索引的基本信息,包括表名、索引名及表空间、存储参数: SQL> select index_name,tablespace_name,initial_extent,next_extent 2 from all_indexes where owner=user; INDEX_NAME TABLESPACE_NAME INITIAL_EXTENT NEXT_EXTENT ------------------------------ ------------------ -------------- ----------- AQ$_MSGTYPES_PRIMARY SYSTEM 65536 65536 AQ$_PROPAGATION_STATUS_PRIMARY SYSTEM 65536 65536 AQ$_QTABLE_AFFINITIES_PK SYSTEM 65536 65536 AQ$_QUEUE_STATITICS_PK SYSTEM 65536 65536 AQ$_SCHEDULES_PRIMARY SYSTEM 65536 65536 ASSOC1 SYSTEM 16384 16384 ASSOC2 SYSTEM 16384 16384 . . . . . . 这里的 where owner=user 表示只查当前用户的索引. 例 3.查询当前用户的索引及索引的列名: 126 SQL> col column_name for a40 SQL> col index_name for a18 SQL> select index_name,table_name,column_name from all_ind_columns 2* where table_owner=user; INDEX_NAME TABLE_NAME COLUMN_NAME ------------------ ------------------ ----------------------------- I_ACCESS1 ACCESS$ D_OBJ# I_ACCESS1 ACCESS$ ORDER# AQ$_MSGTYPES_PRIMARY AQ$_MESSAGE_TYPES QUEUE_OID . . . . . . 例 4.查询当前用户的限制信息,当我们创建表结构时,如果描述了限制,则这些限制就被存放 到 DBA_CONSTRAINTS 数据字典中,看下面例子: 创建下面表结构: Create table worker ( empno number(4) primary key, name varchar2(10), age number(2) CHECK(age between 18 and 65 ), /* age number(2) CHECK( age >=18 and age<=65 ) */ lodging char(15) References LODGING(lodging) ); 查询数据字典信息可以得到: SQL> select owner,constraint_name,table_name from user_constraints; OWNER CONSTRAINT_NAME TABLE_NAME -------------------- ------------------------------ ----------------- ZHAO SYS_C001009 WORKER ZHAO SYS_C001010 WORKER SQL> set long 1000 SQL> select SEARCH_CONDITION from user_constraints; SEARCH_CONDITION -------------------------------------------------------- age between 18 and 65 127 例 5.创建表结构时描述了限制,则这些限制就被存放到 DBA_CONSTRAINTS 数据字典中,再看 下面例子: CREATE TABLE dept (deptno number(2), dname varchar2(20), loc varchar2(20), CONSTRAINT pk_dept PRIMARY KEY (deptno) ); Create table empl ( Empno number(5) primary key, Ename varchar2(15) not null, Job varchar2(10), Mgr number(5), Hiredate date default sysdate, Sal number(7,2) CHECK(sal>100), Comm number(3) default 0.0 , Dept number constraint dept_fkey References zhao.dept ); SQL> col CONSTRAINT_NAME for a12 SQL> select constraint_name,table_name,SEARCH_CONDITION 2* from user_constraints; CONSTRAINT_N TABLE_NAME SEARCH_CONDITION ------------ ------------------ ------------------------- PK_DEPT DEPT SYS_C001013 EMPL "ENAME" IS NOT NULL SYS_C001014 EMPL sal>100 SYS_C001015 EMPL DEPT_FKEY EMPL SYS_C001009 WORKER age between 18 and 65 SYS_C001010 WORKER 已选择 7 行。 128 第四章 视图、同义词和序列 视图、同 义词和序列是 Oracle 的常用对象,在 Oracle 系统安装完成后,就已经建立许多 Oracle 系统所用的视图、同义词和序列。此外,在应用系统设计中,也经常需要创建视图、同义词 和序列来满足应用的需要。下面给出简要介绍。 §4.1 视图 视图的一个主要目的就是简化用于查询所使用的语句,另外就是可以实现安全和保密的 目的。利用视图,我们可以在查询处理中完成复杂的操作。 §4.1.1 使用视图来修改表中数据 可以用视图修改表中数据: l 带有集合操作,如 intersect, union和 minus的视图; l 带有 group by,connect by,或 start with 子句的视图; l 带有组合功能,如 avg , sum 或 max 功能的视图; l 使用 distinct 功能的视图。 §4.1.2 创建一个新视图 1 建立视图命令语法: CREATE [OR REPLACE] [FORCE/NO FORCE] VIEW [schema.]view [column_name1, column_name2] AS query [WITH OBJECT OID | DEFAULT] [WITH CHECK OPTION] [CONSTRAINT constraint] [WITH READ ONLY] OR REPLACE 替换掉原来的视图(不需删除) FORCE 强行创建一视图,无论视图的基表是否存在或拥有者是 否有权限,但作 select、insert、update、delete 前条件 必须为真。 Schema 帐户、缺省为当前登录的帐户。 VIEW 视图名 129 Alias 视图的列名(唯一),缺省为列名 As subquery 查询表达式(不含 order by, For update) WITH CHECK OPTION 在视图上作 insert,update 时必须是视图, 查询所得到的结果,有子查询时可能不正确。 Constraint 约束名称,缺省为 sys_Cn. N 为整数(唯一)。 注:视图只是一个逻辑表,它自己不包含任何数据,目的在于: l 通过限制存取基表中预定的一组行或列,提供安全的附加功能; l 隐藏数据的复杂性,例如,经常对几个表的数据作某种运算后查询 时,可以使用视图使得操作仿佛是在单表上进行; l 省去一些复杂的连接操作 ============================================================================== 注意:下面情况在视图中受到限制: l 视图查询不能选取 Currval,nextval 伪列; l 只有加别名才能使用 rowid,rownum,level; l 如果在子查询中使用 * 代替选择的表的所有列,则后来该表新加的列不会自动被加到视 图中,只有重新创建视图后该新增的列才能被加到视图中; l 如 果视图建立(即查询)时包括任何以下结构之一,则该视图不能作 insert,update,delete(目前的新版可以,需作特别的说明限制): 连接运算; 集合运算符; 组函数; GROUP BY,CONNECT BY,START WITH; DISTINCT。 ============================================================================== 提示:不要在视图中再建视图,理论上虽可以对视图再建视图,但这样在查询时影响速度。 Create view emp_vi as select * from emp; 例 1:为表 emp 建立视图 dept20,此视图可以显示部门 20 的雇员和他们 的年薪。 Create view dept10 As select ename,deptno,job, sal*12 sal12 From emp where deptno=10; 例 2: Create view clerk (id_number, person, depart, position ) As select empno,ename,deptno,job From emp where job='clerk' With check option constraint wco; 130 用户不能往 clerk 视图中作 insert(或 update)非'clerk'的记录。 §4.1.3 删除一个视图 1.用命令删除视图 语法: DROP VIEW [SCHEMA.] view_name; 如 drop view view_data; 建议:一般视图不占用多少空间,可以不必删除。 2.用 Schema Manager 删除视图 1)启动 Schema Manager ,以 DBA 登录; 2)双击 View 文件夹,出现包含视图的模式列表; 3)双击包含要改变的视图的名字; 4)点击要被删除的视图名; 5)点红 X; 6)在确定是否要删除中回答 Yes; 有关的数据字典 user_views(dba_views, all_views) 视图: Column Datatype NULL 说明 ------------ ------------- ---------- ------------------ OWNER VARCHAR2(30) NOT NULL 视图创建者 VIEW_NAME VARCHAR2(30) NOT NULL 视图名 TEXT_LENGTH NUMBER 视图主体长度 TEXT LONG 视图内容 TYPE_TEXT_LENGTH NUMBER 类型文本长度 TYPE_TEXT VARCHAR2(4000) 视图的类型 OID_TEXT_LENGTH NUMBER OID 视图类型的长度 OID_TEXT VARCHAR2(4000) 视图类型的 OID VIEW_TYPE_OWNER VARCHAR2(30) 视图类型的所以者 VIEW_TYPE VARCHAR2(30) 视图类型 131 §4.1.4 改变视图 当视图的状态不可用('INVALID')时,需要用 ALTER VIEW . . . COMPILE 对视图进行 编译。如: SQL>ALTER VIEW SCHEMA.view COMPILE; 你可以用下面语句查询那些无效的视图,然后有针对性地进行编译: SQL> SELECT OWNER,OBJECT_NAME,OBJECT_TYPE,STATUS FROM DBA_OBJECTS WHERE object_type=’VIEW’ and STATUS='INVALID'; §4.2 实体视图(MATERIALIZED VIEW) Oracle8i 版本提供可以创建实体视图(MATERIALIZED VIEW),它确实存放有物理数据。实体 视图包含定义视图的查询时所选择的基表中的行。在普通的视图中,Oracle 在执行查询时临 时进行查询操作来返回结果;而对实体视图的查询是直接从该视图中取出行。 在 Oracle9i 版本里,对实体视图进行了增强,如提供快速刷新等。下面简单介绍实体视图的 使用。 §4.2.1 创建实体视图 1.关键内容: 使用实体视图需要了解下面几个关键点: l 实体视图存放有物理数据; l 实体视图背后的查询只在视图建立或刷新时执行,即如果创建后不进行刷新则只得到创 建时的数据; l 实体视图使用 DBMS_MVIEW 程序包中含有刷新和管理实体视图的过程来进行管理; l 在导出和导入(EXP、IMP)中使用 MVDATA 参数来实现实体视图数据的导出和导入; l 使用 CREATE MATERIALIZED VIEW 语句创建实体视图; l 实体视图中的查询表叫主表(master tables)( 复 制 项 ) 或 详细表(数据仓库项)。为一 致起见,这些主表叫主数据库(master databases.); l 为了复制目的,实体视图允许你在本地管理远程拷贝; l 所复制的数据可以使用高级复制特性进行更新; l 在复制环境下,通常创建的实体视图都是主键、ROWID 和子查询实体视图。 2.创建实体视图前提: 132 l 要有授权创建实体视图的权限(CREATE MATERIALIZED VIEW 或CREATE SNAPSHOT); l 必须有访问各个主表的权限,即 有SELECT ANY TABLE 的系统权限。 如果在另外的用户模式下创建实体视图,则: l 需要有CREATE ANY MATERIALIZED VIEW或CREATE ANY SNAPSHOT、SELECT ANY TABLE 权限; l 必须有CREATE TABLE、SELECT ANY TABLE系统权限。 如果带查询重写有效来创建实体视图,则: l 主表的主人必须有QUERY REWRITE系统权限; l 如果你不是主表主人,则必须有GLOBAL QUERY REWRITE系统权限; l 如果模式主人没有主表,则该模式主人必须有GLOBAL QUERY REWRITE权限。 3.创建实体视图语法: 下面给出 Oracle9i 版本的实体视图的创建语法: CREATE MATERIALIZED VIEW [schema.] materializede_view [ OF [schema .] object_type ]| [(scoped_table_ref_constraint)] | ORGANIZATION_INDEX index_org_table_clause | [ [ [ [segment_attribute_cluase|column_properties ] | [CACHE|NOCACHE ] ] | [ CLUSTER cluster (column,) ] ]| [partitioning_clause|parllel_cluse|build_clause] | [ ON PREBUILT TABLE [ [WITH|WITHOUT] | REDUCED PRECISION ] ]| [ [ USING INDEX [physical_attribute_clause |TABLESPACE tablespace] ] | [ USING NO INDEX ] ] refresh_cluse [ [ FOR UPDATE ] | [ DISABLE | ENABLE ] QUERY REWRITE ] ] AS subquery; 其中: scoped_table_ref_constraint 为: SCOPE FOR ( [ref_column|ref_attribute] ) IS [schema.] scpe_table_name Index_org_table_clause 为: [ (mapping_table_clause) | PCTTHRESHOLD integer | [COMPRESS integer|NOCOMPRESS] ] [ INCLUDING column_name ] OVERFLOW [ segment_attribute_clause] 133 refresh_clause 为: [ NEVER REFRESH | [ REFRESH | [ USING [ DEFAULT [LOCAL | MASTER] ROLLBACK SEGMENT ] | [LOCAL | MASTER] ROLLBACK SEGMENT ] rollback_segment ] | WITH [ PRIMARY KEY | ROWID ] | NEXT [ START WITH ] date | ON [ DEMAND | COMMIT ] | [ FAST | COMPLETE|FORCE ] ] 参数说明: schema 模式名 materialized_view 实体视图名 segment_attributes_clause 建立 PCTFREE、PCTUSED、INITRANS 和 MAXTRANS 参数。 TABLESPACE 表空间 LOB_storage_clause 大对象存储参数 LOGGING | NOLOGGING 指定创建实体视图时是否需要建立日志 CACHE | NOCACHE 实体视图的数据是否被缓存 CLUSTER cluster 名 partitioning_clauses 用于指定实体视图的分区范围或一个HASH函数。实体视图分区与表 分区类似。 parallel_clause 指定实体视图的并行操作和设置查询并行度。 build_clause 当移植实体视图时使用。 NOPARALLEL 指定顺序执行(缺省值), PARALLEL 如果选择并行度时可指定并行。 THREADS_PER_CPU 初始参数 PARALLEL integer 指定并行度。 Build_clause 指定重建实体视图时的选项: IMMEDIATE 指定为IMMEDIATE 表示实体视图是立即移植(缺省值)。 DEFERRED 指定为DEFERRED 表示实体视图是在下次刷新时移植。第一次延期总是一个 完全的刷新。一直到被刷新为止该实体视图的值都是旧的值,所以它是不可查询重写的。 ON PREBUILT TABLE 此项可以使你以原初始化实体视图(preinitialized materialized view) 来注册一个存在的表。这对于大表来说非常有用。它有下面限制: l 每个列的别名必须与表的列名一样; l 如果使用ON PREBULT TABLE,则不能对列再指定 NOT NULL。 WITH REDUCED PRECISION 允许指定表或实体视图精度可以丢失。实体视图的列不能与子 查询所返回的精度一致。 WITHOUT REDUCED PRECISION 表示不允许指定表或实体视图精度可以丢失。实体视图 134 的列要与子查询所返回的精度一致。这是缺省值。 USING INDEX 用此项可以为索引建立INITRANS、MAXTRANS及STORAGE参数。如果不 指定本参数,则系统使用原索引。 限制:不能在USING INDEX字句里指定PCTUSED或PCTFREE参数。 refresh_clause 用于指定缺省方法、模式及Oracle刷新实体视图的次数。如果一个实体视 图的主表被修改。则实体视图必须被更新才能反映当前的数据。这项可以实现指定时间表和 刷新方法。 FAST 指定增量刷新方法,该刷新是根据主表的改变来进行。这种改变存储在任何一个实体 视图的日志里或加载日志里。 即使还没有在主表下建立实体视图日志,也可以建立一个总和的实体视图。然而,如果你建 立其它类型的实体视图时,CREATE 语句就会失败。除非实体视图日志已经存在。 如果在创建实体视图时存在适合的实体视图日志,Oracle 将执行快速的刷新。 为了使 DML 改变和直接的加载都能有效,就要适当限制实体视图的刷新。 COMPLETE 指定刷新方法,如果指定了完全刷新,即使已经指定了快速刷新,Oracle也执 行完全刷新。 FORCE 表示强行刷新。它是FAST、COMPLETE、FORCE三种刷新的缺省值。 4.创建实体例子: 例1.创建实体汇总视图: 下面语句建立一个移植的实体视图,并指定缺省的刷新方法、模式及时间: CREATE MATERIALIZED VIEW mv1 REFRESH FAST ON COMMIT BUILD IMMEDIATE AS SELECT t.month, p.prod_name, SUM(f.sales) AS sum_sales FROM time t, product p, fact f WHERE f.curDate = t.curDate AND f.item = p.item GROUP BY t.month, p.prod_name; 例2.创建实体汇总视图: 下面语句建立和移植一个实体视图sales_by_month_by_state,这个实体视图根据数据语句一旦 执行成功就进行移植。接着就完成实体视图的查询: CREATE MATERIALIZED VIEW sales_by_month_by_state TABLESPACE my_ts PARALLEL (10) 135 ENABLE QUERY REWRITE BUILD IMMEDIATE REFRESH COMPLETE AS SELECT t.month, g.state, SUM(f.sales) AS sum_sales FROM fact f, time t, geog g WHERE f.cur_date = t.cur_date AND f.city_id = g.city_id GROUP BY month, state; 例3.原实体视图(即视图的名字与原来表名一样): 下面语句为先前存在的总结表sales_sum_table 建立汇总视图 sales_sum_table: CREATE TABLE sales_sum_table (month DATE, state VARCHAR2(25), sales NUMBER); CREATE MATERIALIZED VIEW sales_sum_table ON PREBUILT TABLE ENABLE QUERY REWRITE AS SELECT t.month, g.state, SUM(f.sales) AS sum_sales FROM fact f, time t, geog g WHERE f.cur_date = t.cur_date AND f.city_id = g.city_id GROUP BY month, state; 在这个例子中,实体视图与先前建立的 实体表 有相同的名字、相同的列和数据类型。 例4.实体连接视图: 声明语句建立一个连接实体视图: CREATE MATERIALIZED VIEW mjv REFRESH FAST AS SELECT l.rowid as l_rid, l.pk, l.ofk, l.c1, l.c2, o.rowid as o_rid, o.pk, o.cfk, o.c1, o.c2, c.rowid as c_rid, c.pd, c.c1, c.c2 FROM l, o, c WHERE l.ofk = o.pk(+) AND o.ofk = c.pk(+); 例5.子查询实体视图: 下面语句创建一个基于 Order 和 Customers 表的视图: CREATE MATERIALIZED VIEW sales.orders FOR UPDATE 136 AS SELECT * FROM sales.orders@dbs1.acme.com o WHERE EXISTS (SELECT * FROM sales.customers@dbs1.acme.com c WHERE o.c_id = c.c_id); 例6.主键的实体视图: 下面语句创建一个主键实体视图human_genome: CREATE MATERIALIZED VIEW human_genome REFRESH FAST START WITH SYSDATE NEXT SYSDATE + 1/4096 WITH PRIMARY KEY AS SELECT * FROM genome_catalog; 例7.ROWID实体视图: 下面语句创建一个ROWID实体视图emp_data: CREATE MATERIALIZED VIEW emp_data REFRESH WITH ROWID AS SELECT * FROM emp_table73; 例8.周期性刷新的实体视图: 下面语句创建一个主键实体视图emp_sf并根据在纽约的scott的职工表来移植数据: CREATE MATERIALIZED VIEW emp_sf PCTFREE 5 PCTUSED 60 TABLESPACE users STORAGE (INITIAL 50K NEXT 50K) REFRESH FAST NEXT sysdate + 7 AS SELECT * FROM scott.emp@ny; 此语句没有START WITH参数,所以Oracle使用SYSDATE来估计下次的自动刷新时间。 Oracle执行首次刷新为7天后。 例9.自动刷新的实体视图: 下面语句创建一个复杂的实体视图 all_emps,它查询 DALLAS 和 BALTIMORE 中的职工表: CREATE MATERIALIZED VIEW all_emps PCTFREE 5 PCTUSED 60 TABLESPACE users STORAGE INITIAL 50K NEXT 50K 137 USING INDEX STORAGE (INITIAL 25K NEXT 25K) REFRESH START WITH ROUND(SYSDATE + 1) + 11/24 NEXT NEXT_DAY(TRUNC(SYSDATE, ’MONDAY’) )+ 15/24 AS SELECT * FROM fran.emp@dallas UNION SELECT * FROM marco.emp@balt; Oracle在早上11点自动刷新,接着就在周一的3点进行刷新。缺省刷新方法是FORCE, all_emps视图包含一个UNION,它是不支持快速刷新的,所以Oracle只能用完全 (complete)刷新。 上面语句同样为实体视图建立存储特性: l 第一个存储参数建立初始大小为 50KB,下次大小也为 50KB. l 第二个存储参数(使用 USING INDEX)建立初始大小为 25KB,下次大小也为 25KB. 例10.自回滚段的实体视图: 下面语句在远程建立带master_seg 回滚段的主键实体视图sales_emp,并用本地回滚段 snap_seg来刷新实体视图: CREATE MATERIALIZED VIEW sales_emp REFRESH FAST START WITH SYSDATE NEXT SYSDATE + 7 USING MASTER ROLLBACK SEGMENT master_seg LOCAL ROLLBACK SEGMENT snap_seg AS SELECT * FROM bar; §4.2.2 创建实体视图日志 1.创建实体视图日志的目的 使用CREATE MATERIALIZED VIEW LOG语句可以创建实体视图日志。实体视图日志是一个 包含有主表和实体视图的表。这些快照(snapshot)和实体视图(materialized view)其实都 是同义词。它们都引用一个或多个包含查询结果的表,这些表可以是本地数据库或远程数据 库的表。 DML的改变是由主表的数据组成的,Oracle在实体视图日志里存储那些改变行的描述,然后 使用实体视图日志去刷新基于主表的实体视图,这个过程叫快速刷新。如果没有实体视图日 志,Oracle必须重新执行实体视图查询,这个过程叫完全刷新。通常快速刷新要比完全刷 新用的时间少。 一般,实体视图日志与模式中的主表放在一起。你需要为每个主表建立实体视图日志。因为 Oracle 要使用这个实体视图日志来进行快速刷新。 138 2.要求 l 如果你拥有主表,则可以建立实体视图日志。 l 如果你为其他人建立实体视图日志,则必须有CREATE ANY TABLE 和 COMMENT ANY TABLE权限。 3. CREATE MATERIALIZED VIEW LOG 语法 ( 创建实体视图日志命令语法 见《Oracle9i SQL Reference 》 ) p982 4.实体视图日志例子 例1.主键的例子: 下面语句在雇员表上建立实体视图日志: CREATE MATERIALIZED VIEW LOG ON emp WITH PRIMARY KEY; 例2.建立仅包含更新行主键的实体视图日志 Oracle可以用实体视图日志在任何简单主键的实体视图中来执行一个快速刷新。下面语句建 立一个只包含更新行主键的实体视图日志: CREATE MATERIALIZED VIEW LOG ON emp PCTFREE 5 TABLESPACE users STORAGE (INITIAL 10K NEXT 10K); 下面语句建立一个只包含更新行主键的实体视图日志: CREATE MATERIALIZED VIEW LOG ON sales WITH ROWID, PRIMARY KEY; 下面语句建立一个包含更新行主键和更新列ZIP的实体视图日志: CREATE MATERIALIZED VIEW LOG ON address WITH (zip); 下面语句建立一个主表,然后建立一个带INCLUDING NEW VALUES的实体视图日志: CREATE TABLE agg (u NUMBER, a NUMBER, b NUMBER, c NUMBER, d NUMBER); CREATE MATERIALIZED VIEW LOG ON agg WITH ROWID (u,a,b,c,d) 139 INCLUDING NEW VALUES; 下面语句使用agg日志来建立实体视图: CREATE MATERIALIZED VIEW sn0 REFRESH FAST ON COMMIT AS SELECT SUM(b+c), COUNT(*), a, d, COUNT(b+c) FROM agg GROUP BY a,d; §4.2.3 修改实体视图 1.修改实体视图目的 实体视图是Oracle的一个数据库对象。它包含有一个或多个表的查询结果。使用 ALTER MATERIALIZED VIEW 可以对已经存在的实体视图进行修改。修改方法如下: l 修改存储特性; l 修改刷新方法、模式及时间 l 改变实体视图的结构以使它有不同类型; l 使查询重写有效。 2.修改实体视图命令语法 ALTER MATERIALIZED VIEW [schema.] materializede_view [ [ physical_attributes_clause| LOB_storage_clause[,...] | Modify_LOB_storage_clause [,...]| Partition_clause | Parallel_clause | [LOGGING|NOLOGGING] | allocate_extent_clause | [CACHE|NOCACHE ] ]| [ alter_iot_cluse | USING INDEX physical_attribute_clause | MODIFY scoped_table_ref_constraint | REBUILD | Refresh_cluse ]| [ [ DISABLE | ENABLE ] QUERY REWRITE | 140 COMPILE | CONSIDER FRESH ] 详细见《Oracle9i SQL Reference》p502 3.修改实体视图例子 例1: CREATE MATERIALIZED VIEW hq_emp REFRESH COMPLETE START WTIH SYSDATE NEXT SYSDATE +1/4096 AS SELECT * FROM hq_emp; ALTER MATERIALIZED VIEW hq_emp REFRESH FAST; 例2:修改下次刷新: ALTER MATERIALIZED VIEW branch_emp REFRESH NEXT SYSDATE+7; 例3:修改完全刷新: ALTER MATERIALIZED VIEW sf_emp REFRESH COMPLETE START WITH TRUNC(SYSDATE+1) + 9/24 NEXT SYSDATE+7; 例4:使查询重写有效: ALTER MATERIALIZED VIEW mv1 ENABLE QUERY REWRITE; 例5:使用回滚段: ALTER MATERIALIZED VIEW inventory REFRESH USING MASTER ROLLBACK SEGMENT master_seg; ALTER MATERIALIZED VIEW sales REFRESH USING DEFAULT MASTER ROLLBACK SEGMENT; 141 例6:使用主键: ALTER MATERIALIZED VIEW emp_rs REFRESH WITH PRIMARY KEY; 例7:使用完全刷新: ALTER MATERIALIZED VIEW store_mv COMPILE; 例8:修改刷新方法: ALTER MATERIALIZED VIEW store_mv REFRESH FAST; 例9:修改考虑刷新(CONSIDER FRESH)方法: ALTER MATERIALIZED VIEW mv1 CONSIDER FRESH; §4.2.4 修改实体视图日志 ALTER MATERIALIZED VIEW LOG 1.修改实体视图日志目的 使用 ALTER MATERIALIZED VIEW LOG 可以对已经存在的实体视图日志进行修改。可以 修改存储特性、刷新模式、时间或已经存在实体视图日志的类型。 2.修改实体视图日志命令语法 ( 创建实体视图日志命令语法 见《Oracle9i SQL Reference 》 ) 3.修改实体视图日志命令例子 例1:修改扩展次数: ALTER MATERIALIZED VIEW LOG ON dept STORAGE MAXEXTENTS 50; 例2:修改已经存在的ROWID: ALTER MATERIALIZED VIEW LOG ON sales ADD PRIMARY KEY; 142 §4.2.5 实体视图完整例子 要在应用中使用实体视图,除了要实体视图的语句外,还需要进行数据库实例的初始化参数。 并重新启动数据库实例才能使所写的实体视图有效。下面是操作步骤: 1.修改实例初始化参数initsid.ora 有关参数 与实体视图有关的参数与数据库作业一样,都是job_queue_processes和job_queue_interval 。 第1个参数是队列的进程数,一般要设大于 0 ;第2个参数是刷新间隔秒数。Oracle9i可以是 小于1000的整数。例如在initora817.ora初始化中将该二参数设置为: job_queue_processes = 2 job_queue_interval = 5 2.关闭实例和重启动实例 在Oracle8i版本,可用svrmgrl服务器实用程序来关闭和启动数据库实例;在 Oracle9i版本可 用SQL>CONNECT AS SYSDBA实现关闭和启动数据库实例。 3.运行实体视图 CREATE MATERIALIZED VIEW emp_stat TABLESPACE users STORAGE (INITIAL 8K NEXT 5K) REFRESH FAST START WITH SYSDATE NEXT round(SYSDATE + 16/24) AS SELECT deptno,sum(sal) from emp group by deptno; 实体化视图已创建。 22:29:28 SQL> create materialized view log on emp pctfree 5 tablespace users; 实体化视图日志已创建。 SQL> select * from emp_stat; DEPTNO SUM(SAL) ---------- ---------- 10 14116 20 54537 30 9400 143 SQL> alter materialized view emp_stat 2 refresh complete 3 start with trunc(sysdate)+15/24 next sysdate+30/24*60*60; 实体化视图已更改。 SQL> SQL> select * from emp_stat; DEPTNO SUM(SAL) ---------- ---------- 10 14116 20 64536 30 9400 修改下次刷新时间为下午 3 点半(start with trunc(sysdate)+15.5/24),则: SQL> set time on 15:23:34 SQL> alter materialized view emp_stat 15:23:50 2 refresh complete 15:23:50 3 start with trunc(sysdate)+15.5/24 next sysdate+30/24*60*60; 实体化视图已更改。 现在虽然视图已更改,但由于没到时间。所以视图数据还是原来的旧数据: 15:27:05 SQL> / DEPTNO SUM(SAL) ---------- ---------- 10 14116 20 64536 30 9400 15:27:07 SQL> 15:27:07 SQL> 由于时间到了 3 点刷新点,可查出新的统计结果: 15:30:06 SQL> / DEPTNO SUM(SAL) ---------- ---------- 10 24115 20 64536 30 9400 144 15:30:09 SQL> 15:36:09 SQL> insert into emp values(555,'zhaojie','enginner',null,null,20000,5000,20); 已创建 1 行。 15:36:39 SQL> commit; 15:38:08 SQL> select * from emp_stat; DEPTNO SUM(SAL) ---------- ---------- 10 24115 20 64536 30 9400 15:38:34 SQL> 每一小时一次 则 next 表达式为 sysdate+1*60 分*60 秒/24 * 60 分* 60 秒=next sysdate+1/24 每半小时一次 next sysdate + 30*60/60*60*24 = sysdate+1/48 每15 分钟一次 next sysdate+1/96 希望刷新是 4 点半,接着是 15 分一次: alter materialized view emp_stat refresh complete start with trunc(sysdate)+16.5/24 next sysdate+1/96; 16:10:49 SQL> alter materialized view emp_stat 16:13:29 2 refresh complete 16:13:29 3 start with trunc(sysdate)+16.5/24 next sysdate+1/96; 实体化视图已更改。 16:13:31 SQL> select * from emp_stat; DEPTNO SUM(SAL) ---------- ---------- 10 24115 20 64536 30 9400 16:13:43 SQL> 145 16:30:20 SQL>/ DEPTNO SUM(SAL) ---------- ---------- 10 24115 20 64536 30 19399 16:30:27 SQL> 16:30:27 SQL> 16:31:03 SQL> insert into emp values(555,'zhaojie','enginner',null,null,20000,5000,20); 已创建 1 行。 16:32:04 SQL> commit; 提交完成。 16:32:15 SQL> 希望在 16:45 时重新刷新。得到新结果,在时间到后,视图自动刷新,deptno=20的总和已改 变: 16:46:22 SQL> select * from emp_stat; DEPTNO SUM(SAL) ---------- ---------- 10 24115 20 84536 30 19399 与实际表查出一样: 16:46:29 SQL> select deptno,sum(sal) from emp group by deptno; DEPTNO SUM(SAL) ---------- ---------- 10 24115 20 84536 30 19399 4.停止实体视图的自动运行 146 §4.3 序号(sequence) 序号是一个发布唯一数字的 ORACLE 对象,在需要时,每次按 1 或一定增量增加。序 号通常用于产生表中的唯一主键或唯一索引等。 §4.3.1 建立序号 建立序号可以在 SQL*PLUS 中用命令来完成,也可以使用 Schema Manager 工具来完 成。 1. 命令语法: CREATE SEQUENCE [user.]sequence [INCREMENT BY {1|integer}] [START WITH integer] [MAXVALUE integer|NOMAXVALUE] [MINVALUE integer|NOMINVALUE] [CYCLE|NOCYCLE] [CACHE{20|integer}|NOCACHE] [ORDER|NOORDER] 2. 建立序号 例 1:建立 Sequence Create sequence emp_sequence Increment by 1 Start with 1 No maxvalue No cycle Cache 10; Create sequence order_seq Start with 1 Incremant by 1 Nomaxvalue Nocycle Cache 20; 147 §4.3.2 修改序号 3. 修改序号 有时需要对已建立的序号进行修改,比如在系统移植或升级时可能有的序号已经增长到 某个值。现在需要从原先停止的地方开始等。 例 2:修改 sequence Alter sequence emp_sequence Increment by 1 Maxvalue 10000 Cycle Cache 20; §4.3.3 使用序号 建立序号的目的就是使用序号,使用序号主要是在插入和查询时使用。 例 3:使用 sequence insert into orders(orderno,custno) values(order_seq.nextval,1032); update orders set orderno-orderno=order_seq.nextval where orderno=10112; 每使用一次,nextval 自动增 1,currval 是多次使用的值,如果一开始就 用,则其值为 0,一 般 情况下是在 nextval 使用之后才能使用 currval,可 以 用它来产生同样 的号,比如有一定货号有多种商品和数量: insert into line items(orderno,partno,quantity) values(order_seq.currval,20231,3); insert into line_items(orderno,partno,quantity) values(order_seq.currval,29374,1); 提示:在 ORACLE8 中,如果在建立序列的语句中未加上 NOCACHE ,则有可能在关闭系统再启 动后产生跳号现象。如果你的系统要求不许跳号,请在创建序列时在后面加 NOCACHE 。 §4.3.4 删除序号 当不再使用时就可以删除序号,删除序号有两种方法: 1. DROP SEQUENCE [Schema.]seguence_name; 148 2. 使用 Schema Manager 工具; §4.4 同义词 同义词可以使多个用户使用同一个对象而不用将模式(Schema )作为前缀加在对象的 前面,从而简化授权方面的操作。同义词有公有和私有两种。 §4.4.1 建立同义词 要建立同义词,首先要有 Create any synonym和 drop any synonym权限方可 建立和撤消,如果某个用户不能建立同义词,则应给其授该权限。 CRAETE [PUBLIC] SYNONYM [user.]synonym FOR [user.]table [@database_link]; 例 1: Create public synonym emp For scott.emp@sales; 例 2:为当前用户的所有对象建立公共同义词,可用下面各命令来完成创建一个脚本: set echo off set head off set verify off set linesize 200 set pages 0 set feedback off set term on undefine p_user def p_user = &&p_user Prompt Generating Script To Drop User set term off SPOOL create_syn.sql select 'drop public synonym '||object_name||' ;' from user_objects; select ' create public synonym '||object_name|| ' for sale.'||object_name||' ;' from user_objects; SPOOL OFF 149 Start create_syn.sql 注意:当创建同义词后,还要将该同义词授权给 public ,才能使其他的 Oracle 用户可以访 问该同义词。 同义词数据字典: DBA_SYNONYMS 实例中所有同义词 USER_SYNONYMS(=SYN)用户的同义词 §4.4.2 删除同义词 DROP PUBLIC synonym [schema.]synonym ; Drop synonym emp; 例 1:为当前所有对象建立同义词。为了省去编辑,可用下面个命令来完成: * 需具有 dba, -- create any synonym,drop any synonym 权限 select 'drop public synonym '||object_name||' ;' from user_objects; select ' create public synonym '||object_name|| ' for sale.'||object_name||' ;' from user_objects; §4.5 视图、同义词和序列有关的数据字典 当我们创建了视图、同 义词和序列后,相关的信息就被记录到 Oracle 的数据字典中,作为程序 人员和数据库管理员,应该了解有关数据字典的基本查询方法. 与视图、同义词和序列有关的数据字典有: l DBA_VIEWS –实例中所有的视图的基本信息; l DBA_SYNONYMS –实例中所有的同义词; l DBA_SEQUENCES –实例中所有的序列。 150 第五章 簇与分区 Oracle 公司在 Oracle7 以后的版本提供了许多数据库厂商不能具备的分区和簇的存储管理技 术。使用这些技术,可以实现将大的表和索引进行拆分,使得处理速度提高和便于管理。 §5.1 簇( cluster ) 簇(Cluster)是一组表,如果应用程序中的 SQL 语句经常联结两个或多个表,可以把 这些表以簇方式进行创建以改善性能。只要我们创建了簇并在创建表时指定到已经创建好的 簇中,ORACLE 就把簇中的表存储在相同的数据块中,并且各个表中的相同的列值只存储一 个。 §5.1.0 簇概念 簇(Cluster)就是将一组有机联系的表在物理上存放在一起并且相同的关键列的值只存储一 份,用于提高处理效率的一项技术。如下图所示( 见 Oracle8i concept ): 151 1.何时建立簇 如果通过引用完整性把两个或多个表联系起来并经常使用联结,则为这些表创建一个 索引簇。如果一个表的多行经常与一个非唯一的列一起查询,则为该列创建一个单表簇,该 列作为簇关键字,以提高性能。 2.有时簇会损害性能 对频繁更新或删除的表使用簇对性能有不利的影响。 3. 限制: l 簇中的每个表必须有一列与簇中指定的列的 大小和类型 匹配; l 簇码中可用列的最大数目是 16,即一个簇最多有 16 列作为簇码; l 列的最大长度为 239 字节; l LONG 和 LONG RAW 不能作为簇列码。 簇键(deptno) 10 DNAME LOC SALES BOSTON EMPNO ENAME . . . 1000 JONES … 1321 SMITH … . . . . . . 20 DNAME LOC ADMIN NEY-YORK EMPNO ENAME . . . 1139 WILLSON … 1277 NORMAN … DEPT 表 DEPTNO DNAME LOC 10 SALE BOSTON 20 ADMIN NEW YORK EMP 表 EMPNO ENAME DEPTNO 1000 JONES 10 1139 WILLSON 20 1321 SMITH 10 1277 NORMAN 20 152 §5.1.1 建立簇 1. 创建簇语法 CREATE CLUSTER cluster ( column datatype[,colmn datatype] …) [PCTUSED 40|intger] [ PCTFREE 10| intger] [ SIZE intger ] [INITRANS 1|intger] [MAXTRANS 255|intger] [TABLESPACE tablespace] [STORAGE storage] 2.创建簇及其表的步骤: 1) 用 CREATE CLUSTER 创建簇 2) 用 CREATE INDEX 创建簇索引 3) 用 CREATE TABLE 创建表,并指定簇 4) 插入数据并进行 DML 操作 例 1: 住房公积金实例 /******************************************************************/ /* 创建单位信息和单位职工汇缴信息所用的簇 emp_unit */ /* 并为簇 emp_unit 创建相应索引 unit_inf_ind */ /* 为创建单位信息和单位职工汇缴信息表作准备 */ /******************************************************************/ prompt 建立单位代码及职工 cluster drop cluster emp_unit; create cluster emp_unit(acc_no varchar2(15)) tablespace user_data storage(initial 1m next 1m maxextents 121 pctincrease 0 ); / create index unit_inf_ind on cluster emp_unit tablespace user_indx; / 153 /******************************************************************/ /* 创建单位信息表 unit_inf,并指定表属于 cluster emp_unit 簇 */ /* 并为表 unit_inf 的 acc_no 列创建相应索引 unit_inf_in */ /******************************************************************/ prompt 建立单位开户登记表(unit_inf) drop table unit_inf; create table unit_inf ( bank_code varchar2(6) , -- 经办行代码 acc_no varchar2(15) , -- 公积金代号(帐号) proc_date date , -- 处理时间 unit_name varchar2(50) , -- 单位名称 Area varchar2(20) , -- 所在区、县 Address varchar2(50) , -- 单位地址 Zip varchar2(6) , -- 邮政编码 Master varchar2(20) , -- 主管部门 Belong varchar2(20) , -- 隶属关系 economic varchar2(20) , -- 经济性质 tot_emp number(6) , -- 职工人数 sal_bank varchar2(40) , -- 发薪银行 sal_acc_no varchar2(20) , -- 发薪户帐户 sal_date number(2) , -- 发薪日 pay_tot number(6) , -- 汇缴人数 pay_money number(13,2) , -- 汇缴总金额 pro_depart varchar2(40) , -- 经办部门 pro_master varchar2(10) , -- 负责人 pro_cotact varchar2(10) , -- 联系人 pro_tel varchar2(15) , -- 电话 save_bank varchar2(40) , -- 公积金经办行名称 bank_add varchar2(40) , -- 经办行地址 bank_cotect varchar2(10) , -- 经办行联系人 bank_tel varchar2(15) , -- 经办行电话 enter_stamp varchar2(40) , -- 填报单位章 enter_date date , -- 填报日期 center_date date , -- 中心盖章日期 status_code char(1) , -- "0 未缴存","1 缴存","2 封存","3 销户" oper_no varchar2(10),-- 操作员 unit_pay_rate number(7,4) ,-- 单位缴交率 per_pay_rate number(7,4) -- 个人缴交率 ) cluster emp_unit ( acc_no ) ; 154 / prompt 建立 单位开户登记 唯一键: acc_no_in create unique index unit_inf_in on unit_inf ( acc_no ) storage ( initial 1M next 512k maxextents 121 pctincrease 0 ) / /******************************************************************/ /* 创建单位职工汇缴信息表 pay_lst_det,并指定到 emp_unit 簇 */ /* 并为表 pay_lst_det 创建相应唯一索引 pay_det_in1 */ /******************************************************************/ prompt 建立开户单位汇缴清册( pay_lst_det ) drop table pay_lst_det; create table pay_lst_det ( bank_code varchar2(6)NOT NULL, -- 经办行代码 acc_no varchar2(15) not null, -- 公积金代码 emp_acc_no varchar2(20) not null, -- 职工帐号 table_date date , -- 编报日期 Name Varchar2(10), -- 姓名 Sex varchar2(2)check(sex='男' or sex='女'), -- 性别 Birth date, -- 出生年月 Per_id varchar2(20), -- 身份证号 Sal Number(7,2) not null, --月工资 Per_pay_rate Number(7,4), --个人缴交率 Per_pay Number(7,2), --个人交缴金额 Unit_pay_rate Number(7,4), --单位交缴金率 Unit_pay Number(7,2), --单位交缴额 pay_money number(13,2) check(pay_money>=5.0), --月应缴额 status_code char(1) , -- "0 未缴存","1 缴存","2 封存","3 销户" Oper_no Varchar2(10) --操作员代码 ) cluster emp_unit ( acc_no ) / create unique index pay_det_in1 on pay_lst_det( per_id ) storage ( initial 10M next 2m maxextents 121 pctincrease 0 ) / create unique index pay_det_in2 on pay_lst_det( emp_acc_no ) 155 storage ( initial 1M next 512k maxextents 121 pctincrease 0 ) / §5.1.2 改变簇 在用户具有 ALTER ANY CLUSTER 的权限情况下,可以对已建好的簇(CLUSTER )改变 其设置,如: l 物理属性:PCTFREE,PCTUSED,INITRANS,MAXTRANS 和 STORAGE; l 为 CLUSTER 关键字值存储所有行所需的一般空间容量; l 缺省平行度。 命令语法: ALTER CLUSTER Cluster_name { PCTUSED integer | PCTFREE integer | SIZE integer | INITRANS integer | MAXTRANS integer | STORAGE Cluase } 例:ALTER CLUSTER emp_dept PCTFREE 30 PCTUSED 60; 对于用 ALTER TABLE 语句只能改变表中非簇列的设置,不能对簇列进行任何的修改。 §5.1.3 删除簇 只要用户具有 DROP ANY CLUSTER 权限均可以对所有的 CLUSTER 进行删除。 语法如下: DROP CLUSTER [user.]cluster [INCLUDING TABLES] 如果使用 INCLUDING TABLES 则删除 CLUSTER 的同时也删除所包含的表。簇表可 以被单个删除而不影响该表所属的簇、其他簇表或者簇索引。删除一个簇表如同删除一个普 通的表一样都可以用 DROP TABLE 来完成。 注意:当用户从簇中删除单个表时,ORACLE 单独删除表中的每一行。删除整个簇的最有效 的方法是使用带有 INCLUDING TABLE 选项的 DROP CLUSTER 语句删除包含所有表的 156 簇。只有当用户仍想保留簇中其它表时才会使用 DROP TABLE 从簇中删除单个表。 §5.1.4 删除簇索引 一个簇的索引可以被删除而不影响表的数据,但是当簇的索引被删除后,属于该簇的表 就变为不可用,所以当删除簇的索引后还须再建立该簇的索引才行。有时为了消除盘空间的 碎片我们常进行删除簇索引操作。删除索引命令见 DROP INDEX 命令。 §5.1.5 收集簇信息 当应用在设计时使用了簇,则用户或数据库管理员都可以通过查询簇的信息来了解簇的情况, 从而进行必要的管理。使用下面命令可以收集属于用户本人的簇信息: l DBA_CLU_COLUMNS 或 USER_CLU_COLUMNS l DBA_CLUSTERS 或 USER_CLUSTER DBA_CLU_COLUMNS 存放有系统实例中所有簇的数据情况。它的结构如下: SQL> desc dba_clu_columns 名称 空? 类型 ----------------------------------------- -------- --------------- OWNER NOT NULL VARCHAR2(30) CLUSTER_NAME NOT NULL VARCHAR2(30) CLU_COLUMN_NAME NOT NULL VARCHAR2(30) TABLE_NAME NOT NULL VARCHAR2(30) TAB_COLUMN_NAME VARCHAR2(4000) 其中: OWNER 创建簇的主人 CLUSTER_NAME 簇的名字 CLU_COLUMN_NAME 簇中的列名 TABLE_NAME 与之相关的表名 TAB_COLUMN_NAME 表中的列名 DBA_CLUSTERS 数据字典存放有簇的详细数据情况,包括存储参数等。结构如下: SQL> desc dba_clusters 名称 空? 类型 ----------------------------------------- -------- -------------- OWNER NOT NULL VARCHAR2(30) CLUSTER_NAME NOT NULL VARCHAR2(30) 157 TABLESPACE_NAME NOT NULL VARCHAR2(30) PCT_FREE NUMBER PCT_USED NOT NULL NUMBER KEY_SIZE NUMBER INI_TRANS NOT NULL NUMBER MAX_TRANS NOT NULL NUMBER INITIAL_EXTENT NUMBER NEXT_EXTENT NUMBER MIN_EXTENTS NOT NULL NUMBER MAX_EXTENTS NOT NULL NUMBER PCT_INCREASE NUMBER FREELISTS NUMBER FREELIST_GROUPS NUMBER AVG_BLOCKS_PER_KEY NUMBER CLUSTER_TYPE VARCHAR2(5) FUNCTION VARCHAR2(15) HASHKEYS NUMBER DEGREE VARCHAR2(21) INSTANCES VARCHAR2(21) CACHE VARCHAR2(11) BUFFER_POOL VARCHAR2(7) SINGLE_TABLE VARCHAR2(11) 关于列的解释见《Oracle8i/9I reference》。 此外,你还可以用 ANALYZE 命令来分析某个簇的数据情况,ANALYZE 命令语法如下: ANALYZE CLUSTER Cluster_name { COMPUTE STATISTICS | ESTIMATE STATISTICS | DELETE STATISTICS | VALIDATE REF UPDATE | VALIDATE STRUCTURE | LIST Chained ROW INTO table_name } 例:ANALYZE CLUSTER students COMPUTE STATISTICS; 当然我们可以从数据字典中查询所统计的结果,如: SELECT AVG-BLOCKS_PER_KEY,INSTANCES,CACHE,BUFFER_POOL FROM USER_CLUSTER WHERE CLUSTER_NAME=’STUDENT_DEPT’; 小结: 158 l ORACLE8 可以对表及其各自的索引建立簇; l 可以对基于主键的簇和基于哈希函数建立簇; l 簇码只能存储一次; l 簇如果正确使用可以涉及复杂的操作和降低磁盘 I/O; l 簇索引必须在任何簇表装入数据之前创建; l 只对使用等号操作符的查询表和表的大小相对静态使用哈希簇; l 建立簇时,可以用 STORAGE 参数分配来优化簇的性能。 §5.2 分区 现代企业运行的数据库一般都达几个 GB 数据量。我们把这写数据库称为超大型数据库 (VLDB=Vary Large Database)。ORACLE 公司从 ORACLE7 开始就提出了分区的方法。到 ORACLE8 后,分区技术已经提供了非常完善的功能。为大型应用系统提供了可能。 §5.2.1 分区的优点 oracle8i 分区选项可以对超大规模数据库(VLDB=Vary large databast)进行分区、使 之可以达到下面目的: l 增强可用性,如果表的一个分区由于系统故障或者维护而得不到使用时,表的其余部分 仍是可用的 l 减少关闭时间,如果系统故障只影响表的某部分,那么只有这部分需要修复,因此修复 工作量减少,所以更快地完成 l 维护轻松,如果需重新连表,那么独立地管理而不是单个大型表的操作要轻松得多。 l 均衡的 I/O,可以把不同分区映射到磁盘以平衡 I/O 并显著改善性能。 l 改善性能,对已分区对象的某些查询可以运行更快,因为搜索仅限于关心的分区。 大数据库 分 离 A部分 B 部分 C 部分 D 部分 159 表和索引分区的示意图 不是所有表都可以被分区,下面是不可分区的情况: l 存在于 oracle8 簇(cluster)中的表不能被分区 l 如果一个表包含非结构性数据,则这个表不能被分区,下面的数据类型就不能进行分区: 1) LOBS 2) LONG RAW 3)对象类型 l 索引组织的表不能被分区。 §5.2.2 分区的方法 ORACLE 提供了对表或索引的三种分区方法: l 范围分区; l 散列(hash)分区; l 复合分区。 1.范围分区方法 根据表中列值的范围进行分区,如一年中的月份,当数据在范围内均匀分布时,性能最好, 否则应考虑其它的分区方法。 当创建范围分区时,要考虑: l 分区方法;范围 l 分区列 l 分区中说明指定分区边界 2.使用散列分区 如果数据不容易进行范围分区,而出现性能原因时就要进行散列分区。 3.复合分区法 复合分区的分区数据使用范围分区法,而在每个分区或子分区内使用散列分区。 §5.2.3 创建表的分区 1.范围分区法 160 1)表的单列分区 create table students ( student_id integer not null, student_first_name varchar2(25), student_last_name varchar2(25), student_dept_id integer, student_address varchar2(50), student_city varchar2(25), … )constraint Dept_id_pk primary key (student_dept_id) partition By Range (student_dept_id) (partition Dept_id_1 values less than(100) tablespace om1, partition Dept_id_2 values less than (250) tablespace om2, partition Dept_id_3 values less than (500) tablespace om3 partition Dept_id_4 values less than (750) tablespace om4 partition Dept_id_5 values less than (max value)table space om5); Student 表根据 students_Dept_id 到值进行分区创建的五个分区的名字和范围值如下: Dept_id_1-范围 0-99 Dept_id_2-范围 100-249 Dept_id_3-范围 250-499 Dept_id_4-范围 500-749 Dept_id_5-范围 750-MAXVALUE 可以用 oracle schema Manager 工具查看表的分区结果。 注:如果划分有空值,应指定 MAXVALUE,这样 oracle8i 将具有空值的列排到大于其它分区 值之后,但此 MAXVALUE 小。 2)表的多列分区 oracle8i 把多列分区码值作为向量来决定一行应放在哪个分区,如: 例 1: create table students ( student_id integer not null, student_first_name varchar2(25), student_last_name varchar2(25), student_dept_id integer, student_address varchar2(50), student_city varchar2(25), 161 … )constraint Dept_id_pk primary key (student_dept_id) partition By Range (student_id,student_Dept_id) partition Dept_id_1 values less than(1000,100)tablespace om1, partition Dept_id_2 values less than(2000,250)tablespace om2, partition Dept_id_3 values less than(3000,500)tablespace om3, partition Dept_id_1 values less than(4000,750)tablespace om4, partition Dept_id_1 values less than(MAXVALUE,MAXVALUE)tablespace om5); 如果一行码值是(2500,150),则该行插入 Dept_id_2 分区中,因为码(2500,x )小于(300,x)且 比(1000,100)大。 例 2: CREATE TABLE sales (invoice_no NUMBER, sale_year INT NOT NULL, sale_month INT NOT NULL, sale_day INT NOT NULL ) PARTITION BY RANGE( sale_year,sale_month,sale_day) ( PARTITION sales_ql VALUES LESS THAN ( 1999,04,01) TABLESPACE tsa, PARTITION sales_q2 VALUES LESS THAN ( 1999,07,01) TABLESPACE tsb, PARTITION sales_q3 VALUES LESS THAN ( 1999,10,01) TABLESPACE tsc, PARTITION sales_q4 VALUES LESS THAN ( 2000,01,01) TABLESPACE tsd ) 3)等同分区 把表对应的索引按照表的分区确定索引的分区称等同分区,如 students 表使用 student_id 和 student_Dept_id 来分区,则该表的索引也使用这二列来分区.优点有: l oracle8i 在复杂的连接,排序操作中改善分区表的执行计划。 l 由于相关表和索引可同时恢复,减少介质恢复时间。 2.使用散列分区法 散列分区提供了一种通过指定分区编号来均匀地分布数据的方法。基于分区键的散列将 被映射到分区上。为创建和使用散列分区给用户提供了 高度灵活的放置数据的方法,因为通 过在 I/O 设备上进行散列分区,使得这些分区在大小上一致。 162 建立散列分区,需要指定下面信息: l 分区方法:散列; l 分区列; l 分区编号或各个分区的说明。 使用 CREATE TABLE 语句加 PARTITION BY HASH 子句可以指定所建的表被散列分区。 下面例子创建一个散列分区。分区列为 ID,创建了四个分区并分配了由系统生成的分区名, 它们被放置在四个被命名的表空间 gear1,gear2,gear3,gear4 上。 例 1: CREATE TABLE scubagear ( id NUMBER, name VARCHAR2(60) ) PARTITION BY HASH(id) PARTITIONS 4 STORE IN ( gear1,gear2,gear3,gear4); 散列分区表的每个分区内保存在不同的节中,且散列数据被放在缺省表空间中。 例 2: CREATE TABLE ( deptno NUMBER,deptname VARCHAR2(32)) STORAGE( INITIAL 10k ) PARTITION BY HASH(deptno) ( PARTITION p1 TABLESPACE ts1, PARTITION p2 TABLESPACE ts2, PARTITION p3 TABLESPACE ts1, PARTITION p4 TABLESPACE ts3 ); 指定了各个分区的名字及它们所存放的表空间。所有分区都继承表空间的初始分配 INITIAL 10k 参数。 3.复合分区方法 复合分区的分区方法数据使用范围分区,而在每个分区或子分区内使用散列分区法。复合分 区对历史数据和带状数据都很理想,并提供范围分区和数据放置的改进的管理性能和散列分 区的并行优点。 建立复合分区,须进行: l 分区方法:范围分区; l 分区列; l 指定分区边界的分区说明; l 子分区方法;散列; l 子分区列; 163 l 每个分区的子分区数量或子分区说明。 例:下面例子创建了三个范围分区,每个分区又包含八个子分区,子分区没有名字,所以赋 予它们系统生成的名字,“STORE IN”子句将它们分布在四个指定的表空间 ts1,ts2,ts3,ts4 中。 CREATE TABLE scubager(equipno NUMBER,equipname VARCHAR(32),price NUMBER) PARTITION BY RANGE(equipno)SUBPARTITION BY HASH(equipname) SUBPARTITIONS 8 STORE IN ( ts1,ts2,ts3,ts4) ( PARTITION p1 VALUES LESS THAN(1000), PARTITION p2 VALUES LESS THAN(2000), PARTITION p3 VALUES LESS THAN(MAXVALUE) ); 4. 对表分区小结 把表的数据范围(range)进行分区存储; 只需在 Create table 或 Alter table 命令中指定即可; 分区名在 Create table 或 Alter table 中指定(给出)即可,不需在任何另外的地方预先说 明。 l 建立表结构时指定区 Create table emp (emp_no number(5), dept varchar2(2), name varchar2(30)) storage(initial 100k next 50k) logging PARTITION BY RANAE (enp_no) (PARTITION acct values less than (1000) tablespace ts1, PARTITION sales values less than (2000) tablespace ts2, PARTITION edue values less than (3000)); Insent into emp values (1226, ′sa′,′smith′); Insent into emp values (2100, ′ed′,′jones′); l 对具有分区的表更新,有以下不足: 1) 不能进行的更新 up date emp set emp _no=1500 where name= ′JONES′; 此条语句将不能运行(引起错误),原因是′Jones′原来是(emp_no=2100)对应的分区为 educ,而现要将其从 educ 分区移至 sales 中,所以不能垮分区修改。 2) 不指定分区的更新(影响效率) update emp set emp_no=1356 where name = ′SMITH′; 3) 指定分区的更新(提高效率) 164 update sale partition (feb96) set s.account_name=upper(s.account_name); l 对具有分区的表进行删除(指定分区效率更高) Delete From sales Partition (nov96) Where amount_of_sale !=0; l 对具有分区的表进行查询 Select * from emp partition acct Where emp_no=999; l 用日期字段作分区条件(详细见《oracle8 sql Reference 》 ) Create table stock_xaction (stock_symbot CHAR(5), stock_series CHAR(1), num_shares Number(10) price Number(5,2) trade_date Date Storage (inltial 100k next 50k)logging PARTITION By range (trade_date) (PARTITION sx1992 values less than (to_date(′01-JAN-1993′, ′DD-MON-YYYY′))Tablespace tso Nologging, PARTITION sx1993 values less than(To-date(′01-JAN-1994′, ′DD-MON-YYYY′))Tablespace ts1, PARTITION sx1994 values less than (To-date(‘01-JAN-1995′, ′DD-MON-YYYY′))Tablespace ts2); l 用 Alter 对表进行分区 可以用下面语句实现分区指定: MODIFY PARTITION partition-name [phsical-attributes-clause] §5.2.3 创建索引的分区 可以创建两种类型的索引分区: l 局部索引 l 全部索引 165 这两种均遵从下列原则: l 分区的索引表不能应用聚类表 l 位图索引必须为局部索引 l 分区和未分区的索引可以应用于分区或未分区的表 1. 局部索引 根据表的分区个数来建立同样的索引分区叫局部索引,如: ( create index Dept_id_1 tablespace om1, create index Dept_id_2 tablespace om2, create index Dept_id_3 tablespace om3, create index Dept_id_4 tablespace om4 create index Dept_id_5 tablespace om5 ); 每个局部索引都与其基于的表等同分区。局部索引有下列优点: l 如果只一个分区需要维护,则只有一个局部索引受影响 l 支持分区独立性 l 只有局部索引能支持单一分区的装入和卸出 l oracle8 更好的查询 l 表分区和各自的局部索引可同时恢复 l 局部索引可以单独重建 l 位图索引仅由局部索引支持 根据前面 STUDENTS 表被划分为 5 个区 DEPT_ID_1,... DEPT_ID_5 。按照上面对各个分区的 进行局部索引的创建,则形象如下图: 166 局部索引 DEPT_IDX ( Dept_idx 图) 2. 全局索引分区 对表的多个分区建立索引分区叫全局索引(分区)一般可以这样认为,未作分区的索引被认 为是全局索引如: create index Dept_idx on students(student_dept_id) GLOBAL partition By range (student_dept_id) (partition Dept_id_1 values less than (1000,100) tablespace om1, partition Dept_id_2 values less than (2000,250) tablespace om2, partition Dept_id_3 values less than (3000,500) tablespace om3, partition Dept_id_4 values less than (4000,750) tablespace om4, partition Dept_id_5 values less than (MAXVALUE,MAXVALUE) tablespace om5; 下面图表示全局索引 Dept_idx 的情况 STUDENTS 表 范 围 划 分 Dept_id_1 Dept_id_2 Dept_id_3 Dept_id_4 Dept_id_5 局部索引 Dept_id_1 局部索引 Dept_id_2 局部索引 Dept_id_3 局部索引 Dept_id_5 局部索引 Dept_id_4 表范围划分 局部索引 DEPT_IDX 167 全局索引 Dept_idx(Dept_idx2 图) 3. 相关的数据字典 DBA_IND_PARTITIONS DBA_TAB_PARTITIONS DBA_PART_COL_STATISTICS USER_TAB_PARTITONS USER_PART_COL_STATISTICS USER_IND_PARTITIONS ALL_TAB_PARTITIONS ALL_IND_PARTITIONS ALL_PART_COL_STATISTICS §5.2.4 维护表分区和索引分区 在了解如何建立表分区和索引分区后,在应用设计中还经常进行分区的维护。下面是维 护分区的简要介绍。 1.用 ALTER TABLE 语句来维护表分区 STUDENTS 表 范 围 划 分 Dept_id_1 Dept_id_2 Dept_id_3 Dept_id_4 Dept_id_5 局部索引 Dept_id x 表范围划分 局部索引 DEPT_IDX 168 维护操作 范围 散列 复合 加入分区 ADD PARTITION ADD PARTITION ADD PARTITION MODIFY PARTITION …ADD SUBPARTITION 合并分区 N/a COALESCE PARTITION MODIFY PARTITION …ADD COALESCE SUBPARTITION 删除分区 DROP PARTITION N/a DROP PARTITION 互换分区 EXCHANGE PARTITION EXCHANGE PARTITION .EXCHANGE PARTITION .EXCHANGE UBPARTITION 合并(merge) 分区 MERGE PARTITION N/a MERGE PARTITION 修改分区缺省 属性 MODIFY DEFAULT ATTRIBUTES MODIFY DEFAULT ATTRIBUTES .MODIFY DEFAULT ATTRIBUTES .MODIFY DEFAULT ATTRIBUTES FOR PARTITION 修改分区实际 属性 MODIFY PARTITION MODIFY PARTITION .MODIFY PARTITION .MODIFY SUBPARTITION 移动分区 MOVE PARTITION MOVE PARTITION MOVE SUBPARTITION 重命名分区 RENAME PARTITION RENAME PARTITION . RENAME PARTITION . RENAME SUBPARTITION 拆分分区 SPLIT PARTITION N/a SPLIT PARTITION 截短分区 TRUNCATE PARTITION TRUNCATE PARTITION .TRUNCATE PARTITION . TRUNCATE SUBPARTITION 2.用 ALTER INDEX 语句来维护索引分区 维护操作 索引 类型 索 引 分 区 类 型 范围 散列 复合 删除索引 分区 全局 本地 DROP PARTITION N/a N/a N/a 修改索引 分区的缺 省值 全局 本地 .MODIFY DEFAULT ATTRIBUTES .MODIFY DEFAULT ATTRIBUTES .MODIFY DEFAULT ATTRIBUTES .MODIFY DEFAULT ATTRIBUTES .MODIFY DEFAULT ATTRIBUTES FOR PARTITION 修改索引 分区的实 际属性 全局 本地 .MODIFY PARTITION .MODIFY PARTITION MODIFY PARTITION MODIFY SUBPARTITION 重 建索引 分区 全局 本地 REBILD PARTITION REBILD PARTITION REBILD PARTITION 重新命名 索引分区 全局 本地 RENAME PARTITION RENAME PARTITION RENAME PARTITION RENAME PARTITION 拆 分 索引 分区 全局 本地 SPLIT PARTITION N/a N/a N/a 169 §5.3 簇与分区有关的数据字典 如果你在应用系统设计时采用了分区和簇技术,则你最好要了解与簇和分区有关的数据 字典。这样对管理有好处。 §5.3.1 分区、簇数据字典列表 下面给出的数据字典有三类,分别以 DBA、ALL 和 USER 开头,如果你具有 DBA 权限,你 只要了解 DBA 开头即可。下面仅给相关数据字典的名字,具体的列名及介绍请见《Oracle8i/9i 数据库管理》。 l ALL_CLUSTERS、DBA_CLUSTER、USER_CLUSTER 存放簇的基本信息。 l DBA_TABLES 存放索引表的信息,其中 cluster_name 表示该表所对应的 Cluster 名字。 l ALL_TAB_PARTITIONS、DBA_TAB_PARTITIONS、USER_TAB_PARTITIONS 存放有关分区的基 本信息,如表名,分区名等。 l ALL_IND_PARTITIONS、DBA_IND_PARTITIONS、USER_IND_PARTITIONS 有关索 引分区的信息。 l ALL_PART_INDEXES、DBA_PART_INDEXES、USER_PART_INDEXES 可访问的分 区的索引。 l ALL_PART_TABLES、DBA_PART_TABLES、USER_PART_TABLES 存放可访问的分区表 的信息。 l ALL_PART_LOBS、DBA_PART_LOBS、USER_PART_LOBS 存放大对象类型的分区 信息。 §5.3.2 基本的分区、簇信息查询 了解数据字典的目的是查询它们的信息和管理。下面给出几个常用查询例子。 例 1.查询与簇有关的表的信息: SQL> col owner for a20 SQL> col table_name for a20 SQL> col tablespace_name for a20 SQL> select OWNER,table_name,TABLESPACE_NAME,CLUSTER_NAME from dba_tables 2* where CLUSTER_NAME is not null; OWNER TABLE_NAME TABLESPACE_NAME CLUSTER_NAME -------------------- -------------------- -------------------- -------------- SYS IND$ SYSTEM C_OBJ# SYS CLU$ SYSTEM C_OBJ# SYS ICOL$ SYSTEM C_OBJ# 170 SYS FET$ SYSTEM C_TS# SYS CDEF$ SYSTEM C_COBJ# . . . . . . 已选择 33 行。 例 2.查询进行过分区的表的信息: SQL> select TABLE_OWNER,TABLE_NAME,PARTITION_NAME,TABLESPACE_NAME 2 from DBA_TAB_PARTITIONS; 未选定行 SQL> 第六章 使用 SQL 进行数据操作 大家都知道,关系数据库中使用最频繁的 SQL 语句可以是 SELECT 、INSERT、UPDATE 及 DELETE 语句了,尽 管 它 们使 用简单,但也是变化最多和最能衡量一个编程人员水平的语 句了。下面就增、删、改作简要介绍。 §6.1 INSERT 操作 INSERT 语句可以完成对表、视图及快照(snapshot)进行数据插入。插入的数据依不同 的版本而允许插入的数据类型也不同,最新版本可以在子查询中使用 LOB 数据类型。现在 最新的版本仍有下面限制: l 不能在语句中使用并行,也不允许从远程进行插入; l 在子查询中不允许使用带有 long 类型的字段。 1.INSERT 命令语法: INSERT INTO [user.]table[@db_link][(column1[,column2]...)] VALUES ( express1[,express2]...|subquery...); 2 . 日期的插入 INSERT into emp_house_fund(name,emp_acc_no,tran_date,tran_val) VALUES('赵元杰','123456',to_date('06/09/2000','dd/mm/yyyy'),99.9); 171 INSERT into emp_house_fund(name,emp_acc_no,tran_date,tran_val) VALUES('赵元杰','123456',to_date('2000.06.09','yyyy.mm.dd'),99.9); INSERT into emp_house_fund(name,emp_acc_no,tran_date,tran_val) VALUES('赵元杰','123456',to_date('06092000','ddmmyyyy'),99.9); 3.带 select 的插入 SQL> create table emp_house_fund_sum( per_id verchar2(20), tran_val number(9,2)); SQL> insert into emp_house_fund_sum select per_id,sum(tran_val) From emp_house_fund grou by per_id; SQL>select a.name, b.per_id,b.tran_val from emp_house_fund a,emp_house_fund_sum b where a.per_id=b.per_id; §6.1.1 用文字插入操作 INSERT INTO dept VALUES (50, ‘PRODUCTION’,’SAN FRANCISCO’); INSERT INTO emp (empno, ename, job, sal, comm, deptno) VALUES (7890, ‘LINKS’,’CLERK’,1.2E3, NULL, 40); 下面语句完成同样的功能,只是用了子查询: INSERT INTO (SELECT empno, ename, job, sal, comm, deptno FROM emp) VALUES (7890, ‘LINKS’,’CLERK’,1.2E3, NULL, 40); §6.1.2 用子查询插入操作 INSERT INTO bonus SELECT ename, job, sal, comm FROM emp WHERE comm > 0.25 * sal OR job IN (‘PRESIDENT’,’MANAGER’); 分区的例子: 插入到 SALES表的 OCT98 分区中: INSERT INTO sales PARTITION (oct98) 172 SELECT * FROM latest_data; 绑定变量的例子:下面例子将插入结果返回到变量: INSERT INTO emp VALUES (empseq.nextval, ‘LEWIS’ ‘CLARK’ 7902, SYSDATE, 1200, NULL, 20) RETURNING sal*12, job INTO :bnd1, :bnd2; 插入 LOB 数据类型的例子: 1)插入一个带 long raw 的表: CREATE TABLE long_tab (long_pics LONG RAW); 2)建立一个带 LOB的表: CREATE TABLE lob_tab (lob_pics BLOB); 3)用下面预计完成将 long raw 插入到 LOB 中: INSERT INTO lob_tab (lob_pics) SELECT TO_LOB(long_pics) FROM long_tab; 4)可以将带有long raw 的列删除掉: ALTER TABLE long_tab DROP COLUMN long_pics; 插入BFILE 的例子: INSERT INTO emp VALUES (1, BFILENAME (‘a_dir_alias’, ‘a_filename’); §6.2 UPDATE 操作 1. UPDATE 语法 UPDATE [user.]table[@db_link][alias] SET { column1=express1[,column2=experss2]...| (column1[,column2]...)=(subquery) } [WHERE condition|current of cursor]; 2.一般的修改 如果起息日为空时以处理日作为该记录的起息日: SQL>update emp_house_fund set tran_date=sysdate Where proc_date=sysdate and tran_date is null; 3. 带 null 的修改 SQL>update emp set per_id=null where length(per_id)<15 or Substr(per_id,15,1) > 1; 173 §6.2.1 用文字更新操作 在一般情况下,我们经常使用文字更新操作,即在 UPDATE 语句中直接将要更新的数 值写在语句中,如: UPDATE emp SET job = ’MANAGER’, sal = sal + 1000, deptno = 20 WHERE ename = ’JONES’; UPDATE accounts@boston SET balance = balance + 500 WHERE acc_no = 5001; 限制: l 不能在并行语句中使用或在远程进行更新; l 不能在更新子句中对LONG类型进行更新。 §6.2.2 用查询更新操作 在 Oracle 中,可以根据查询结果来更新表的数据。比如,在申请基金项目时,不允许一个人 在大学申请项目又在大学的研究所中申请项目,则可使用下面例 1 的语句来实现检查。 例 1: SQL>update colle_subjects set app_flag='0' Where per_id in ( select per_id from univ_subjects ); 例 2: SQL>update comfort set ( noon, midnigt )= (select humiddity,temperature from weather where city='MANCHESTER') where City='WALPOLE' and Sampledate=to_date('22-dec-2000','DD-MON-YYYY'); 例 3: UPDATE sales PARTITION (feb96) s SET s.account_name = UPPER(s.account_name); 174 §6.2.3 用相关子查询更新操作 同样可以在更新中使用相关的查询操作,如: 例 1.复杂 UPDATE 语句: UPDATE emp a SET deptno = (SELECT deptno FROM dept WHERE loc = ’BOSTON’), (sal, comm) = (SELECT 1.1*AVG(sal), 1.5*AVG(comm) FROM emp b WHERE a.deptno = b.deptno) WHERE deptno IN (SELECT deptno FROM dept WHERE loc = ’DALLAS’ OR loc = ’DETROIT’); 例2:相互更新的例子: UPDATE TABLE(SELECT projs FROM dept d WHERE d.dno = 123) p SET p.budgets = p.budgets + 1; §6.3 DETELE 操作 在应用中,可以使用 delete 语句实现将不需要的记录进行删除。值得注意的是,经常使用 DELETE 语句对表的记录进行有条件的删除。而无条件的全表删除需要一定的技巧。请看下 面的例子。 §6.3.1 用delete 删除全部记录的操作 1. DELETE 语法 DELETE [ FROM ] [user.]table [@db_link][Alias] [WHERE condition]; 这里的 condition 可以复杂的表达式或子查询。 175 2.例子: SQL> delete from house.emp_house_fund; SQL>delete from colle_subjects Where per_id in ( select per_id from univ_subjects ); §6.3.2 用delete 有条件删除部分记录 删除语句用的最多应该是有条件的删除记录。如果我们不是有条件的删除的话,我们应 该采用直接建立一个新表、DROP 旧表的方法来达到我们的目的。 例 1: DELETE FROM temp_assign; 例 2: DELETE FROM emp WHERE JOB = ’SALESMAN’ AND COMM < 100; 例 3: DELETE FROM (select * from emp) WHERE JOB = ’SALESMAN’ AND COMM < 100; 限制: l 不能使用并行或带远程对象 l 不能用 LONG 类型 §6.3.3 用delete 分段删除大量记录 有时我们需要删除大块的数据,在环境比较差的情况下,往往由于回滚段不够大而出现 删除失败。这样我们可以采用以下两种方法来达到删除大量数据的目的。 例 1:用 rownum 来限制每次删除的记录数目: DELETE from emp where deptno=9999 and rownum < 1000; 176 例 2:编写一个简单的存储过程,如: SQL>get del_rec DECLARE TMP VARCHAR2(1); BEGIN LOOP BEGIN /* 下面语句确定是否还有可删的记录,如果没有就直接到 EXCEPTION */ SELECT ‘X’ INTO TMP FROM SAMPLE WHERE ROWNUM = 1; /* 如果 SAMPLE 还有数据就执行删除一组操作,即使不够 20 条也不会出错 */ DELETE FROM SAMPLE WHERE ROWNUM<20; COMMIT; EXCEPTION WHEN NO_DATA_FOUND THEN EXIT; END; END LOOP; END; §6.4 insert、delete 及 update 的提交和撤消 与桌面数据库最大的区别是,所有的关系数据库在事务处理操作中,可以对每个事务 进行提交或撤消。当我们在进行 insert、update、delete 时,都可以根据当前的处理情况来确 定目前的操作是提交或撤消。 §6.4.1 自动提交的设置 为了保证在 SQL>方式下进行 INSERT、DELETE 和 UPDATE 操作达到安全的目的,一 般 在 SQL> 下进行 INSERT、DELETE 和 UPDATE 操作前,建议将环境设置成为非自动提交的方式。 我们可以在 SQL>下用 show autocommit 命令查看当前该参数的状态。如果状态是 ON,则建 议用下面命令将其设置为 OFF 状态,这样做主要目的是:即使误删除某些记录也可以用 ROLLBACK 命令进行恢复。 l 查看当前的提交状态: SQL>show autocommit autocommit OFF l 设置是否自动提交的命令: SET AUTO[commit]{ON|OFF|IMM{[EDIATE]|n}(oracle8 SET AUTO[commit]{ON|OFF|IMM{[EDIATE]}(oracle7 177 当设为 imm 时,每作一个修改操作均自动提交。 当设 n(n 为一个整数),当作过 n 个修改时自动提交。 l 设置为非自动提交: SQL>set autocommit off l 设置为自动提交: SQL>set autocommit on l Commit Commit Complete (这样的命令表示以前的操作到目前为止都进行提交,不是仅提交当前的操作) l rollback rollback complete (只回滚那些未被提交的且最近一次的那些事务) l 隐含提交 虽然有的操作并不发出 commit,但我们用 exit 退出后系统会自动提交,目前 exit 等价于 quit,以前 oracle v5 如果用 quit 退出,则所作修改不提交。 l 自动回滚 oracle 在遇到异外情况下,如断电,系统故障时,自动采取回滚。 例。 SQL>show user User 为“SCOTT” SQL>show autocommit Autocommit off SQL> SQL> update emp set sal = sal*1.2 where deptno=10; 已更新 2 行。 SQL> rollback; 重算已完成。 §6.4.2 保留点和撤消 我们可以使用 ROLLBACK 命令撤消最近一次所做的操作,要想实现对前面的所有各个操 178 作也要撤消的话,就必须在每个操作命令前设置相应的保留点。当对每个操作都设置了相应 的保留点,我们就可以根据需要用 ROLLBACK TO xx 来实现撤消到某一步。 l SAVEPOINT 命令 SAVEPOINT savepoint_work; 其中: savepoint_work 是要设置的保留点标识。 l ROLLBACK 命令 ROLLBACK [WORK ] [TO [SAVEPOINT] savepoint_work] 其中: savepoint_work 是要设置的保留点标识。 例子: -- 看当前用户的名字 SQL> show user USER 为"ZHAO" -- 先查看 emp 表的记录数 SQL> select * from emp; ENAME SAL DEPTNO TEL -------------------- ------------ ------------ ----------------- 赵元杰 99999.12 10 1360 136 5681 张 x 8888.88 10 12345 -- 设置第 1 个保留点 a SQL> savepoint a; 保存点已创建。 --插入第 1 条记录 SQL> insert into emp values('John',123.45,20,'56789'); 已创建 1 行。 -- 设置第 2 个保留点 b SQL> savepoint b; 保存点已创建。 --插入第 2 条记录 SQL> insert into emp values('Scott',456.78,20,'13601361234'); 179 已创建 1 行。 -- 设置第 3 个保留点 c SQL> savepoint c; 保存点已创建。 -- 插入第 3 条记录 SQL> insert into emp values('赵 x',3210.1,20,'62348901'); 已创建 1 行。 -- 查询到目前为止的 emp表记录数 SQL> select * from emp; ENAME SAL DEPTNO TEL -------------------- ---------- ---------- -------------------- 赵元杰 99999.12 10 1360 136 5681 张 x 8898.88 10 12345 John 123.45 20 56789 Scott 456.78 20 13601361234 赵 x 3210.1 20 62348901 -- 要求撤消到第 2 步,即撤消到保留点 b SQL> rollback to b; 重算已完成。 -- 再查询撤消后的 emp 表记录情况 SQL> select * from emp; ENAME SAL DEPTNO TEL -------------------- ---------------- -------- -------------------- 赵元杰 99999.12 10 1360 136 5681 张 x 8898.88 10 12345 John 123.45 20 56789 SQL> 注意:撤消的处理必须是在没有发出 COMMIT 命令的前提下才能有效。 180 第七章 复杂查询语句的使用 在关系数据库中,select 语句是使用最频繁的语句。它的处理复杂程度可依据业务的要 求的不同而不同。它是程序员和管理员必需的语句。前面已经进行过介绍,但下面从较为复 杂的程度来介绍它的使用情况。 §7.1 复杂查询语句的使用 使用 SELECT 语句和子查询(SUBQUERY)可以从一个或多个表、视图、实体视图中返回 数据。 §7.1.1 相关子查询 可以将子查询(前面提到的 as subquery )或 In 或 exists 当成 where 的一个条件的 一部分,这样的查询称作子查询。 l where 中可以包含一个 select 语句子查询; l where 中可以包含 IN, EXISTS 语句; l 最多可嵌套 16 层; l 层数过多会影响性能。 例:比 如 一个查询是否有专家既以研究所的名义申请基金项目又以大学系为单位申请项目(按 规定只能以一个单位来申请): SQL>select name,per_id,dept_name from univ_subjects Where per_id in ( select per_id from colle_subjects ); §7.1.2 外连接 招生中,如果所有学生的信息放在 students 表中,而部分有特长的学生在另一个表 student_skill 中同样有该学生信息。现在要全部列出所有学生,如果某个学生在表 student_skill 中有其特长信息,就显示特长内容,如果某个学生没有特长(在表 student_skill 中无其特长信息)就显示特长为空: SQL>select a.st_id, name, age,skill from students a, student_skill b Where a.st_id=b.st_id(+) Order by a.name; Students 结构为: 181 St_id varchar(20), Name varchar2(10), Age number(2), Tot_score number(3), ... ... Student_skill 结构为: St_id varchar(20), Skill varchar2(20), ... ... Students 的记录,Student_skill 的记录少。上面的“+”跟在记录少的表后面,它表示当 没有与 a.st_id 匹配时就为 b.st_id 增加一空行。 St_id name tot_score skill ---------- ---------- ------------- ------------------ 1111 aaaa 600 足球 2222 bbbb 590 篮球 3333 cccc 620 4444 dddd 610 跳高 ... ... §7.1.3 自我连接 自我连接是在同一个表或视图内进行条件连接。下面语句返回的是每个雇员的名字及该雇员 的经理的名字: SELECT e1.ename||’ works for ’||e2.ename "Employees and their Managers" FROM emp e1, emp e2 WHERE e1.mgr = e2.empno; Employees and their Managers ------------------------------- BLAKE works for KING CLARK works for KING JONES works for KING FORD works for JONES SMITH works for FORD ALLEN works for BLAKE WARD works for BLAKE MARTIN works for BLAKE SCOTT works for JONES TURNER works for BLAKE ADAMS works for SCOTT 182 JAMES works for BLAKE MILLER works for CLARK 连接条件是 e1.mgr = e2.empno §7.1.4 UNION,INTERSECT及 MINUS 有时需要从多个表中组合具有一种相似类型的信息。Union 可以完成将两个以上的表 的相类似的查询结果合并在一起,并且相同的只取其一;如果 union all 则表示返回所有行 (不管是否重复)。Intersect 返回在两个表中都有相同内容的信息。Minus 则返回只在一个 表中出现的信息。 1. 语法: select ... union[all] select ... select ... intersect select ... select ... minus select ... 例: sql> select sum(balance) into lf_return from ( select sum(nvl(tran_val,0)*decode(db_cr_flag,'1',1,'0',-1,0) ) balance from per_fix_det where acc_no=as_acc_no union all select sum(nvl(tran_val,0)*decode(db_cr_flag,'1',1,'0',-1,0) ) balance from per_detail where acc_no=as_acc_no ); 列出有特长的考生(在表 students,student_skill 同时出现): sql>select name from sutdents intersect select name from student_skill; 183 列出没有特长的考生(仅在表 students 出现): sql>select name from sutdents minus select name from student_skill; §7.2 创建复杂的视图 许多应用系统都可能有统计等功能,没有经验的开发者可能在开发工具端来写这些语 句。比如在 POWER BUILDER 中加上复杂的统计与排序等处理。其实,这样很不好。建议把这 些复杂语句写成视图更好。下面就介绍几个常用的视图。 §7.2.1 分组视图 例 1: CREATE OR REPLACE VIEW dept_tot as select a.dname dept,sum(b.sal) total_sal from dept a,emp b where a.deptno=b.deptno group by a.dname 例 2: CRATE OR REPLACE ITEMTOT AS SELECT PERSION,SUM(AMOUNT) ITEMTOT FROM LEDGER WHERE ACTIONDATE BETWEEN TO_DATE(‘01-MAR-1901’,’DD-MON-YYYY’) and TO_DATE(‘31-MAR-1901’,’DD-MON-YYYY’) And ACTION IN ( ‘BOUGHT’,’RAID’) GROUP BY PERSION; §7.2.2 合计视图 例: CREATE VIEW empvi AS SELECT DEPTNO,SUM(SAL),SUM(COMM) FROM EMP GROUP BY DEPTNO; 184 §7.2.3 组合视图 例: CREATE OR REPLACE VIEW BYITEM AS SELECT L.persion persion.item, Amount, 100*amount/itemtotal bypersion, 100*amount/total bytotal from ledgerl L ,iteamtotal I, total where L.persion=I.persion and actiondate between to_date(‘01-MAR-1901’,’DD-MON-YYYY’) and TO_date(‘31-MAR-1901’,’DD-MON-YYYY’) And ACTION IN(‘BOUGHT’,’PAID’); §7.3 家族树 ORACLE 提供了一个有趣的功能 connect by 子句,它可以对具有家族树结构的分枝进 行排序。它的用途有 机构或公司的各层结构,财务的科目代码等。 要使用查询遍历,需要在将数据在基表中按照层次结构进行存储。比如一个组织机构就 是这样的典型例子。 实现语句: SELECT column FROM table_name START WITH column=value CONNECT BY PRIOR 父主键=子外键 §7.3.1 排除单一体和分枝 例 1:在 ORACLE 的 EMP 表中,每一条记录都有一个唯一标识当前雇员的 empno和标 识这个雇员的经理的 mgr 列。如果 mgr 为空,则该雇员是该机构的最顶级。现在要列出每个 雇员的层次结构(从顶到底): select lpad(' ',4*(level-1))||ename name ,empno,mgr from emp start with mgr is null connect by prior empno=mgr; NAME EMPNO MGR -------------------- --------- --------- 185 KING 7839 JONES 7566 7839 SCOTT 7788 7566 ADAMS 7876 7788 FORD 7902 7566 SMITH 7369 7902 BLAKE 7698 7839 ALLEN 7499 7698 WARD 7521 7698 MARTIN 7654 7698 TURNER 7844 7698 JAMES 7900 7698 CLARK 7782 7839 MILLER 7934 7782 14 rows selected. SQL> 从查询结果中可以看出,由于 JONES、BLAKE、CLARK 的上司是 KING,所以 JONES 等 MGR(经理编号)=KING 的 empno号,即 KING 的直接下级是 JONES、BLAKE、CLARK,因 为他们的 MGR 与 KING 的 EMPNO 一样。 §7.3.2 遍历至根 例 2:现在要从某个雇员往他的上级列出该雇员的层次结构(从顶到底): SQL> col ename for a30 SQL> l select lpad(' ',4*(level-1))||ename ename,mgr,empno from emp start with mgr=7788 connect by prior mgr= empno SQL> / ENAME MGR EMPNO ------------------------------ ----- --------- ADAMS 7788 7876 SCOTT 7566 7788 JONES 7839 7566 KING 7839 例 3:现在要列出所有雇员的层次结构(从顶到底): 186 select lpad(' ',4*(level-1))||ename name ,empno,mgr from emp start with mgr is not null connect by empno=prior mgr NAME EMPNO MGR -------------------- --------- ----- SMITH 7369 7902 FORD 7902 7566 JONES 7566 7839 KING 7839 ALLEN 7499 7698 BLAKE 7698 7839 KING 7839 WARD 7521 7698 BLAKE 7698 7839 KING 7839 JONES 7566 7839 KING 7839 MARTIN 7654 7698 BLAKE 7698 7839 KING 7839 BLAKE 7698 7839 KING 7839 CLARK 7782 7839 KING 7839 SCOTT 7788 7566 JONES 7566 7839 KING 7839 TURNER 7844 7698 BLAKE 7698 7839 KING 7839 ADAMS 7876 7788 SCOTT 7788 7566 JONES 7566 7839 KING 7839 JAMES 7900 7698 BLAKE 7698 7839 KING 7839 FORD 7902 7566 JONES 7566 7839 KING 7839 MILLER 7934 7782 CLARK 7782 7839 187 KING 7839 38 rows selected. §7.4 在from 中使用视图 在 SELECT 语句中,当对一个表或视图查询时,语句要求视图是必须存在的。在 ORACLE7.2 版以后。当该视图不存在时,我们可以在 FROM 子句后写上该视图即可。 详细例子如下: 1.假设有下面视图: CREATE OR REPLACE VIEW TOTAL AS Select SUM(amount) TOTAL From ledger Where actiondate between To_date(‘01-MAR-1901’,’DD-MON-YYYY’) and To_date(‘31-MAR-1901’,’DD-MON-YYYY’) And action in(‘BOUGHT’,’PAID’); 2.我们可以像下面来使用视图( FROM 之后的 TOTAL 是视图): SELECT PERSON,AMOUNT,100*AMOUNT/TOTAL From LEDGER,TOTAL Where actiondate between To_date(‘01-MAR-1901’,’DD-MON-YYYY’) and To_date(‘31-MAR-1901’,’DD-MON-YYYY’) And action in(‘BOUGHT’,’PAID’); 3.如果不建立 TOTAL 视图,也可以使用下面语句来完成同样的工作: SELECT PERSON,AMOUNT,100*AMOUNT/TOTAL From LEDGER, ( select SUM(Amount) TOTAL from Ledger Where actiondate between To_date( ‘01-MAR-1901 ’,’DD-MON-YYYY ’) and To_date( ‘31-MAR-1901 ’,’DD-MON-YYYY ’) And action in( ‘BOUGHT ’,’PAID’) ) Where actiondate between To_date(‘01-MAR-1901’,’DD-MON-YYYY’) and To_date(‘31-MAR-1901’,’DD-MON-YYYY’) And action in(‘BOUGHT’,’PAID’); 188 第八章 一些高级的用法 这里给出一点不作为一般要求的内容,它虽然不是必需的,但对于应用开发来说很重要。希 望 Oracle 应用设计者把它应用到系统的设计中。 §8.1 关于DECODE DECODE 是 Oracle 公司独家提供的功能,它是一个功能很强的函数。它虽然不是 SQL 的标准,但对于性能非常有用。到目前,其他的数据库供应商还不能提供类似 DECODE 的 功能,甚至有的数据库的供应商批评 Oracle 的 SQL 不标准。实际上,这种批评有些片面或 不够水平。就象有些马车制造商抱怨亨利。福特的“马车”不标准一样。 §8.1.1 DECODE 中的 if-then-else 逻辑 在逻辑编程中,经常用到 If – Then –Else 进行逻辑判断。在 DECODE 的语法中,实 际上 就 是这样的逻辑处理过程。它的语法如下: DECODE(value, if1, then1, if2,then2, if3,then3, . . . else ) Value 代表某个表的任何类型的任意列或一个通过计算所得的任何结果。当每个 value 值被测 试,如果 value 的值为 if1,Decode 函数的结果是 then1;如果 value 等于 if2,Decode 函数结 果是 then2;等等。事实上,可以给出多个 if/then 配对。如果 value 结果不等于给出的任何配 对时,Decode 结果就返回 else 。 需要注意的是,这里的 if、then 及 else 都可以是函数或计算表达式。 §8.1.2 DECODE 的简单例子 Oracle 系统中就有许多数据字典是使用 decode 思想设计的,比如记录会话信息的 V$SESSION 数据字典视图就是这样。我们从《Oracle8i Reference》资料中了解到,当用户登 录成功后在 V$SESSION 中就有该用户的相应记录,但用户所进行的命令操作在该视图中只 记录命令的代码(0—没有任何操作,2—Insert…),而不是具体的命令关键字。因此,我们 需要了解当前各个用户的名字及他们所进行的操作时,要用下面命令才能得到详细的结果: select sid,serial#,username, DECODE(command, 0,’None’, 2,’Insert’, 189 3,’Select’, 6,’Update’, 7,’Delete’, 8,’Drop’, ‘Other’) cmmand from v$session where username is not null; §8.1.3 DECODE 实现表的转置 数据库中的表是由列和行构成的一个二维表。一般列在任何数据库中都是有限的数量,而行 的变化较大,如果表很大,行的数量可能大上千万行。同一列的不同行可能有不同的值,而 且不是预先定义的。 除上面描述表具有的一些特点外,有一些表可以看成是不变的或者是较稳定的,比如住房公 积金系统是各个单位按照职工的工资数的比例交到本地的经办行中,它的处理流程如下: 例 1.住房公积金报表置换实例: 1.各个单位在本地经办行进行开户,开户就是将单位的基本信息和职工信息的进行登记; 2.每月各个单位的会计到经办行交缴本单位的所有职工的住房公积金,系统记录有每个职工 的交缴明细并在每条记录上记录有经办行的代码; 3.每月、季、半年及年终都要求将经办行 变为“列”给出个月的明细报表: 经办行:城西区 城东区 。 。 。 月份: 2001.01 xxxx1.xx xxxxx2.xx 2001.02 xxxx3.xx xxxxx4.xx 。 。 。 。 。 。 原来的数据顺序是: 城西区 2001.01 xxxxx1.xx 城东区 2001.01 xxxxx2.xx 城西区 2001.02 xxxxx3.xx 城东区 2001.02 xxxxx4.xx 住房公积金系统记录职工的每月交缴名细的 pay_lst 表结构是: bank_code varchar2(6)NOT NULL, -- 经办行代码 acc_no varchar2(15) not null, -- 单位代码(单位帐号) emp_acc_no varchar2(20) not null, -- 职工帐号 tran_date date not null, -- 交缴日期 tran_val Number(7,2) not null, -- 交缴额 sys_date date default sysdate, --系统日期 190 oper_id varchar2(10) --操作员代码 这样的表结构,一般按照将经办行作为行进行统计是很容易的,但是如果希望将经办行变为 列这样的格式来输出就有困难。如果用 DECODE 函数来处理则变得很简单: 我们创建一个视图来对目前的 pay_lst 表进行查询。将经办行代码变为一些具体的经办行名 称即可: CREATE OR REPLACE VIEW bank_date_lst AS Select to_char(tran_date,’yyyy.mm’), SUM( DECODE ( bank_code,’001’, tran_val,0 )) 城西区, SUM( DECODE ( bank_code,’002’, tran_val,0 )) 城南区, SUM( DECODE ( bank_code,’003’, tran_val,0 )) 城东区 FROM pay_lst GROUP BY to_char(tran_date,’yyyy.mm’); 例 2.希望将下面的列结果按照列的方式来显示 JOB 内容: SQL> select empno,ename,job,sal,deptno from emp 2 order by deptno,job; EMPNO ENAME JOB SAL DEPTNO ---------- ---------- --------- ---------- ---------- 7934 MILLER CLERK 1300 10 7782 CLARK MANAGER 2450 10 7839 KING PRESIDENT 5000 10 7788 SCOTT ANALYST 3000 20 7369 SMITH CLERK 800 20 7876 ADAMS CLERK 1100 20 7566 JONES MANAGER 2975 20 7938 赵元杰 软件 12345 20 7698 BLAKE MANAGER 2850 30 7499 ALLEN SALESMAN 1600 30 7654 MARTIN SALESMAN 1250 30 7844 TURNER SALESMAN 1500 30 7521 WARD SALESMAN 1250 30 18 rows selected. 191 再看下面的查询结果: SQL> select deptno,job,sum(sal) from emp group by deptno,job; DEPTNO JOB SUM(SAL) ---------- --------- ---------- 10 CLERK 1300 10 MANAGER 2450 10 PRESIDENT 5000 20 ANALYST 3000 20 CLERK 1900 20 MANAGER 2975 20 软件 74070 30 MANAGER 2850 30 SALESMAN 5600 9 rows selected. 从上面的结果看,如果希望将 JOB 置换成列的方式,则只要用 DECODE 将 JOB 列进行描述即可。 创建的视图如下: create or replace view empv as select deptno, sum( decode(job,’ANALYST’, sal,0)) ANALYST, sum( decode(job,’CLERK’, sal,0)) CLERK, sum( decode(job,’MANAGER’, sal,0)) MANAGER, sum( decode(job,’PRESIDENT’, sal,0)) PRESIDENT, sum( decode(job,’SALESMAN’, sal,0)) SALESMAN, sum( decode(job,’软件’, sal,0)) 软件 from emp group by deptno; 具体运行的显示样本如下: SQL> create or replace view empv as 2 select deptno, 3 sum( decode(job,'ANALYST', sal,0)) ANALYST, 4 sum( decode(job,'CLERK', sal,0)) CLERK, 5 sum( decode(job,'MANAGER', sal,0)) MANAGER, 6 sum( decode(job,'PRESIDENT', sal,0)) PRESIDENT, 7 sum( decode(job,'SALESMAN', sal,0)) SALESMAN, 8 sum( decode(job,'软件', sal,0)) 软件 9 from emp group by deptno; 192 View created. SQL> select * from empv; DEPTNO ANALYST CLERK MANAGER PRESIDENT SALESMAN 软件 ---------- ---------- ---------- ---------- ---------- ---------- ---------- 10 0 1300 2450 5000 0 0 20 3000 1900 2975 0 0 74070 30 0 0 2850 0 5600 0 §8.2 关于访问远程数据库 在许多环境中,都可能需要访问远程数据库。现在的 Oracle8i/9I 的 NET 都支持远程访问技 术。只要环境网络具备和在参数文件中进行相应的配置就能在 SQL 语句中进行访问。关于环 境的安装和配置另见 DBA 资料。 §8.2.1 数据库链接 Oracle 本地要与远程进行连接,要通过数据库链接。 1.使用数据库链接进行查询和更新: SELECT * from worker; 这样的语句表示在本地进行查询。而对于远程,则需要在语句后加相应的数据库链接。如: SELECT * FROM worker@remote_connect; 如果想省去@号后面的字串,可以采用建立一个本地的同义词来实现。如: CREATE SYNONYM WORKER_SYN for WORKER@remote_connect; 如果希望进行远程更新的话,类似可以在 UPDATE 语句中加上远程连接符。如: UPDATE worker@remote_connect SET lodging=’CRANMER’ where lodging=’ROSE HILL’; 2.创建数据库链接的语法: 创建数据库链接的语法如下: 193 CREATE [PUBLIC] DATABASE LINK remote_connect CONNECT TO username identified by password using ‘connect string’; 一般 PUBLIC 有 DBA 来创建。个人用户可以不加 PUBLIC 就是私有的数据库链接。 Oracle 系统可以创建链接,但是连接的数量有限制。缺省的并发数是 4(由 init.ora 文件中 的 OP_LINKS 来限制)。 为了建立数据库链接,需要有 CREATE DATABASE LINKS 系统权限;要与远程的帐号进行连接 还需要有 CREATE SESSION 普通权限。 CREATE database link zhao connect to zhaoyuanjie identified by zhao_yuan_jie Using ‘sun450’; 这样创建后,可以用下面语句来使用: SELECT * from tst@sun450; 需要注意的是,在创建数据库链接时是根据 Oracle 的 Tnsnames.ora 参数文件中的连接字符 串来填写连接字串。比如上面的连接字串是 sun450 。则在 tnsmaes.ora 中的要有下面的数 据项: SUN450 = (DESCRIPTION = (ADDRESS_LIST = (ADDRESS = (PROTOCOL = TCP)(HOST = dbsvr)(PORT = 1521)) ) (CONNECT_DATA = (SERVICE_NAME = s450) ) ) §8.2.2 使用同义词获得本地透明 在应用系统的生命周期内,为了方便和维护简便,经常采用建立同义词来实现透明的访问。 例1. 没有建立本地透明时的访问: SELECT * FROM north.worker; 例 2.建立一个同义词,然后进行访问: CREATE SYNONYM WORKER FOR NORTH.WORKER; 194 SELECT * FROM WORKER; 在实际应用中,为了达到隐藏表的所有权,还可以通过使用数据库链接和同义词来隐藏数据 的物理位置。通过使用对应远程端的本地表同义词,可以把另一个逻辑层从应用转移到数据 库中。 例 3.建立一个本地同义词的远程表: CREATE SYNONYM WORKERSKILL For WORKERSKILL@remote_connect; §8.2.3 在视图中使用 user 伪列 Oracle 提供一个伪列 user, 它可以在创建视图中使用,从而实现对结果的返回的限制。如: CREATE OR REPLACE VIEW emp_lst AS select * from emp Where ename=user; 这样的视图表示,只有使用者的用户名与 ename 中的名字一样,才能返回相关的记录。看下 面的结果就会明白: SQL> CREATE OR REPLACE VIEW emp_lst 2 AS select * from emp 3 Where ename=user; View created. SQL> select * from emp; EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTN ---------- ---------- --------- ---------- --------- ---------- ---------- --------- 7369 SMITH CLERK 7902 17-DEC-80 800 2 7499 ALLEN SALESMAN 7698 20-FEB-81 1600 300 3 7521 WARD SALESMAN 7698 22-FEB-81 1250 500 3 7566 JONES MANAGER 7839 02-APR-81 2975 2 7654 MARTIN SALESMAN 7698 28-SEP-81 1250 1400 3 7698 BLAKE MANAGER 7839 01-MAY-81 2850 3 7782 CLARK MANAGER 7839 09-JUN-81 2450 1 7788 SCOTT ANALYST 7566 19-APR-87 3000 2 7839 KING PRESIDENT 17-NOV-81 5000 1 195 7844 TURNER SALESMAN 7698 08-SEP-81 1500 0 3 7876 ADAMS CLERK 7788 23-MAY-87 1100 2 7934 MILLER CLERK 7782 23-JAN-82 1300 1 7938 赵元杰 软件 23-SEP-01 12345 54321 2 7939 赵元杰 软件 23-SEP-01 12345 54321 2 14 rows selected. SQL> select * from emp_lst; EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTN ---------- ---------- --------- ---------- --------- ---------- ---------- --------- 7788 SCOTT ANALYST 7566 19-APR-87 3000 2 SQL> 上面结果显示,由于本用户的名字是 scott,所以只显示 ename=scott 的记录。 §8.2.4 使用 COPY 功能 如果我们用 CREATE TABLE xxx AS select * from tablename@remote_connect; 不能完成 带 Long 等列的操作时,请你使用 Oracle 提供的 COPY 命令。COPY 可以实现在 CREATE TABLE 复制表时所不能实现的功能。 COPY 命令的语法如下: COPY { FROM username[/password]@database | TO username[/password]@database | FROM username[/password]@database TO username[/password]@database } { APPEND|CREATE|INSERT|REPLACE } destination_table[(col1,col2,...) ] USING query 参数说明: APPEND 如果目标表已存在,将查询的记录插入该表中, 如果目标表不存在,则创建再插入所查询的记录。 CREATE 先创建目标表再插入所查询的记录, 如果目标表不存在,则提示错误。 INSERT 将查询(必须用 using query 查)的记录插入到目标表中, 如果目标表不存在,则提示错误。 REPLACE 将查询的记录替换到目标表中的内容, 如果目标表存在,则先删旧表内容再用拷贝表替换, 196 如果目标表不存在,则创建表。 使用 copy 命令还需设置以下变量: SQL>set long n; /* 数据长度 */ SQL>set copycommit m;/* m 行提交一次 */ SQL>set arraysize n; /* 批操作的大小 */ 例: COPY from zhao/zhaoyuan@sun450 CREATE WORKER using select * from WORKER; §8.2.5 管理Oracle 名称服务器 要保证与远程进程连接,DBA 必须确保名称服务器配置的正确。另见 DBA 资料的“NET8 名称 服务器”章节。 §8.3 关于上下文的使用 在 Oracle 系统中,可 以 支持对文本进行处理。要 想对文 本进行搜索,则需要对数据库环境进 行设置。 §8.3.1 设置上下文选项 为了在数据库中使用上下文功能,先要设置上下文选项。用以启动数据库上下文处理进 程。可以用 CTXCTL 实用程序来启动上下文服务器: $CTXCTL … … >help The follwing commands are available: Help[command] -- 命令信息 Status -- 正在运行的服务器情况 Start n [line |query | ddl | dml ] … --启动 n 服务进程 Stop pid… | all --停止 ctxctl 197 Quit -- 结束 ctxctl Exit --结束 ctxctl 为了支持文本搜索,用户至少启动一个 query 上下文服务器。到底启动多少个服务器,要根 据用户的要求决定。比如: start 1 ddl dml query start 1 query 服务器的当前情况可以从 CTS_ALL_SERVERS数据字典来查询,如: SQL>col ser_name for a30 Select ser_name,ser_status,set_started_at from CTX-ALL_SERVERS; 从结果可看出已经启动的服务器,DBA 可以在 SQL>下用下面命令来停止服务的运行: SQL>exec CTX_ADM.SHUTDOWN; 1.在 init.ora 参数文件中设置启动参数: 要使上下文有效,必须在 Init.ora 文件中设置下面参数: text_enable= TRUE 也可以在 SQL>下进行设置: ALTER SESSION set text_enable = TRUE; 2.必要的角色: 在 Oracle 数据库中,上下文的数据字典属于 CTXSYS 用户所有。所以 CTXSYS 是唯一具有 CTXADMIN 角色的用户。此外,还有 CTXAPP(应用程序所有)和 CTXUSER(应用程序用户) 角色。一般需要将 CTXAPP 授予开发上下文的用户。如: grant CTXAPP to scott; §8.3.2 为上下文查询设置表 为了实现上下文的查询,需要在基表的某列建立主关键字和为表中的文本列设置相应的查询 策略。比如有下面的求职表: 1.基本的设置: 198 1)创建基本表: CREATE TABLE prospect ( name varchar2(20), Address varchar2(40), Resume long ) tablespace user_data storage(initial 5m next 1m pctincrease 0); 2)为 prospect 表建立一个主关键字: ALTER table prospect add constraint prospect_pk primary key ( name ); 3)为 prospect 表建立定义策略: 为了在 prospect 表上进行上下文的查询,需要用 Oracle 提供的 CREATE_POLICY 过程来创 建一个策略。CREATE_POLICY 过程需要两个参数:策略名称 和 被索引列的名称。如: exec CTX_DDL.CREATE_POLICY(‘prospect’,’ prospect.resome’); 2.显示和修改选项: 可以从 CTX_PREFERENCE_USAGE 数据字典视图中查出有关当前已经建立的策略信息。 1)显示策略信息: 例 1.查询数据字典视图中的 PROSPECT 策略的信息: SELECT PRE_NAME from CTX_PREFERENCE_USAGE Where pol_name=’ PROSPECT’; 2)修改策略信息: 可以通过执行 CTX_DDL_UPDATE_POLICY 过程来对策略进行修改,如希望加 SOUNDEX 来对 prospect进行查询: EXEC CTX_DDL_UPDATE_POLICY( policy_name=>’ PROSPECT’, Worldist_pref=>’CTXSYS.SOUNDEX’); 3)删除策略信息: 可以通过执行 CTX_DDL_DROP_ POLICY 过程来实现删除某个策略。如: EXEC CTX_DDL_DROP_POLICY( ’ PROSPECT’ ); 3.建立文本索引: 199 要实现对文本的查询,除了设置参数外,还要用 CTX_DDL 包中 CREATE_INDEX 过程为表 建立文本索引。要建立文本索引,要求具有 CTXAPP 角色。 1)建立文本索引: EXEC CTX_DDL.CREATE_INDEX(‘prospect’); 如果出现错误,可能还没有启动 DDL 服务器,则要用 CTXCTL 来启动上下文服务器,在运 行上面的建立索引命令。 2)生成数据库对象: 当创建文本索引完成后,系统就数据库中建立一些表,这些表存放支持策略的信息。可以从 CTX_USER_POLICY数据字典中查到各个表及其策略。要 查 询 策略信息,还需要与 user_tables 和 user_indexes数据字典进行相关查询。 3)删除文本索引: 当不能修改文本策略索引或不再需要时,可以通过 CTX_DDL.DROP_INDEX 过程来删除文 本索引。 例。删除一个索引: EXEC CTX_DDL.DROP_INDEX(‘prospect’); 再查看数据字典的信息: select pol_status from CTX_USER_POLICIES where pol_name=’PROSPECT’; §8.3.3 优化文本索引 在 CTX_DDL 包中提供了一个 OPTIMIZE_INDEX 过 程 来 重 建 所有的文本索引。 OPTIMIZE_INDEX 过程可以对压缩索引中的碎片,并且去掉或删除文本数据项中的引用和 其他相关的数据项。OPTIMIZE_INDEX 过程的用法如下: EXEC CTX_DDL .OPTIMIZE_INDEX(‘prospect’); §8.4 关于维数(DIMENSION) Oracle8i提供一种新功能叫维(DIMENSION),用于在一对列之间定义一个“父-子”关系,这 些列的全部列必须来自同一个表。但是,对于一个列(或层)可以来自不同的表。优化器可 以在实体化视图中利用这种“父-子”关系来进行查询改写。 要建立维,你必须有CREATE DIMENSION 系统权限。如果你要在其他的模式下建立维,则需要 200 具有 CREATE ANY DIMENSION 系统权限。 注意,在建立完成维后,Oracle系统会自动有效这些维,如果希望对建立的维有效,则需要 指定hierarchy_clause和join_clause, 你必须用DBMS_OLAP.validate_dimension 存储过程。 §8.4.1 CREATE DIMENSION 语法 创建维的语法如下: CREATE DIMENSION [schema.] dimension LEVEL level IS ( level_table.level_column ) { HIERARCHY hierarchy ( child_level CHILD OF parent_level JOIN KEY (child_key_column) REFERENCES parent_level ) | ATTRIBUTE level DEFERENCES ( dependent_column ) } schema 模式名字,如果没有指定模式名,则Oracle将你的用户名作为模式名。 dimension 维的名字,在模式下的维名字必须唯一。 level_clause level_clause定义维的级,一个级定义一个层和属性 level 层的名字 level_table.level_column 级的列名,最多32级。有下面限制: l 在级中的所有列必须来自同一个表; l 不同级的列可以来自不同的表,但是必须指定join_clause; l 所指定的一组列在该级中必须是唯一的; l 所指定的列不能在另外的地方指定; l 每个level_column必须是非空的(不是原来意义上的NOT NULL)。 hierarchy_clause 层在维数中定义一个线性的层,每个层概括一个父-子关系的链。在 维 中的层与其他层有关系, 它们可以有一些列。 hierarchy 指定相同的级,这些级在维中必须是唯一的。 child_level 指定级中的名字。 join_clause join_clause 可以为一个包括多个表的维指定一个内部的等价连接。 201 attribute_clause attribute_clause可 以 指定唯一确定的列。在level 中的列必须来自同一个 dependent_columns所指的表。在level_clause 中,dependent_columns不需指定。 例如,层次级为:city、state和 country,则city是可以作为市长(mayor),而state 可以确定为 州长(governor),而country确定为总统(president)。 §8.4.2 创建维的例子 下面例子在time_tab表中创建一个维 time 和在CITY、STATE、COUNTRY表中创建维geog CREATE DIMENSION time LEVEL curDate IS time_tab.curDate LEVEL month IS time_tab.month LEVEL qtr IS time_tab.qtr LEVEL year IS time_tab.year LEVEL fiscal_week IS time_tab.fiscal_week LEVEL fiscal_qtr IS time_tab.fiscal_qtr LEVEL fiscal_year IS time_tab.fiscal_year HIERARCHY month_rollup ( curDate CHILD OF month CHILD OF qtr CHILD OF year) HIERARCHY fiscal_year_rollup ( curDate CHILD OF fiscal_week CHILD OF fiscal_qtr CHILD OF fiscal_year ) ATTRIBUTE curDate DETERMINES (holiday, dayOfWeek) ATTRIBUTE month DETERMINES (yr_ago_month, qtr_ago_month) ATTRIBUTE fiscal_qtr DETERMINES yr_ago_qtr ATTRIBUTE year DETERMINES yr_ago ; CREATE DIMENSION geog LEVEL cityID IS (city.city, city.state) LEVEL stateID IS state.state LEVEL countryID IS country.country HIERARCHY political_rollup ( 202 cityID CHILD OF stateID CHILD OF countryID JOIN KEY city.state REFERENCES stateID JOIN KEY state.country REFERENCES countryID); 203 第九章 安全管理 在建立应用系统的各种对象(包括表、视图、索引等)前,就得先确定各个对象与用户 的关系。也就是说,哪些用户需要建立,哪些用户都充当什么样的角色,他们应该有多大权 限等。下面介绍基本的安全管理方面的内容,更详细的内容在 DBA 资料里介绍。 §9.1 CREATE USER 命令 CREATE USER username IDENTIFIED BY password Or IDENTIFIED EXETERNALLY Or IDENTIFIED GLOBALLY AS ‘CN=user ’ [DEAFULT TABLESPACE tablespace ] [TEMPORARY TABLESPACE tablespace] [QUOTA [integer K[M]][UNLIMITED] ON tablespace [,QUOTA [integer K[M]][UNLIMITED] ON tablespace [PROFILES profile_name] [PASSWORD EXPIRE] [ACCOUNT LOCK or ACCOUNT UNLOCK] CREATE USER username 用户名 IDENTIFIED BY password 用户口令 IDENTIFIED BY EXETERNALLY 用户名在操作系统下验证,这个用户名必须与操作 系统中所 定义的用户相同。 IDENTIFIED GLOBALLY AS ‘CN=user’ 用户名是 ORACLE 安全域中心服务器来验证 ,CN 名字标识用户的外部名。 [DEAFULT TABLESPACE tablespace ] 缺省的表空间 [TEMPORARY TABLESPACE tablespace] 缺省的临时表空间 [QUOTA [integer K[M]][UNLIMITED] ON tablespace 允许使用 k[m]字节 [,QUOTA [integer K[M]][UNLIMITED] ON tablespace [PROFILES profile_name] 资源文件的名字 [PASSWORD EXPIRE] 立即将口令设成过期状态,用户在登录进入前必须 修改口令。 [ACCOUNT LOCK or ACCOUNT UNLOCK] 用户不被加锁。 204 §9.2 建立用户 建立用户虽然不是经常的工作,但却是比不可少的工作。如果你的环境是一个较复杂的 应用系统,你还是应该重视用户的建立和管理的事。下面是建立不同类型用户的方法。 §9.2.1 外部验证(Authenticated )用户 外部识别的 Oracle 用户可以被客户端的操作系统验证,即在 Oracle 外放置了用于口令 管理和用户验证的控制。此类登录不再需要 Oracle 口令。操作系统验证的实现需要进行下面 步骤: 1. 在 INITsid.ORA 文件中设置 OS_AUTHENT_PREFIX 参数,在 Oracle6 里必须设置用户 的前缀为 OPS$。Oracle8 可以不需要前缀 OPS$。如在 INITsid.ORA 文件上加: . . . OS_AUTHENT_PREFIX=”OPS$” . . . 2. 用 CREATE USER 建立外部用户: CREATE USER ops$zhao IDENTIFIED BY EXTERNALLY; 如果在 INITsid.ORA 文件的 OS_AUTHENT_PREFIX=””(即没有设置为 OPS$),则: CREATE USER zhao IDENTIFIED BY EXTERNALLY; CREATE USER ops$zhaoyj IDENTIFIED BY EXTERNALLY DEFAULT TABLESPACE users TEMPORARY TABLESPACE temp QUOTS UNLIMITED ON users QUOTS UNLIMITED ON temp; §9.2.2 全局(Globally)验证用户-企业验证 在 Oracle 数据库里,可以将用户配置成不需要验证口令的方式,用 以 替 代 来自 X.509 企业 目录服务的口令检查。这种类型的用户一般都是在大的企业里的登录使用。一般企业验证启 用 Oracle 安全服务(OSS)来实现单独的注册。建立全局验证的用户需要带 GLOABLLY AS 。如: 205 CREATE USER SCOTT IDENTIFIED GLOABLLY AS ‘CN=scott, OU=division1, O=sybex, C=US’; §9.3 ALTER USER 命令 ALTER USER 命令用于修改用户的资源限制和口令等。ALTER USER 命令语法如下: ALTER USER username IDENTIFIED BY password Or IDENTIFIED EXETERNALLY Or IDENTIFIED GLOBALLY AS ‘CN=user’ [DEAFULT TABLESPACE tablespace ] [TEMPORARY TABLESPACE tablespace] [QUOTA [integer K[M]][UNLIMITED] ON tablespace [,QUOTA [integer K[M]][UNLIMITED] ON tablespace [PROFILES profile_name] [PASSWORD EXPIRE] [ACCOUNT LOCK or ACCOUNT UNLOCK] [DEFAULT ROLE role[,role] or [DEFAULT ROLE ALL [EXEPT role[,role]]]or[DEFAULT ROLE NOTE] 例:比如用户使用的资源超出限额的话,就如下提示: ORA-01536:SPACE QUOTA EXCEEDED FOR TABLESPACE ‘USERS’ 这时需要对该用户增加资源限额: SQLPLUS SYSTEM/MANAGER SQL>ALTER USER sideny QUOTA 10M ON SYSTEM; §9.4 DROP USER 命令 对于不再需要的用户,可以用 DROP USER 来将不要的用户从数据库系统中删除。以释放出磁 盘空间。DROP USER 语句的语法如下: DROP USER user [CASCADE] 如果加 CASCADE 则连同用户的 对象一起删除。 SQL>drop user zhao cascade; 提示:不要轻易使用 DROP USER 命令。只有在确认某个用户没有保留时才使用该命令。 206 §9.5 GRANT 命令与 REVOKE 命令 Oracle 提供两个命令(grant 和 revoke)用于给用户(或角色)进行授权和从用户(或角色)中 收回某些权限。GRANT 可以给用户(或角色)授予对象的权限和系统权限。 §9.5.1 GRANT 命令 可以使用 GRANT 语句将权限或角色授予某个用户或角色。GRANT 的语法如下: GRANT system_privilege | role TO user | role | PUBLIC [WITH ADMIN OPTION] GRANT object_privilege | ALL column ON schema.object FROM user | role | PUBLIC WITH GRANT OPTION system_privilege: 系统权限或角色 role: 角色 user: 被授予的用户或角色 object_privilege:对象的权限,可以是: l ALTER l DELETE l EXECUTE l INDEX l INSERT l REFERENCES l SELECT l UPDATE 例子: SQL GRANT CREATE TABLE TO gavaskar; GRANT team_leader TO crystal; GRANT INSERT, UPDATE ON sales TO larry WITH GRANT OPTION; GRANT ALL TO PUBLIC;. §9.5.2 REVOKE 命令 可以使用 REVOKE 语句从用户或角色中撤消某些权限。REVOKE 的语法如下: 207 REVOKE system_privilege | role FROM user | role | PUBLIC REVOKE system_privilege | role FROM user | role | PUBLIC REVOKE object_privilege | ALL ON schema.object FROM user | role | PUBLIC CASCADE CONSTRAINTS system_privilege: 系统权限或角色 object_privilege:对象的权限,可以是: l ALTER l DELETE l EXECUTE l INDEX l INSERT l REFERENCES l SELECT l UPDATE 例: REVOKE ALTER TABLESPACE FROM john; REVOKE GRANT ANY ROLE FROM todd; REVOKE manager FROM imran; REVOKE INSERT ON sales FROM javed; REVOKE ALL ON marketing FROM terry;. §9.6 权限和角色 为了管理复杂系统的不同用户,Oracle 系统提供了角色和权限。权限可以使用户能访问 对象或执行程序。而角色是一组权限的集合,同样,角色被授予用户后,用户也具有某些权 限。Oracle 有三种类型的权限: l 对象权限(Object) l 系统权限(System) l 角色(Role) §9.6.1 建立角色 角色是一组权限的集合。角色包含一个或多个权限;角色可以再包含角色。关于角色的 详细描述参考另外的《Oracle8i 初级数据库管理》--赵元杰著。 1.建立角色的命令语法如下: 208 CREATE ROLE role_name [ NOT INDENTIFIED | [ INDENTIFIED [BY password | EXTERNALLY|GLOABALLY] ] ]; role 指定角色名; NOT IDENTIFIED 不需口令有数据库验证; IDENTIFIED 需要口令,分别为三种情况: l BY password 指定本地用户口令,如果在建立角色时用口令,则用户在使用时也 要给出口令。 l EXTERNALLY 指定为外部用户,该用户用外部服务进行验证。 CREATE ROLE role NOT IDENTIFIED IDENTIFIED BY password EXTERNALLY GLOBALLY; 例: CREATE ROLE vendor IDENTIFIED GLOBALLY; 2.三种标准角色: 自从Oracle6版本以后,Oracle系统一直有三种缺省的角色,即: l CONNECT ( 连接角色) 具有CONNECT 角色用户,可以进行 SELECT ,INSERT,UPDATE和DELETE操作。 l RESOURCE (资源角色) 具有RESOURCE角色的用户可以进行CONNECT所做的工作,此外,还可以进行CREATE TABLE、CREATE SEQUENCE、CREATE PROCEDURE、CREATE TRIGGER、CREATE INDEX 及CREATE CLUSTER等。 l DBA(数据库管理员角色) 具有DBA角色的用户可以进行除 RESOURCE外,还可以进行数据库的管理操作。 §9.6.2 给角色授权 一旦创建完角色,用户就可以给角色授权。给 角色授权的GRANT语句在前面介绍。通过 GRANT语句可以对角色授各种权限,如用户对象的访问权,系统权限等。如果用户具有DBA 209 权限的话,则用户有GRANT ANY PRIVILEGE系统权限。可以对角色授予各种权限。如: GRANT CREATE SESSION TO clerk; GRANT CREATE SESSION,CREATE Database link to mamager; §9.6.3 授权角色给用户 如果角色创建完毕并且已经给角色授了相应的权限,用户就可以将角色授权给用户了。 这样的操作完成后,被授角色的用户就有了相应的权限。要完成这样的操作,只要操作者具 有GRANT ANY PRIVILEGE系统权限就可通过GRANT语句对用户授各种权限。如: 例。假设clerk 是一个角色,则可以将它授予用户: GRANT clerk TO ZHAO; §9.7 有关的数据字典 无论对数据库管理员或是一般的用户,对 Oracle 有关数据字典的了解程度是衡量是否真 正掌握 Oracle 核心的关键。如果你了解基本的 Oracle 数据字典,对于各种系统的信息查询 将大有好处。下面给出与安全管理有关的数据字典简单介绍。 §9.7.1 与用户、角色与权限有关的数据字典 与用户、角色、权限有关的数据字典主要有: DBA_USERS 实例中有效的用户及相应信息。 V$SESSION 实例中会话的信息。 DBA_ROLES 实例中已经创建的角色的信息。 ROLE_TAB_PRIVS 授予角色的对象权限。 ROLE_ROLE_PRIVS 授予另一角色的角色。 ROLE_SYS_PRIVS 授予角色的系统权限。 DBA_ROLE_PRIVS 授予用户和角色的角色。 SESSION_ROLES 用户可用的角色的信息。 §9.7.2 查询数据字典信息 对于一般的软件人员来说,应该掌握对数据字典的基本查询,如: 例 1。查看当前已经创建了多少用户和用户缺省的表空间: 210 SQL> set line 120 SQL> col username for a26 SQL> col default_tablespace for a20 SQL> select username,DEFAULT_TABLESPACE,created from dba_users; USERNAME DEFAULT_TABLESPACE CREATED -------------------------- -------------------- ---------- SYS SYSTEM 05-12 月-01 SYSTEM TOOLS 05-12 月-01 OUTLN SYSTEM 05-12 月-01 DBSNMP SYSTEM 05-12 月-01 AURORA$JIS$UTILITY$ SYSTEM 05-12月-01 OSE$HTTP$ADMIN SYSTEM 05-12月-01 AURORA$ORB$UNAUTHENTICATED SYSTEM 05-12月-01 ORDSYS SYSTEM 05-12 月-01 ORDPLUGINS SYSTEM 05-12 月-01 MDSYS SYSTEM 05-12 月-01 ZHAO USERS 07-12 月-01 SCOTT USERS 08-2月 -02 已选择 12 行。 例 2。查看当前已经创建了多少角色: SQL> select * from dba_roles; ROLE PASSWORD ------------------------------ -------- CONNECT NO RESOURCE NO DBA NO SELECT_CATALOG_ROLE NO EXECUTE_CATALOG_ROLE NO DELETE_CATALOG_ROLE NO EXP_FULL_DATABASE NO IMP_FULL_DATABASE NO RECOVERY_CATALOG_OWNER NO AQ_ADMINISTRATOR_ROLE NO AQ_USER_ROLE NO ROLE PASSWORD ------------------------------ -------- SNMPAGENT NO 211 OEM_MONITOR NO HS_ADMIN_ROLE NO JAVAUSERPRIV NO JAVAIDPRIV NO JAVASYSPRIV NO JAVADEBUGPRIV NO JAVA_ADMIN NO JAVA_DEPLOY NO TIMESERIES_DEVELOPER NO TIMESERIES_DBA NO 已选择 22 行。 SQL> 212 第十章 其它一些常见问题及技巧 下面给出一些对于初学者来是常见问题的一点描述,目的是使那些使用 Oracle 系统时间不长 的人员能尽快适应在 Oracle 环境下的开发。 §10.1 一些常见问题 下面是一些初学者常遇到的问题的解释。如果你是一位 Oracle 的老手可以不阅读本章的 内容。 §10.1.1 Oracle 与 2000 年问题 l oracle 约定 l oracle 在系统中一直用 YYYY:MM:DD HH24:MI:SS 表示日期和时间 l ORACLE7 server 和 ORACLE8 server 提供一种年格式掩码 RR 规则转换如下表: 当前年度(最后两位数) 指定的两位数年 (机器设置为) RR 返回的年 0~49 0~49 50~99 0~49 0~49 50~99 50~99 50~99 当前世纪(19XX) 下个世纪(20XX) 上个世纪(18XX) 当前世纪(19XX) l 当前年是在 50~99 后半世纪 1)如果输入 00 和 99 之间,oracle 将被记为下个世纪,如在 1996 年输 02,则被记为 2002 年。 2)如果输入 50 和 99 之间,oracle 将被记为当前世纪,如在 1996 年输 97,则被记为 1997 年。 l 当前年是在 00~49 前半世纪 1)如果输入 00 和 49 之间,oracle 将被记为当前世纪,如在 2001 年时输 02,则被记为 2002 年。 213 2)如果输入的两位年在 50 和 99 之间,oracle 将被记为上个世纪,如在 2001 年输 97,则被 记为 1997 年。 l 例子 Create table abc(datefld date) Insert into abc Value('01-JAN-11'); Insert into abc Value('01-JAN-90'); 转换成 1911 年和 1990 年 Update abc Set Datefld(d=To_date(To_datefld,'DD-MON-YY HH24:MI:SS'), 'DD_MON_RR HH24:MI:SS'); Select To_char(Datefld,'DD-MON-YYYY') Datefld from abc; 01-JAN-2011 01-JAN-1990 建议:2000 年问题在开发中的建议任何时应采用 4 位年表示如果用两位一定用 YY 或 RR 表示 输入界面最好作判断和提示。 §10.1.2 如何正确插入日期数据 许多初学者都可能遇到这样的问题,就是往 DATE 类型的列插入日期数据时,经常被提 示错误。 比如有下面的 ABC 表结构: SQL> desc abc 名称 空? 类型 ----------------------------------------- -------- ------------ RQ DATE NAME VARCHAR2(20) 当用下面命令插入数据到 ABC 表时,系统提示如下信息: SQL> insert into abc values('02-JAN-2002','赵元杰'); insert into abc values('02-JAN-2002','赵元杰') * ERROR 位于第 1 行: ORA-01843: 无效的月份 这是由于系统安装时的默认字符集引起的。虽然上面语句看上去没有错误,但是它不符合当 214 前系统的日期格式要求。那么当前系统的日期格式是什么呢?我们可以用下面语句来查询: SQL> select sysdate from dual; SYSDATE ---------- 01-2 月 -02 既然系统的日期格式是中文的月份,则将上面语句改为中文的月即可: SQL> insert into abc values('02-2 月-2002','赵元杰'); 已创建 1 行。 当然,你可以用 alter session 命令修改当前系统的日期格式为你喜欢的格式,如: SQL> alter session set nls_date_format='yyyy/mm/dd'; 会话已更改。 SQL> insert into abc values('2002/02/02','赵元杰'); 已创建 1 行。 SQL> select * from abc; RQ NAME ---------- -------------------- 2002/02/02 赵元杰 2002/02/02 赵元杰 关于日期格式的有关资料,请参见《Oracle8I 数据库管理员》--赵元杰著 §10.1.3 在查询中只返回满足条件的部分记录 有时,我们关心的查询结果不是所有的记录,而是关心所查询的内容的存在性。如果 我们不加特别的限制,满足条件的所有记录会源源不断地显示在屏幕上。为了只显示少量的 内容,oracle 提供 rownum 伪列来限制在查询时返回的记录数。例如: Select * from dict where rownum < 10 Rownum 是要显示的记录数 215 注意: l 该用法在 PL/SQL 和 Pro*C 中常常不能用 ; l 在条件中可以用 <= ,但不能用 = 或 > 作判断。 §10.1.4 快速大量删除数据 Truncate 在数据库管理操作中,经常需要将某个表的所有记录都删除而只保留表结构,这样的要求如 果用 delete 进行删除的话,Oracle 系统会自动为该操作分配回滚段。如果回滚段较小,则 可能导致操作失败。即使回滚段足够大,删除操作也需要较长的时间才能完成。为了加快删 除操作,Oracle 提供了一个特别的命令 TRUNCATE,可 以 快速地完成对某个表的所有记录的删 除。TRUNCATE 的语法如下: TRUNCATE [TABLE | CLUSTER] schema.[table][cluster] [DROP | REUSE STORAGE] 删除表中或簇中的所有行,REUSE STORAGE 保留被删除的空间作为该表的新行使用:缺省 为 DROP storge 即收回被删除的空间给系统。 特点:不可恢复。即不需 rollback segment, 不在日志文件中记录信息。 §10.1.5 Rowid 的使用 l oracle 为每个表的每一条记录赋予一个唯一的标识号 rowid; l 它是一个伪列,虽然在定义表结构时并不声明它,但它自动地建立; l 用 desc 查看表结构时并不显示该字段; l ROWID 在进行 UPDATE 或 DELETE 操作中速度最快; l Oracle7 和 Oracle8 的 ROWID 不同。 SQL>select name,sex,sal,rowid from emp; SQL>delete from emp where rowid='...XXXX.XX.XXXX'; l Oracle7 的 Rowid 由三个部分组成,结构为: block.row.file 格式为: BBBBBBBB.RRRR.FFFF BBBBBBBB 是文件的块号;RRRR 块中的行号;FFFF 是文件的绝对号。 例 0000000F.0000.00002 第 15 数据块.第 1 行.第二个数据文件 216 l Oracle8 和 Oracle8i/9i 的 Rowid 由四个部分组成,结构为: OOOOOOFFFBBBBBBRRR 格式为: l OOOOOO 代表数据对象号,它表示数据库段的编号; l FFF 代表在表空间中的相对文件号; l BBBBBB 代表在一个文件中的块号,块号与数据文件有关,与表空间无关; l RRR 代表块中行的位置号。 例 1:查询记录中的 ROWID 列的值: SQL> select * from emp; ENAME SAL DEPTNO TEL -------------------- ---------- ---------- ------------- 赵元杰 9999.12 10 1360 136 5681 赵元杰 9999.12 10 1360 136 5681 例 2:使用 ROWID 删除重复的记录。由于记录每个列的值完全一样,where 条件无法辨别, 但是两条记录的 ROWID 号是不一样的。所以可以用 ROWID 作为条件。详细操作如下: 1)先查出记录: SQL> select ename,sal,deptno,tel,rowid from emp; ENAME SAL DEPTNO TEL ROWID ------------ ---------- ---------- -------------------- ------------------ 赵元杰 9999.12 10 1360 136 5681 AAAFyUAADAAAAADAAA 赵元杰 9999.12 10 1360 136 5681 AAAFyUAADAAAAADAAB 2)看到两条记录的 rowid 不一样,可以使用 chartorowid 函数和 rowid 值完成删除操作: SQL> delete from emp where rowid = chartorowid('AAAFyUAADAAAAADAAB'); 已删除 1 行。 3)删除操作完成,再查看 emp 表的数据: SQL> select ename,sal,deptno,tel,rowid from emp; 217 ENAME SAL DEPTNO TEL ROWID ------------ ---------- ---------- -------------------- ------------------ 赵元杰 9999.12 10 1360 136 5681 AAAFyUAADAAAAADAAA 从例子中可以看出,rowid 的优势,建议在 PL/SQL 中的循环操作使用 ROWID 来提高处理速度。 §10.1.6 在查询中不让记录被更新 要保证在统计(查询)执行过程中,记录不被其他用户更新,则可以使用 For update 子句进行加锁。这样在这个锁释放前其他用户不能对这些记录作 update、delete 和加锁。 SQL>Select daptno from dept Where deptno=25 For update; 如果你使用了 FOR UPDATE 来对表进行加锁,组必须用 commit 来释放加锁的记录。 §10.1.7 EXCEPTIONS(违反完整性)问题 前面介绍的主键的创建方法,如果我们对表创建了主键后,那么在查入记录时,Oracle 会自动对插入数据进行唯一性检查,当出现有数据违反唯一性限定的情况时,一般用户可能 只看到 ORA-0001 Dup_val_on_index ( 试图破坏一个唯一性限制 ) 类似的提示,而没有看 是哪条记录违反唯一性限定。为了使用户有针对性地修改违反唯一性限定的记录,Oracle 提 供了一种方法可以容许用户捕获那些导致限定产生失败的行的信息。方法是: l 用户生成一个列为 EXCEPTION 的表,创建该表的脚本是 UTLEXCPT.SQL ,你可以从 oracle.../rdbms/admin 目录中找。如: SQL> start c:\oracle\ora81\rdbms\admin\utlexcpt 表已创建。 l 在建表时声明 EXCEPTIONS。 l 激活 EXCEPTIONS,如: Alter table newspaper enable primary key Exceptions into EXCEPTIONS; EXCEPTIONS 表有四个列: Row_ID 违反限定的各行 Ower 违反限定的拥有者 218 Table_name 违反限定所在的表 Constraint 行所在的限定 l 查看违反完整性的记录: Select * form Newspaper Where Rowid in (select Row_id from EXCEPTIONS); 注:可能原版资料上将例外的表拼写成为 except_table ,其实脚本并不是这样。下面是原 版资料的例子: ALTER TABLE emp ENABLE VALIDATE CONSTRAINT fk_deptno EXCEPTIONS INTO except_table; SELECT emp.* FROM emp e, except_table ex WHERE e.row_id = ex.row_id AND ex.table_name = ’EMP’ AND ex.constraint = ’FK_DEPTNO’; §10.1.8 Not in 和 Not Exists 一般来说,在处理存在性检查中,用户都会看到 Not in 和 Not Exists 两个判断语句, 但是它们在处理速度上有些不同。 Not in 速度慢 Not Exists 速度较快。 SQL>select name,depart,zip From export Where name not in (select name from xxx not exists Item_application where …) and rownum<6 Order by score; §10.1.9 关于 COPY 命令 可以弥补 create table ... as select ... from ...的和 imp,exp 的不足,主要功能有: 1) 从一个本地数据库将一个或多个表拷贝到一个远程数据库; 2) 将一个表的一些记录拷贝到远程或本地库的其它表中; 3) 将包含 long 类型的表的一些列拷贝到其他表中; 4) 从一个 oracle 数据库向一个非 oracle 数据库的拷贝表。 219 语法如下: COPY { FROM username[/password]@database | TO username[/password]@database | FROM username[/password]@database TO username[/password]@database } { APPEND|CREATE|INSERT|REPLACE } destination_table[(col1,col2,...) ] USING query 参数说明: APPEND 如果目标表已存在,将查询的记录插入该表中, 如果目标表不存在,则创建再插入所查询的记录。 CREATE 先创建目标表再插入所查询的记录, 如果目标表不存在,则提示错误。 INSERT 将查询(必须用 using query 查)的记录插入到目标表中, 如果目标表不存在,则提示错误。 REPLACE 将查询的记录替换到目标表中的内容, 如果目标表存在,则先删旧表内容再用拷贝表替换, 如果目标表不存在,则创建表。 使用 copy 命令还需设置以下变量: SQL>set long n; /* 数据长度 */ SQL>set copycommit m;/* m 行提交一次 */ SQL>set arraysize n; /* 批操作的大小 */ §10.1.10 列值为NULL 情形的处理 对于编程人员来说,如果对列的空值(NULL)不注意而使处理结果不正确的情况还比 较多。这主要是由于数学上的问题引起的,数学的数字运算是:null + 数字 = null 。这样 的法则使我们在处理表中的列的值为空时会出现不正确的结果。请看下面操作: 例子:假设 EMP 表有下面的记录: SQL> select * from emp; ENAME SAL DEPTNO TEL COMM ------------ ---------- ---------- -------------------- ---------- 赵元杰 9000 10 1360 136 5681 1000 张三 8898 10 123456 1200 李四 7000 10 654321 从查询结果来看,李四的 comm(奖金)没有值。当我们将 sal+comm(工资+奖金)来列出结果时, 则看到下面的结果: 220 SQL> select ename,sal,comm,sal+comm from emp; ENAME SAL COMM SAL+COMM ------------ ---------- ---------- ---------- 赵元杰 9000 1000 10000 张三 8888 1200 10088 李四 7000 由于李四没有奖金(comm 列值为空),所以“工资”加“奖金”也变为“空”了。 对于这样的情形,请你务必记住使用 NVL 函数来解决。NVL 函数的格式为: NVL ( value, substitute) 即 value 为空时以 substitute 代替,可以将上面语句改为下面语句就正确了: SQL> select ename,sal,comm,nvl(sal,0)+nvl(comm,0) from emp; ENAME SAL COMM NVL(SAL,0)+NVL(COMM,0) ------------ ---------- ---------- ---------------------- 赵元杰 9000 1000 10000 张三 8888 1200 10088 李四 7000 7000 §10.1.11 使用 product_user_file 来限制用户使用产品 缺 省 情况下,该表在 oracle rdbms 中是不建立的,需要时可以 system 帐户下运 行...\dbs\pupbld.sql 即可建立该表,product_user_file 表的结构如下: product 产品名,sql*plus userid 被禁止的用户(大写) attribute 被禁止的属性(具体命令) scope 用于非 oracle 产品,用 null 替换 numeric_value 用于非 oracle 产品, 用 null 替换 char_value 必需含'DISABLED' date_value 用于非 oracle 产品,用 null 替换 long_value 用于非 oracle 产品,用 null 替换 例 1:禁止 scott 用户使用 sql*plus ,则 insert into product_user_profile (product,userid,attribute,scope,numeric_value, char_value,date_value,long_value) values ('SQL*PLUS','SCOTT','HOST',NULL,NULL,'DISABLE',NULL,NULL); 221 例 2:重新让 scott 用户使用 sql*plus ,则 SQL>delete from product_user_profile Where userid='SCOTT' and attribute='HOST'; Attribute 可能的命令如下: COPY EDIT EXECUTE EXIT GET HOST QUIT PASSWORD RUN SAVE SET SPOOL START ALTER ANALYZE AUDIT CONNECT CREATE DELETE DROP GRANT INSERT LOCK NOAUDIT RENAME REVOKE SELECT SET ROLE SET TRANSACTION TRUNCATE UPDATE BEGIN DECLARE §10.2 常用技巧 下面给出开发人员在工作中经常遇到的问题的解决方法。这里的所有例子都经过作者的 222 精心调试通过。希望能对那些新手的读者有点帮助。 §10.2.1 long 类型的查询 由于在 SQLPLUS 下的缓冲区有限,并且 LONG 的缺省长度为 80 个字符。所 以 要 查 询 LONG 类型的字段时,需要设置 LONG 的值为一个合适的值。如: SQL>set long 3000 SQL>col text for a90 SQL>select text from user_source; §10.2.2 如何确定执行时间 在程序调试过程中,经常需要了解某个语句的执行时间。以选择较好的语句。用下面的设置 可以显示每个语句所用去的时间(毫秒,毫秒/1000=秒)。 SQL> set timing on SQL> select count(*) from emp; COUNT(*) -------------- 14 real: 190 SQL> 实际需要 190/1000=0.19 秒 §10.2.3 如何终止用户会话 有时由于系统资源紧张或需要进行系统的整理时,都希望将与系统处于连接的用户会 话进行终止。可以用下面命令分两步实现: 1)先查询出所有用户的信息: SQL> select sid,serial#,username,terminal from v$session; SID SERIAL# USERNAME TERMINAL --------- --------- ------------------------------ ---------------- 1 1 ZHAOYUANJIE 2 1 ZHAOYUANJIE 3 1 ZHAOYUANJIE 4 1 ZHAOYUANJIE 5 1 ZHAOYUANJIE 223 6 1 ZHAOYUANJIE 7 505 8 505 11 370 SYS ZHAOYUANJIE 9 rows selected. real: 190 SQL> 2)用 ALTER system kill session ‘sid,serial#’ ; 来终止: SQL>Alter system kill session ’11,370’; 如果希望一次终止多个会话,可以采用变量的方式更为快捷,如: SQL> select sid,serial#,username,terminal from v$session; SID SERIAL# USERNAME TERMINAL --------- --------- ------------------------------ ---------------- 1 1 ZHAOYUANJIE 2 1 ZHAOYUANJIE 3 1 ZHAOYUANJIE 4 1 ZHAOYUANJIE 5 1 ZHAOYUANJIE 6 1 ZHAOYUANJIE 7 833 8 833 11 370 SYS ZHAOYUANJIE 13 370 SCOTT ZHAOYUANJIE 10 rows selected. SQL> alter system kill session '&sid,&ser'; Enter value for sid: 13 Enter value for ser: 370 old 1: alter system kill session '&sid,&ser' new 1: alter system kill session '13,370' System altered. real: 100 224 §10.2.4 用TRANSLATE 对数据加密和解密 TRANSLATE 函数是一个变换函数,用它可以实现对存入表中数据进行加密和解密处理。函 数语法如下: REPLACE (‘string’ [,’string_in’,’string_out’]) String:希望被替换的字符串或变量。 String_in: 被替换字符串。 String_out: 要替换字符串。 例1: PL/SQL Var1:= REPLACE (‘Oracle’, ‘Or’, ‘Mir’,); SQL SELECT REPLACE (‘Oracle’, ‘Or’, ‘Mir’) “Example “ FROM DUAL; Example ------- Miracle 下面给出较复杂的例子,例 1 是一个 加密的存储过程,例 2 是用该过程进行加密的过程;例 3 是 密 的 过 程,例 4 是使用解密的过程: 例 1:加密过程可以写成如下: CREATE OR REPLACE FUNCTION ENCRYPT(INPASS IN VARCHAR2) RETURN VARCHAR2 AS STRING_IN VARCHAR(78); STRING_OUT VARCHAR2(39); OFFSET NUMBER(2); OUTPASS VARCHAR2(30); BEGIN OFFSET := TO_NUMBER(TO_CHAR(SYSDATE,’SS’))MOD 39; STRING_IN := ‘YN8K1JOZVURB3MDETS5GPL27AXWIHQ94C6F0#$_’; STRING_OUT :=’_$#ABCDEFGHIJKMNOPQRSTUVWXYZ0123456789’; OUTPASS := SUBSTR(STRING_IN,OFFSET,1); STRING_IN := STRING_IN||STRING_IN; STRING_IN := SUBSTR(STRING_IN,OFFSET,39); OUTPASS := OUTPASS||TRANSATE(UPPER(INPASS),STRING_IN,STRING_OUT); RETURN OUTPASS; END; 例 2:编写下面过程以调用 ENCRYPT 来加密: DECLARE 225 X VARCHAR2(40); BEGIN X := ENCRYPT(‘HELLO’); DBMS_OUTPUT.PUT_LINE(‘Encrypted:’|| X ); END; SQL>set serveroutput on SQL>/ Encrypted:#2PVV9 例 3:编写一个针对例 1 的加密函数程序: CREATE OR REPLACE FUNCTION DECRYPT(OUTPASS IN VARCHAR2) RETURN VARCHAR2 AS STRING-IN VARCHAR2(780; STRING_OUT VARCHAR2(39); OFFSET NUMBER(2); INPASS VARCHAR2(30); BEGIN STRING_IN :=‘YN8K1JOZVURB3MDETS5GPL27AXWIHQ94C6F0#$_’; STRING_OUT :=’_$#ABCDEFGHIJKMNOPQRSTUVWXYZ0123456789’; OFFSET := INSTR(STRING_IN,SUBSTR(OUTPASS,1,1)); STRING_IN := STRING_IN||STRING_IN; STRING-IN := SUBSTR(STRING_IN,OFFSET,39); INPASS := TRANSLATE(UPPER(SUBSTR(OUTPASS,2)),STRING_OUT,STRING_IN); RETURN INPASS; END; 例 4:编写一个调用解密的简单过程: DECLARE X VARCHAR2(30); BEGIN X := DECRYPT(‘#2PVV9’); DBMS_OUTPUT.PUT_LINE(X); END; §10.2.5 如何用查询来修改数据 有时需要用另外表的数据或本表的数据来修改某些记录。这 样 的应用在实际中经常使用。 以下例子具有代表性: 例 1:更新一个字段的情况: UPDATE DEPT SET DEPT_NAME=(SELECT DEPART_NAME FROM DEPART 226 WHERE DEPART.DEPTNO = DEPT.DEPTNO ); 例 2:更新多个字段的情况: UPDATE CHP8A SET (DEPT_NAME,MGR_ID)=(SELECT DEPART_NAME,MANAGER_ID FROM CHP8B WHERE CHP8B.DEPART_NUMBER=CHP8A.DEPT_NO AND ROWNUM=1) WHERE EXIST(SELECT ‘X’ FROM CHP8B where CHP8B.depart_number=CHP8a.dept_no); §10.2.6 如何产生创建用户的脚本 有时,我们需要在新的环境创建用户,这些用户来自一个已经存在的应用环境中。比如希望重 新创建用户的命令如何来产生。下面的例子从数据字典中查询数据自动完成创建用户、创建 角色、授权角色给用户操作。 accept uname prompt '输入希望的用户名: ' spool c:\gen_user SELECT username, 'CREATE USER '||username||' '|| DECODE(password, 'EXTERNAL', 'IDENTIFIED EXTERNALLY', 'IDENTIFIED BY '''||password||''' ') lne, 'DEFAULT TABLESPACE '||default_tablespace lne, 'TEMPORARY TABLESPACE '||temporary_tablespace||';' lne FROM DBA_USERS WHERE USERNAME LIKE UPPER('%&&uname%') OR UPPER('&&uname') IS NULL ORDER BY USERNAME; SELECT username, 'ALTER USER '||username||' QUOTA '|| DECODE(MAX_BYTES, -1, 'UNLIMITED', TO_CHAR(ROUND(MAX_BYTES/1024))||'K') ||' ON TABLESPACE '||tablespace_name||';' lne FROM DBA_TS_QUOTAS WHERE USERNAME LIKE UPPER('%&&uname%') OR UPPER('&&uname') IS NULL ORDER BY USERNAME; spool off 227 §10.2.7 如何产生创建表结构的脚本 可以通过查询 Oracle 的数据字典 USER_TABLES和 USER_TAB_COLUMNS来产生创建表的 脚本。这样的要求,其实主要是 decode 函数的使用。下面给出两个例子。 例 1.从 USER_TAB_COLUMNS 来产生创建表的脚本: /************************************************************/ /* 功能:自动产生创建表的脚本 */ /* 文件名:gen_cre_tab1.sql */ /* 作者:赵元杰 */ /* 日期:2001.12.10 */ /************************************************************/ set linesize 500 set pagesize 1000 set arraysize 8 set feedback off set heading off select decode(t1.column_id,1,'CREATE TABLE '||t1.table_name|| ' (', ' ') a, t1.column_name b, t1.data_type||decode(t1.data_type,'DATE', decode(t1.NULLABLE,'N',' not null'), 'VARCHAR2','('||to_char(t1.data_length)||')'|| decode(t1.NULLABLE,'N',' not null'), 'NUMBER',decode(t1.data_precision,null,‘ ‘ , '('||to_char(t1.data_precision)|| ','||to_char(t1.data_scale)||')' ) ||decode(t1.NULLABLE,'N',' not null'), 'CHAR','('||to_char(t1.data_length)||')'|| decode(t1.NULLABLE,'N',' not null'))|| decode(t1.column_id,max(t2.column_id),');',',') c FROM user_tab_columns t1,user_tab_columns t2 WHERE t1.table_name = t2.table_name and t1.table_name in (select distinct object_name from user_objects where object_type='TABLE') group by t1.column_id,t1.table_name,t1.data_type,t1.nullable, t1.data_length,t1.data_scale,t1.column_name, t1.data_precision order by t1.table_name,t1.column_id; 例 2.从 USER_TABLES 和 USER_TAB_COLUMNS 来产生创建表的脚本: 228 /************************************************************/ /* 功能:自动产生创建表的脚本和相应的存储参数 */ /* 文件名:gen_cre_tab2.sql */ /* 作者:赵元杰 */ /* 日期:2001.12.10 */ /************************************************************/ set linesize 500 set pagesize 1000 set arraysize 8 set feedback off set heading off select decode(t1.column_id,1,'CREATE TABLE '||t1.table_name|| ' (', ' ') a, t1.column_name b, t1.data_type||decode(t1.data_type,'DATE', decode(t1.NULLABLE,'N',' not null'), 'VARCHAR2','('||to_char(t1.data_length)||')'|| decode(t1.NULLABLE,'N',' not null'), 'NUMBER',decode(t1.data_precision,null,‘ ‘ , '('||to_char(t1.data_precision)|| ','||to_char(t1.data_scale)||')' ) ||decode(t1.NULLABLE,'N',' not null'), 'CHAR','('||to_char(t1.data_length)||')'|| decode(t1.NULLABLE,'N',' not null'))|| decode(t1.column_id,max(t2.column_id), ')'||chr(10)|| 'TABLESPACE ' ||t3.tablespace_name||chr(10)|| -- ‘ PCTFREE ‘||TO_CHAR(t3.pct_free)|| chr(10)|| -- ‘ PCTUSED ‘||TO_CHAR(t3.pct_used)|| chr(10)|| ‘ STORAGE( INITIAL ‘||TO_CHAR(t3.initial_extent)|| chr(10)|| ‘ NEXT ‘||TO_CHAR(t3.next_extent) ||’ );’ ||chr(10) , ',') c FROM user_tab_columns t1,user_tab_columns t2 ,user_tables t3 WHERE t1.table_name = t2.table_name and t2.table_name=t3.table_name and t1.table_name in (select distinct object_name from user_objects where object_type='TABLE') group by t1.column_id,t1.table_name,t1.data_type,t1.nullable, t1.data_length,t1.data_scale,t1.column_name, t1.data_precision, t3.tablespace_name , -- t3.pct_free , t3.pct_used, t3.initial_extent ,t3.next_extent order by t1.table_name,t1.column_id; 229 §10.2.8 如何产生创建视图的脚本 对于视图来说,所有的创建视图的数据来源都在 USER_VIEWS 数据字典。但是 USER_VIEWS 的 view_name 是视图的名称;而视图的查询文本存放在 text 列上。而且 text 列的类型是 long 类型。所以在查询前先要设置 long 类型为一个较大的值(因为 long 的缺 省值为 80 个字符),这样就可以查询完整的视图内容。 set linesize 150 set pagesize 1000 set arraysize 8 set feedback off set heading off set long 5000 col view_name for a20 col text for a80 select 'CREATE OR REPLACE VIEW '||VIEW_NAME||' AS ',TEXT FROM USER_VIEWS order BY VIEW_NAME; §10.2.9 如何产生创建序号的脚本 对于序号来说,所有的创建序号的数据都存放在 USER_SEQUENCES 数据字典。具体操 作如下: select 'CREATE SEQUENCE '|| SEQUENCE_NAME|| ' START WITH '||to_char(min_value)|| ' INCREMENT BY '||to_char(INCREMENT_BY)||':' FROM USER_SEQUENCES order BY SEQUENCE_NAME; §10.2.10 如何为用户创建公共同义词 同义词是 Oracle 用于管理用户对象的一种方法,它可以隐藏实际对象,但是不影响其他 经过授权的使用。下面是创建用户的表、视图、序列的简单办法。 1.假设下面脚本的文件名为 cre_syn.txt: accept uname prompt '输入希望的用户名: ' set echo off set heading off set feedback off spool c:\cre_syn.sql 230 select 'drop public synonym ' || table_name || ';' from all_tables where owner = upper('&&username') ; select 'create public synonym ' || table_name || ' for ' || upper('&&username') || '.' || table_name || ';' from all_tables where owner = upper('&&username') ; select 'drop public synonym ' || view_name || ';' from all_views where owner = upper('&&username') ; select 'create public synonym ' || view_name || ' for ' || upper('&&username') || '.' || view_name || ';' from all_views where owner = upper('&&username') ; select 'drop public synonym ' || SEQUENCE_NAME || ';' from ALL_SEQUENCES where SEQUENCE_OWNER = upper('&&username') ; select 'create public synonym ' || SEQUENCE_NAME || ' for ' || upper('&&username') || '.' || SEQUENCE_NAME || ';' from ALL_SEQUENCES where SEQUENCE_OWNER = upper('&&username') ; spool off 2. 运行时,只要输入用户名字即可,如: SQL> start c:\syn.txt 输入希望的用户名: zhao 原值 1: select 'drop public synonym ' || table_name || ';' from all_tables where owner 新值 1: select 'drop public synonym ' || table_name || ';' from all_tables where owner drop public synonym ABC; . . . . . . 3. 编辑产生创建脚本的 cre_syn.sql 文件,保留 drop synonyms 和 create public synonym 两 种语句,删除“原值 1: select”和“新值 1: select”. 231 第二部分 Oracle PL/SQL 基础 第十一章 PL/SQL 程序设计简介 在这部分用简短的篇幅描述一下 PL/SQL 程序设计的基本知识。由于本教材是针对初 学者,因而内容只涉及 PL/SQL 的基础部分。希望深入了解的读者请参考目前书店销售的 《Oracle8I PL/SQL 高级程序设计》和《PL/SQL User’s Guide and reference》。 §11.1 概述 早些的 Oracle5 以前是没有 PL/SQL 这个产品的。由于当时数据库与编程的接口基本上都 使用高级语言(简称 3GL),如 Fortran、COBOL 和 C/C++等。所以一般编程都是以高级语言 为主,将数据库作为辅助的存储数据的工具来使用数据库系统。后来由于数据库的发展和软 件技术的发展。出现了第 4 代开发工具,称为 4GL。4GL 虽然在编程方面功能强大,但在与 数据库接口上仍然采用 SQL 语句(现在 4GL 与数据库的通信仍以 SQL 语句来实现)。4GL 的功能是在处理界面上有优势,但在数据库的数据处理上仍不是它们的特长。鉴于数据库在 SQL 方面的优势,Oracle 公司在 Oracle6 版本以后开发了 PL/SQL 产品。起初它仅是一个辅 助的产品。用 它 也 只 是 弥 补 SQL 语句本身不进行过程编程的不足。但是后来由于数据库技术 的发展。有些应用业务处理要求进行大量的数据处理。比如银行的年终结息;商场的日结、 月结等。这类处理基本上不要求进行实时的人-机交互。而是只关心最后的结果。由于这类业 务的需求增长,许多数据库公司纷纷在自己的数据库引擎上增加了存储过程这样的功能。比 如 Sybase 的相应产品叫存储过程;IBM 也叫存储过程,但它不但可以将类似 PL/SQL 的程序 写进数据库系统中,此外也可以将 C 语言写的程序加进数据库中。处于这样的一种需求和时 髦的推动,Oracle 便在后来的版本中增强了 PL/SQL 的功能。包括现在的许多系统的处理几 乎是由 PL/SQL 写成,而不是用 C 来编写。这样的看法可以从目前的大量 PL/SQL 存储包和 Oracle9i 的 iAS 就可以看出来。 §11.2 SQL 与 PL/SQL 与其它的开发工具类似,在 Oracle 的 PL/SQL 工具中,可以使用标准 SQL 的部分子集。 §11.2.1 什么是 PL/SQL? 232 PL/SQL 是 Procedure Language & Structured Query Language 的缩写。Oracle 的 SQL 是支持 ANSI(American national Standards Institute)和 ISO92(International Standards Organization)标准的产品。PL/SQL是对 SQL 语言存储过程语言的扩展。从 Oracle6 以后,Oracle 的 RDBMS 附带了 PL/SQL。它现在已经成为一种过程处理语言,简称 PL/SQL(发音:pea ell sequel)。目前的 PL/SQL 包括两部分,一部分是数据库引擎部分;另一部分是可嵌入到许多 产品(如 C 语言,JAVA 语言等)工具中的独立引擎。可以将这两部分称为:数据库 PL/SQL 和工具 PL/SQL。两者的编程非常相似。都具有编程结构、语法和逻辑机制。工具 PL/SQL 另 外还增加了用于支持工具(如 Oracle Forms)的句法,如:在窗体上设置按钮等。本章主要 介绍数据库 PL/SQL 内容。 §11.2.1 PL/SQL 的好处 §11.2.1.1 有利于客户/服务器环境应用的运行 对于客户/服务器环境来说,真正的瓶颈是网络上。无论网络多快,只要客户端与服务器 进行大量的数据交换。应用运行的效率自然就回受到影响。如果使用 PL/SQL 进行编程,将 这种具有大量数据处理的应用放在服务器端来执行。自然就省去了数据在网上的传输时间。 §11.2.1.2 适合于客户环境 PL/SQL 由于分为数据库 PL/SQL 部分和工具 PL/SQL。对于客户端来说,PL/SQL 可以 嵌套到相应的工具中,客户端程序可以执行本地包含 PL/SQL 部分,也可以向服务发 SQL 命 令或激活服务器端的 PL/SQL 程序运行。 §11.2.1.3 客户及服务器端的好处 l 减少网络传输量 l 开发标准的代码 l 力争低偶联与高内聚性(少用全局变量和建立包来实现) l 隐藏实现细节 l 统一的和集中的方式处理工程项目,以达到重用 l 更好地设计数据库应用(标准化、降低维护) l 支持 SQL 语句 l 支持面向对象编程 l 更好的性能 l 轻便性(portability) l 更高的编程效率(productivity) 233 §11.2.2 PL/SQL 可用的 SQL 语句 PL/SQL 是 Oracle 系统的核心语言,现在 Oracle 的许多部件都是由 PL/SQL 写成。在 PL/SQL 中可以使用的 SQL 语句有: l 在 PL/SQL 中可以用的 SQL 语句有: INSERT UPDATE DELETE SELECT INTO COMMIT ROLLBACK SAVEPOINT 提示:在 PL/SQL 中只能用 SQL 语句中的 DML 部分,不能用 DDL 部分,如果要在 PL/SQL 中使用 DDL(如 Create table 等)的话,只能以动态的方式来使用。 l Oracle 的 PL/SQL 组件在对 PL/SQL 程序进行解释时,同时对在其所使用的表名、 列名及数据类型进行检查。 l PL/SQL 可以在 SQL*PLUS 中使用。 l PL/SQL 可以在高级语言中使用。 l PL/SQL 可以 在 Oracle 的 开发工具中使用。 l 其它开发工具也可以调用 PL/SQL 编写的过程和函数,如 Power Builder 等都可以调 用服务器端的 PL/SQL 过程。 §11.3 运行 PL/SQL 程序 PL/SQL 程序的运行是通过 Oracle 中的一个引擎来进行的。这个引擎可能在 Oracle 的服 务器端,也可能在 Oracle 应用开发的客户端。引擎执行 PL/SQL 中的过程性语句,然后将 SQL 语句发送给数据库服务器来执行。再将结果返回给执行端。比如已经用下面的脚本创建 了一个存储过程: create or replace procedure fundstat1(start_year_month in varchar2 , end_year_month in varchar2 ) is year_month0 varchar2(7); --年月 stat_date0 date; --统计时间 bank_code0 varchar2(20); --经办行代码 no_id0 number(2); --经办行序号 234 ... -- 声明光标, 用于 在各经办行信息表(bank_code)中取出每一个经办行名称 cursor get_bank is select bank_code , bank_name,no_id from bank_code order by no_id; begin set transaction use rollback segment hdhouse_rs;-- SCO 上的回退段 begin if (substr(end_year_month,5,2) >= 1 . . . . . . end; 则在 SQL*PLUS下运行可以用下面命令启动运行: SQL>execute funstat1(‘2001.01’,’2001.02’); 类似地,在 Power builder和 Developer /2000下可以用下面语句来启动运行: EXECUTE fundstat1(‘2001.01’,’2001.03’); 或 date1 := ‘2001.01’; date2 := ‘2001.03’; EXECUTE fundstat1 ( :date1,:date2 ); §11.4 PL/SQL 内置包 除了 Oracle 引擎提供环境让程序设计者根据应用要求来开发各个存储过程、函数、包及 触发器外。Oracle 系统本身提供了一套功能强大的内置包。这些系统包都以 DBMS_开头进行 命名。用这些包可以完成许多 Oracle 管理功能。关于 Oracle 内置包的详细说明请参考 《Oracle8I Supplied PL/SQL Packages Reference》原版资料。下面是一些常用包的简单说明: l DBMS_ALERT 数据库报警,允许会话间通信; l DBMS_JOB 任务调度服务; l DBMS_LOB 大对象操作用的包; l DBMS_PIPE 数据库管道用的包; l DBMS_SQL 动态SQL 所用的包; l UTL_FILE 文本文件I/O 所用的包。 235 第十二章 PL/SQL 块结构和组成元素 本章给出编写 PL/SQL 程序的基本结构和语句。 §12.1 PL/SQL 结构 l PL/SQL 块中可以包含子块; l 子块可以位于 PL/SQL 中的任何部分; l 子块也即 PL/SQL 中的一条命令; l 已定义的对象有一定的作用范围。 举例:本例是 一个嵌套子块的结构: Declare /* 本部分可以定义变量、光标等。 */ v_name varchar2(10); v_sql number(7,2); Begin /* 执行部分 */ . . . . . . select ename, sal into v_name, v_sal from scott.emp where empno=’7777’; begin /* 子块开始,也是执行语句 */ . . . . . . EXCEPTION /* 执行异常处理部分 */ . . . . . . end; EXCEPTION /* 执行异常部分 */ . . . . . . end; /* 本 PL/SQL 程序结束 */ 236 §12.2 PL/SQL 块 PL/SQL 程序由三个块组成,即 声明部分、执行部分、异常处理部分。 PL/SQL 块的结构如下: Declare /* 声明部分: 在此 声明 PL/SQL 用到的变量,类型及光标 */ begin /* 执行部分: 过程及SQL 语句 , 即程序的主要部分 */ Exception /* 执行异常部分: 错误处理 */ End; 其中 执行部分是必须的。 块可以分为四类: 无名块:动态构造,只能执行一次。 命名块:加了标号的块。 子程序:存储在数据库中的存储过程、函数及包等。当在数据库上建立好后可以在其它程序 中调用它们。 触发子:当数据库发生操作时,回触发一些事件,从而自动执行相应的程序。 §12.3 标识符 PL/SQL 程序设计中的标识符定义与 SQL 的标识符定义的要求相同。要求和限制有: l 标识符名不能超过 30 字符; l 第一个字符必须为字母; l 不分大小写; l 不能用’-‘(减号); l 不能是 SQL 保留字。 举例 1: 合法的标识符: declare v_name varchar2(20); /* 存放 name 列的值 */ v_sal number(9,2); /* 存放 sal 列的值 */ . . . . . . 举例 2: 不合法的标识符: 237 declare v-name varchar2(20); /* 存放 name 列的值 */ 2001_sal number(9,2); /* 存放 sal 列的值 */ mine&yours number; -- 非法的标识符 debit-amount number(10,4) ; -- 非法的标识符 on/off char(1); -- 非法的标识符 user id varchar2(20); -- 非法的标识符(不能用空格) 提示: 一般不要把变量名声明与表中字段名完全一样,如果这样可能得到不正确的 结果. 变量命名在 PL/SQL 中有特别的究竟,建议在系统的设计阶段就要求所有编程人员共同遵守 一定的要求。使得整个系统的文档在规范上达到要求。下面是建议的命名方法: 变量名 意义 V_variablename 程序变量 E_exceptionName 自定义的异常标识 T_TypeName 自定义的类型 P_parameterName 存储过程、函数的参数变量 C_ContantName 用 CONTANT 限制的变量 §12.4 PL/SQL 变量类型 在前面的介绍中,有系统的数据类型,也可以自定义数据类型。下表是 Oracle 类型和 PL/SQL 中的变量类型的合法使用列表: §12.4.1 变量类型 在 Oracle8i 中可以使用的变量类型有: 类型 子类 说 明 范 围 ORACLE限制 Char Character String Rowid Nchar 定长字符串 接受 nls 数据 0à32767 可选,缺省=1 255 Varchar2 Varchar String Nvarchar2 可变字符串 0à32767 4000 2000 238 Binary_integer 带符号整数,为整数计算优 化性能 Number(p,s) Dec Double precision Integer Int Numeric Real Small int 小数, Number 的子类型 高精度实数 整数, Number 的子类型 整数, Number 的子类型 与 Number 等价 与 Number 等价 整数, 比 integer 小 Long 变长字符串 0->2147483647 32,767 字节 Date 日期型 公元前 4712 年 1 月 1 日至公元后 4712 年 12 月 31 日 Boolean 布尔型 TRUE, FALSE,NULL 不使用 ROWID 存放数据库行号 例 1. declare order_no number(3); cust_name varchar2(20); order_date date; emp_no integer := 25; -- 缺省为 25 pi constant number := 3.14159; begin null; end; §12.4.2 复合类型(记录和表) ORACLE 在 PL/SQL 中除了提供象前面介绍的各种类型外,还提供一种称为复合类型 的类型---记录和表。 1. 记录类型 定义记录类型语法如下: TYPE record_type IS RECORD( Field1 type1 [NOT NULL] [:= exp1 ], Field2 type2 [NOT NULL] [:= exp2 ], . . . . . . Fieldn typen [NOT NULL] [:= expn ] ) ; 239 例 : -- 节选自在线代码 assign.sql DECLARE TYPE t_rec1 type is record ( Field1 number, Field2 varchar2(5) ); TYPE t_rec2 IS RECORD( Field1 number, Field2 varchar2(5)); V_Rec1 t_rec1 type; V_recc1 t_rec2 type; Begin /* 赋值 (要求类型一致) */ v_rec1 := v_rec2; v_rec1.field1 := v_rec2.field1; v_rec2.field2 := v_rec2.field2; end; 可以用 select 语句对记录变量进行赋值,只要保证 记录字段与 查询结果列表中的字段相 配即可。 例: --节选自在线代码 select.sql DECLARE -- 用 %TYPE 类型定义与表相配的字段 TYPE t_studentrecord IS RECORD( Firstname sutdents.first_name%TYPE, Lastname sutdents.last_name%TYPE, Major sutdents.major%TYPE ); -- 声明接收数据的变量 v_stduent t_StudentRecord; Begin Select first_name,last_name,major Into v_student From students Where id=10000; End; 240 §12.4.3 使用%ROWTYPE PL/SQL 可以声明与数据库行有相同类型的记录。 例: --节选自在线 tabrec.sql DECLARE TYPE t_studenttable is TABLE OF students%ROWTYPE INDEX BY BINARY_INTEGER; /* v_students 的每一元素是一个记录 */ v_students t_studentstable; Begin /* 将结果存到数组变量中 */ select * into v_students(10001) from students where id=10001; end; §12.4.4 LOB 类型 Oracle 提供了 LOB (Large OBject)类型,用于存储大的数据对象的类型。Oracle 目前主要支 持 BFILE, BLOB, CLOB 及 NCLOB 类型。 BFILE 存放大的二进制数据对象,这些数据文件不放在数据库里,而是放在操作系统的某个目录里, 数据库的表里只存放文件的目录。 BLOB 存储大的二进制数据类型。每个变量存储大的二进制对象的位置。大二进制的大小<=4GB。 CLOB 存储大的字符数据类型。每个变量存储大字符对象的位置,该位置指到大字符数据块。大字 符的大小<=4GB。 NCLOB 存储大的NCHAR字符数据类型。每个变量存储大字符对象的位置,该位置指到大字符数据块。 大字符的大小<=4GB。 241 §12.4.5 用户定义的子类型 在 Oracle7.2 后的版本中,可以定义一种称为子类型的类型,子类型可以使真正类型的名字 变为另外的名字(注意仅仅是一种真正类型的另外叫法)。子类型的声明使用 SUBTYPE 命令 说明。如: SUBTYPE CHARACTER IS CHAR; SUBTYPE INTEGER IS NUMBER(38,0); -- allows only whole numbers 这里子类型 CHARACTER 与真正类型 CHAR 一样, 所以 CHARACTER 是一个不受约束的子类型。 但是 INTEGER 是基本类型的一个子类型 NUMBER,所以 INTEGER 是受约束的子类型。 定义子类型 语法如下: SUBTYPE subtype_name IS base_type[(constraint)] [NOT NULL]; 例: DECLARE SUBTYPE BirthDate IS DATE NOT NULL; -- 基于 DATE 类型 SUBTYPE Counter IS NATURAL; -- 基于 NATURAL 子类型 TYPE NameList IS TABLE OF VARCHAR2(10); SUBTYPE DutyRoster IS NameList; -- 基于 TABLE 类型 TYPE TimeRec IS RECORD (minutes INTEGER, hours INTEGER); SUBTYPE FinishTime IS TimeRec; -- 基于 RECORD 类型 SUBTYPE ID_Num IS emp.empno%TYPE; -- 基于 column 类型 使用子类型 一旦定义子类型,就可以在声明的地方使用子类型。 DECLARE SUBTYPE Counter IS NATURAL; rows Counter; DECLARE SUBTYPE Accumulator IS NUMBER; total Accumulator(7,2); 242 例。 DECLARE SUBTYPE Numeral IS NUMBER(1,0); x_axis Numeral; -- 大小范围: -9 .. 9 y_axis Numeral; BEGIN x_axis := 10; -- 触发 VALUE_ERROR ... END; 类型的兼容性 一个无约束的子类型可以与基本类型进行交换,如: DECLARE SUBTYPE Accumulator IS NUMBER; amount NUMBER(7,2); total Accumulator; BEGIN ... total := amount; ... END; 不同的子类型也可以互换,如: DECLARE SUBTYPE Sentinel IS BOOLEAN; SUBTYPE Switch IS BOOLEAN; finished Sentinel; debugging Switch; BEGIN ... debugging := finished; ... END; 不同的子类型也可以互换,如: DECLARE SUBTYPE Word IS CHAR(15); SUBTYPE Text IS VARCHAR2(1500); verb Word; sentence Text(150); 243 BEGIN ... sentence := verb; ... END; §12.4.6 数据类型的转换 可以进行转换的隐式类型转换有: BIN_INT CHAR DATE LONG NUMBER PLS_INT RAW UROWID VARCHAR2 BIN_INT X X X X X CHAR X X X X X X X X DATE X X X LONG X X X NUMBER X X X X X PLS_INT X X X X X RAW X X X UROWID X X VARCHAR2 X X X X X X X X §12.5 运算符和表达式(数据定义) 与其他语言一样,为了完成所要求的各种处理,PL/SQL 需要下面各个运算符和表达式。 §12.5.1 关系运算符 关系运算符有: 运算符 意义 = 等于 <>, !=, ~=, ^= 不等于 < 小于 > 大于 244 <= 小于或等于 >= 大于或等于 §12.5.2 一般运算符 一般运算符有: 运算符 意义 + 加号 - 减号 * 乘号 / 除号 := 赋值号 => 关系号 .. 范围运算符 || 字符连接符 §12.5.3 逻辑运算符 逻辑运算符有: 运算符 意义 is null 是空值 Between 介于两者之间 In 在一列值中间 And 逻辑与 Or 逻辑或 Not 取返,如 is not null, not in, 245 §12.6 变量赋值 在 PL/SQL 编程中,变量赋值是一个值得注意的地方,它的语法如下: variable := expression ; variable 是一个 PL/SQL 变量, expression 是一个 PL/SQL 表达式. §12.6.1 字符及数字运算特点 l 空值加数字仍是空值: null + < 数字> = null l 空值加(连接)字符,结果为字符: null || <字符串> = < 字符串> §12.6.2 Boolean 赋值 布尔值只有 TRUE, FALSE 及 NULL 三个值。如: DECLARE done BOOLEAN; the following statements are legal: BEGIN done := FALSE; WHILE NOT done LOOP ... END LOOP; §12.6.3 数据库赋值 数据库赋值是通过 select 语句来完成的。每执行select 语句一次只能赋值一次。一般要求被 赋值的变量与select 中的列名要一一对应。如: 246 DECLARE emp_id emp.empno%TYPE; emp_name emp.ename%TYPE; wages NUMBER(7,2); BEGIN ... SELECT ename, sal + comm INTO emp_name, wages FROM emp WHERE empno = emp_id; ... END; 提示:不能将select 语句中的列赋值给布尔变量。 Declare V_string1 varchar2(10); V_string2 varchar2(15); V_numeric number; Begin V_string1 :=’Hello’; V_string2 := v_string1; V_numeric := -12.4; End; §12.6.4 可转换的类型赋值 l CHAR 转换为 NUMBERT 使用 TO_NUMBER 函数来完成字符到数字的转换,如: v_total := to_number(‘100.0’) + sal; l NUMBERT 转换为 CHAR 使用 TO_CHAR 函数可以实现 数字到字符的转换,如: v_comm := to_char(‘123.45’) || ’元’ ; l 字符 转换为 日期 使用 TO_DATE 函数可以实现 字符到日期的转换,如: v_date := to_date('2001.07.03','yyyy.mm.dd'); 247 l 日期 转换为 字符 使用 TO_CHAR 函数可以实现 日期到字符的转换,如: v_to_day := to_char(sysdate,'yyyy.mm.dd hh24:mi:ss') ; 可以在 SQL>下输入下面命令来验证以上的语句: select to_char(sysdate,'yyyy')||'年'||to_char(sysdate,'mm')||'月' ||to_char(sysdate,'dd')||'日' from dual; TO_CHAR(SYSDAT -------------- 2001 年 07 月 02 日 SQL> alter session set nls_date_format ='yyyy"年"mm"月"dd"日"'; Session altered. SQL> select sysdate from dual; SYSDATE -------------- 2001 年 04 月 24 日 SQL> select to_number('133')+200 from dual; TO_NUMBER('133')+200 -------------------- 333 SQL> select to_char('321')||'元' from dual; TO_CH ----- 321 元 SQL> select to_date('2001.07.03','yyyy.mm.dd') from dual; TO_DATE('2 ---------- 03-7 月 -01 248 §12.7 变量作用范围以可见性 在 PL/SQL 编程中,如果在变量的定义上没有做到统一的话,可能会隐藏一些危险的错 误,这样的原因主要是变量的作用范围所致。与其它高级语言类似,PL/SQL 的变量作用范 围特点是: l 变量的作用范围是在你所引用的程序单元(块、子程序、包)内。即从声明变量开 始到该块的结束。 l 一个变量(标识)只能在你所引用的名字内是可见的。 l 当一个变量超出了作用范围,PL/SQL 引擎就释放用来存放该变量的空间( 因为 它 可 能 不 用了)。 l 在子块中重新定义该变量后,它的作用仅在该块内。 §12.8 注释 在PL/SQL里,可以使用两种符号来写注释,即: l 使用双 ‘-‘ ( 减号) 加注释 PL/SQL允许用双 - - (双减号) 来写注释,它的作用范围是只能在1行有效。如: V_Sal number(12,2); -- 工资变量。 l 使用 /* */ 来加一行或多行注释 使用 /* . . . */ 在PL/SQL程序中加,可以对多行进行注释。如: 如: /***********************************************/ /* 文件名: stattistcs_sal.sql */ /* 功能:统计整个部门工资 */ /* 作者: 赵元杰 */ /* 修改日期 :2001.07.03 */ /***********************************************/ 或 /*********************************************** 文件名: stattistcs_sal.sql 功能:统计整个部门工资 249 作者: 赵元杰 修改日期 :2001.07.03 ***********************************************/ 提示:被解释存放在数据库中的PL/SQL 程序,一般系统自动将程序头部的注释去掉。只有 在Procedure 之后的注释才被保留;另外程序中的空行也自动被去掉。 建议:为了标准起见,最好使用 /* . . . */ 这样的注释语句。因为这样的注释在许多语言 中是相同的。 §12.9 简单例子 在我们给出编写 PL/SQL 程序所需的各个语句之前,先给出一些简单的例子,目的是让 读者对 PL/SQL 程序先有个感性认识。 §12.9.1 简单数据插入例子 /* 本例子仅是一个简单的插入,不是实际应用。 */ declare v_ename varchar2(20) := ‘赵元杰’; v_sal number(7,2) :=1234.56; v_deptno number(2) := 10; v_empno number(4) := 8888; begin insert into emp ( empno, ename, JOB, sal, deptno , hiredate ) values ( v_empno, v_ename, ‘自由职业’, v_sal, v_deptno, to_date(’1954.06.09’,’yyyy.mm.dd’) ); commit; end; / show error §12.9.2 简单数据删除例子 /* 本例子仅是一个简单的删除例子,不是实际应用。 */ declare v_ename varchar2(20) := ‘赵元杰’; 250 v_empno number(4) := 8888; begin delete from emp where empno=v_empno and ename=v_ename; commit; end; / show error 第十三章 PL/SQL 处理流程 在PL/SQL程序中,要使程序能按照逻辑进行处理,除了有些语句是SQL语句外,还必须有能 进行逻辑控制的语句。下面就介绍进行处理流程的语句结构。 §13.1 条件语句 IF <布尔表达式> THEN PL/SQL 和 SQL 语句 END IF; IF <布尔表达式> THEN PL/SQL 和 SQL 语句 ELSE 其它语句 END IF; IF <布尔表达式> THEN PL/SQL 和 SQL 语句 ELSIF < 其它布尔表达式> THEN 其它语句 END IF; 提示: ELSIF 不能写成 ELSEIF 例: --节选自在线代码 if1.sql DECLARE V_numberseats rooms.number_seats%TYPE; 251 V_comment varchar2(35); Degin Select number_seats into v_numberseats From rooms where room_id=99999; IF v_numberseats<50 then V_comment := ‘Fairly small’; Elsif v_numberseats < 100 then V_comment := ‘A little bigger’; Else V_comment := ‘Lots of room’; End if ; End; §13.2 循环 1. 简单循环 Loop 要执行的语句; end loop; --此循环将执行到遇到一条 exit 语句为止. 例 1. declare x number; begin x:= 0; loop x:=x+1; dbms_output.put_line(to_char(x)); exit when x=10; end loop; end; 例 2. --节选自在线代码 simple.sql DECLARE V_counter BINARY_INTEGER := 1; Begin 252 LOOP Inert into temp_table Values( v_counter, ‘loop index’ ); V_counter := v_counter + 1; If v_counter > 50 then Exit; End if ; End loop; End; 例 3. --节选自在线代码 exitwhen.sql DECLARE V_counter binary_index := 1; Begin Loop Insert into temp_table Values ( v_counter,’ loop index ‘ ); Exit when v_counter > 50 ; End loop; End; 2. WHILE 循环 While 循环 While <布尔表达式> loop 要执行的语句; end loop; 例 1. declare x number; begin x:= 1; while x<10 loop dbms_output.put_line(to_char(x)||’还小于 10’); x:= x+1; end loop; end; 253 例 2. --节选自在线代码 while1.sql DECLARE V_counter binary_integer := 1; Begin While v_counter <= 50 loop Inert into temp_table Values( v_counter, ‘loop index ‘) ; V_counter := v_counter + 1; End loop; End; 3. 数字式循环 For 循环 For 循环计数器 in 下限 .. 上限 loop 要执行的语句; end loop; FOR loop_counter IN [ REVERSE ] low_bound . . high_bound LOOP Sequence_of_statements; END LOOP; 例 1. begin for I in 1 .. 10 loop dbms_output.put_line(‘in=’||to_char(I)); end loop; end; 例 2. 254 --节选自在线代码 forscope.sql DECLARE V_counter number := 7; Begin Inert into temp_table (num_col) Values ( v_counter ); For v_counter IN 20 .. 30 loop Insert into temp_table (num_col ) Values ( v_counter ); End loop; Inert into temp_table (num_col ) Values( v_counter ); End ; 注:如果在 for 中用 INVERSE 关键字,则循环索引将从最大向最小进行迭代. §13.3 标号和GOTO PL/SQL 中 GOTO 语句是无条件跳转到指定的标号去的意思。语法如下: GOTO label; . . . . . . <
还剩642页未读

继续阅读

下载pdf到电脑,查找使用更方便

pdf的实际排版效果,会与网站的显示效果略有不同!!

需要 20 金币 [ 分享pdf获得金币 ] 1 人已下载

下载pdf

pdf贡献者

wqh_1011

贡献于2011-07-07

下载需要 20 金币 [金币充值 ]
亲,您也可以通过 分享原创pdf 来获得金币奖励!