本讲稿(ORACLE8i 数据库基础)是作者在多年的工作和授课中的总结,主要包括两个部分,第一部分是ORACLE SQL*PLUS基础,主要讲述ORACLE 应用系统设计的基本知识和给出一些有用的实例;第二部分是介绍ORACLE PL/SQL知识,主要讲述ORACLE数据库PL/SQL程序设计所用到基本知识,这部分给出进行应用设计所必需的基础知识。这两部分的内容都尽可能做到内容简洁而全面。特点是,1.用简单明了的语句对解释各个部分的内容,省去一些理论性的解释;2.给出作者在应用设计和开发中的一些具体的例子,为软件人员提供一些借鉴,省去查阅大量资料的时间。3.给出了许多资料所没有提供的一些使用技巧,如导出触发器等。总之,内容基本上包括当前Oracle8I的最新内容。同时也覆盖了最新的ORACLE8iOCP培训大纲的内容。不仅包含ORACLE 程序设计人员、DBA所必须掌握的知识,而且还含盖了系统分析员所要求的内容。与本书(讲稿)相伴的还有《Oracle8i/9i初级数据库管理》和《Oracle8i/9i高级数据库管理》。
全书内容简练实用,可作为ORACLE 数据库管理人员参考,也可作为应用开发人员和系统分析与设计人员以及大学计算机专业教学的参考资料。由于作者水平所限,加之ORACLE的产品与内容的浩瀚,在资料的整理与收集中可能有不少错误和不妥之处,希望读者给予批评制正。
目 录
第一部分 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
§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
§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
§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
§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 Exists218
§10.1.9 关于 COPY命令... 218
§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
§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.5SELECT 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
§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
§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
§23.1.1 调试指南... 363
§23.1.2 显示在编译产生的错误... 363
§23.2 插入测试表... 364
§23.3 DBMS_OUTPUT的使用... 364
§23.4 PL/SQL调试器... 365
§23.4.1 ProcedureBuilder调试器... 365
§23.4.2SQL-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
§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
§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
(+)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 RESOURCECOST. 471
ALTER ROLE. 472
ALTER ROLLBACKSEGMENT. 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
ASCII481
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
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 DATABASELINK.. 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 ROLLBACKSEGMENT. 507
CREATE SCHEMA.. 508
CREATE SEQUENCE. 509
CREATE SNAPSHOT. 509
CREATE SNAPSHOTLOG.. 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
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 ROLLBACKSEGMENT. 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
EMPTY_CLOB. 539
EXCEPTION INITPragma. 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
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
运算符—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
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
VARIABLEASSIGNMENT. 639
VARIANCE. 639
VSIZE. 640
RESERVED WORDS. 640
WHENEVER OSERROR. 641
WHENEVER SQLERROR. 642
WHILE-LOOP. 642
ZERO_DIVIDE. 643
Oracle的SQL*PLUS是设计所有应用系统的基础工具。要想将应用系统设计成一个健壮的、性能优越的系统。最关键的是要理解RDBMS的真正含义和结构,理解OracleSQL*PLUS 的特点和核心,弄清关系数据库与桌面数据库的差别。比如理解数据的完整性、一致性、索引、视图等。只有这样才能设计出符合Oracle特点的应用系统。从而保证系统在提供使用后不会出现一致性、性能等问题。
CODASYL(数据系统语言协会)是数据库任务组(Database Task Group,DBTG)创建的一种数据库标准,这是一种基于COBOL的网络数据库标准。
一个描述两个集合的元素如何相互联系或如何一一对应的数学概念,对于数据库来说,关系只是一个带有一些特殊属性的表。所以有:
l 数据的基础项是关系
l 在这些表上的操作只产生关系
一个关系表必须符合某些特定条件,才能成为关系模型的一部分
l 储存在单元中的数据必须是原子的。每个单元只能存储一条数据,叫信息原则(Information Principle)。如果存储多条则违反信息原则。特舒情况下可能需要违反信息原则。
l 储存在列下的数据必须具有相同的数据类型。
l 每一行是唯一的(没有完全相同的行)。
l 列没有顺序。
l 行没有顺序
l 列有一个唯一性的名称。
关系模型的另一个是完整性原则。它包括实体完整性原则(Entity integrity rule)和引用完整性原则( Referential integrity rule ),如:
l 主键(Primary key )是能唯一标识行的一列或一组列的集合。
l 由多个列构成的主键称为连接键(Concatenated key)、组合键(Compound key ),或称作为复合键(Composity key )。
另外就是外部键(Foreign key )是一个表中的一列或一组列,它们在其它表中作为主键而存在。一个表中的外部键被认为是对另外一个表中主键的引用。实体完整性原则简洁地表明主键不能全部或部分地空缺或为空,引用完整性原则简洁地表明一个外键必须为空或者它所引用的主键当前存在值相一致。
Oracle数据库系统是一个完美的完全符合数据库技术的关系数据库系统。要想你的应用设计按照数据库原理来进行,最重要的就是理解Oracle的结构、语句和命令。Codd提出的十二条法则在Oracle系统中都可以找到:
1)信息法则。
2)授权存储法则,每一个数据项都通过“表名+行主键+列名”的组合形成访问。
3)必须以一致的方法使用空值。
4)一个活跃的、在线数据字典应作为关系型表被储存
5)必须提供数据存取语言进行存取访问。
6)所有能被更新的视图应当是可被更新的。
7)必须有集合级的插入、更新和删除。
8)物理数据的独立性。即应用不依赖物理结构。
9)逻辑数据的独立性。如果一个表被分成两个部分,则应用视图连接在一起,以便不会对应用产生影响。
10) 完整性的独立性。完整性规则应该储存在数据字典中。
11) 分布独立性。一个数据库即使被分布,也应该能工作。
12) 非破坏性原则。如果允许低级存取,一定不能绕过安全性和完整性原则。
RDBMS由两部分组成,即数据库系统内核(软件)和数据字典(内核用于管理数据库系统的数据结构)两部分。
RDBMS就是用来控制数据访问的操作系统。它的任务是按照一定的规则存储数据、检索数据及保护数据。
数据自动存放数据库中所有对象(如表,索引,视图等)所需的信息。Oracle 8i 的数据字典是存放数据库系统信息的一组表,从数据字典中的信息可以确认数据库中数据对象的基本信息及存放位置。
下面用简单的语言解释Oracle的常用产品所包含的SQL*PLUS和PL/SQL的关系。
SQL是标准结构查询语言,而SQL*PLUS实际是包括标准的SQL和Oracle公司的一些命令组成的产品,因而Oracle公司将其取名为SQL*PLUS。下面是它们的解释。
1. SQL(StructuredQuery 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
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
Update
Select
Commit work
Rollback
PL/SQL是OracleRDBMS (Oracle 6 之后版本)的一个组成部分,PL 是“过程化语言(ProcedureLanguage )”的缩写。PL/SQL语言是在SQL语言中结合了结构化过程语言成分的准第四代语言。
使用PL/SQL的目的:
由于大多数PL/SQL是在服务端来运行,这样可减少由客户端运行程序时所需的网络数据流量。
可以使用PL/SQL的地方:
l PL/SQL可以单独进行程序的编写,完成一般的处理功能;
l 在高级语言中可嵌入PL/SQL 块;
l 在4GL中可以嵌入PL/SQL块;
l 在PL/SQL程序中可以嵌入 HTML和XML。
我们创建任何对象,如创建表、索引等都需要连接到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 不再支持字符终端)
在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))
)
(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 =
(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:
$sqlplususername/password
或
$SQLPLUS username/password@connect_string
3)用下面命令隐式登录到 SQL*PLUS:
$sqlplus [enter]
Enter username:scott
Enterpassword:******
在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)
)
)
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 =
(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:
$sqlplususername/password
或
$SQLPLUS username/password@connect_string
Windows NT/2000图形方式登录步骤:
1)点击“开始”=》“程序”=》“Oracle –OraHome81”=》“Application on Development”=》“SQL Plus”进入如下屏幕:
|
在WINDOWSNT/98/2000上的登录界面(sqlplus图)
可以在用户名框内输入用户、口令及主机字串;也可以分别进行输入。
Oracle公司提供的附加语句(或称命令),可以满足程序人员和管理员的一些特殊操作要求。比如,在显示超过上百行记录信息时,可以采用每屏“暂停”来实现。要达到这样的目的,就要在SQL>下发 set pause on 命令。由于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 目录下。
可以用 exit 或quit 来终止SQL*PLUS的操作(会话)。语法如下:
{EXIT|QUIT} [SUCCESS|FAILURE|WARNING ]
{EXIT|QUIT} 可以用exit 或quit ,目前它们的功能一样。
SUCCESS 正常退出
FAILURE 带提示错误代码的退出
WARNING 带提示警告代码的退出
COMMIT 退出前将未提交进行保存
例如:
SQL>exit
DESCRIBE可以用(只要用DESC即可)来显示表、视图的列的定义,也可以显示同义词、函数或存储过程的说明。语法如下:
DESC[RIBE] {[schema.]object[@connect_identifier]}
Schema:用户名,如果省去,则为对象的所有者。
object
可以是表(table), 视图(view),类型( type), 存储过程(procedure),函数( function), 包(package)或同义词( synonym)
@connect_identifier
数据库连接字串
例:显示emp 表的结构:
SQL>desc emp
可以用 LIST 命令来列出当前SQL缓冲区中的一行或多行命令语句。
L[IST] [n|n m|n *|n LAST|*|* n|* LAST|LAST]
n 列出第n行
nm 列出n到m行
n * 列出第n行到当前行
n LAST 列出第n行到最末行
* 列出所有行
* n 列出当前行到第n行
*LAST列出当前行到最末行
LAST 列出最末行
例:
SQL> LIST
1 SELECT ENAME, DEPTNO, JOB
2 FROM EMP
3 WHERE JOB = ’CLERK’
4* ORDER BY DEPTNO
可以用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>
可以用 Append命令来完成在当前行的末尾追加字符串。语法如下:
A[PPEND] text
Text 所要求追加的字符串
例:在当前行selectsal,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 wheresal>=2000
SQL>
可以用SAVE命令将当前的命令行保存到操作系统的文件中。语法如下:
SAV[E] filename[.ext][CRE[ATE]|REP[LACE]|APP[END]]
其中:
filename:你将把缓冲区中的内容存入到操作系统目录的文件名。
ext:若使用文件后缀,缺省的文件后缀为SQL。
例:
SQL>select table_namefrom dict where table_name like ‘%ROLE%’;
SQL>save c:\get_role
可以用GET 命令将操作系统的目录下的命令文件读到缓冲区(但不执行)。语法如下:
GET filename [.ext][LIS[T]|NOL[IST]]
其中:
filename: 希望加载到SQL缓冲区的文件名
ext: 文件的扩展名,缺省为 SQL.
例:
SQL>get c:\get_role
Oracle的SPOOL 命令可以实现将屏幕所出现的一切信息记录到操作系统的文件中直到SPOOL OFF为止。语法如下:
SPO[OL] [filename[.ext] |OFF | OUT]
其中:
filename:你想输出(spool)的文件名。
ext:文件的后缀。缺省的后缀是LST(或LIS)。
SQL>coltable_name for a20
SQL>col commentsfor a80
SQL>set linesize110
SQL>SPOOlc:\all_dict
SQL>selecttable_name,comments from dict;
. . . .. . (系统查询信息)
SQL>SPOOL OFF
在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%'
SQL> /
TABLE_NAME
------------------------------
DBA_ROLES
DBA_ROLE_PRIVS
USER_ROLE_PRIVS
ROLE_ROLE_PRIVS
ROLE_SYS_PRIVS
ROLE_TAB_PRIVS
SESSION_ROLES
已选择7行。
ORACLE 提供许多内部数据字典, 用以管理系统的各种信息和参数(即数据库对象),下面列出几个常用的数据字典供初学者参考,其它方面的数据字典将在DBA管理中介绍。
ORACLE 数据字典的命名说明:
USER 为前缀----记录用户的所有对象信息
ALL 为前缀----记录包括 USER 记录和授权给PUBLIC或该用
户的所有对象的信息。
DBA 为前缀----记录关于数据库对象(非用户对象)的信息。
V$ 公共系统动态视图,用于系统优化和调整参考.
V_$ 动态性能视图,你可用 CATALOG.SQL 脚本建立动态视图建立同义词。
GV$ 新(oracle 8)的附加的固定视图(Global V$).在并行环境下反应的是
V$视图的信息。如:
SELECT * FROMGV$LOCK WHERE INST_ID = 2 OR INST_ID = 5 ;
返回的是instances2 和5的V$的信息。所以GV$反应一组Instances的参数.GV$视图的限制是参数PARALLEL_MAX_SERVERS必须大于0 。
详见 OracleEnterprise Manager Administrator's Guide.
注:请注意下面的总结:
l 一般DBA_的视图内容都包含USER_和ALL_为前缀的视图;
l DBA_为前缀的视图的内容基本上是大写;
l 以V$_为前缀的视图的内容基本上是小写。
1.USER_TABLEs(=TABS) 用户的所有表的信息。
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'; 等来实现对表或列进行注释,但不建议设计者采用这样的工作方式。而建议将注释写到脚本中更为直观。
Oracle数据库的数据类型与其它的数据库系统相比,它的数据类型不多,Oracle在表示数据方面比其他数据库系统来说要省去许多关键字。Oracle只用NUMBER(m,n)就可以表示任何复杂的数字数据。其它如日期类型等也简单得多,只DATE就表示日期和时间。下面以列表形式给出各个版本的Oracle系统数据类型的表示方法。下面给出Oracle旧版本的数据类型的目的是让读者了解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 是变长),字符长度不够自动在右边加空格符号。当字符长度超出2000个则错误。不指定大小缺省为 1。
VARCHAR(
可变字符型,当前与VARCHAR2(
VARCHAR2(
可变字符型,当前与VARCHAR(
NCHAR(
NCHAR 和NVARCHAR2 分别与CHAR和VARCHAR2 有相同的大小。并用于于存放National Language Support (NLS)数据,Oracle 允许以本地语言存放数据和查询数据。
如果将列名声明成NCHAR、NVARCHAR2这样的类型,则insert和 select 等语句中的具体值前加N,不能直接按照普通字符类型进行操作。看下面例子:
SQL> create tablenchar_tst(name nchar(6),addr nvarchar2(16),sal number(9,2));
表已创建。
SQL> insert intonchar_tst values(N'赵元杰',N'北京市海淀区',9999.99);
已创建 1 行。
SQL> select * fromnchar_tst where name like N'赵%';
NAME ADDR SAL
---------------------- ----------
赵元杰 北京市海淀区 9999.99
SQL> select *from nchar_tst where name like '赵%';
select * fromnchar_tst where name like '赵%'
*
ERROR 位于第 1 行:
ORA-12704: 字符集不匹配.
提示:虽然Oracle可以使用nchar, nvarchar2 类型来存放字符数据,但建议设计者不要使用NCHAR和NVARCHAR2。因为CHAR和VARCHAR2就能存放汉字。
NUMBER( ,)
是数据的整数部分,是数据的精度(即小数)部分,注意,部分可以表示负的精度。用可以表示从小数点往右或往左保留多少位。如下表:
实际值 |
数据类型 |
存储值 |
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 tablesave_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 行。
SQL> select *from save_info;
PER_ID NAME TRAN_DATE TRAN_VAL
---------------------------------------- ---------- ----------
110105540609811 赵元杰 18-6月 -01 1234.66
SQL> selectper_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> showparameter nls_date_format
NAME TYPE VALUE
------------------------------------------- ------------------------------
nls_date_format string
SQL> altersession set nls_date_format=
2 '"公元"yyyy"年"mm"月"dd"日"';
会话已更改。
SQL> selectsysdate from dual;
SYSDATE
------------------
公元2001年05月18日
SQL> selectto_char(sysdate,'cc yyyy.mm.dd') from dual;
TO_CHAR(SYSDA
-------------
21 2001.05.18
关于日期型的使用方法详细请参考《Oracle8i National Language Support Guide》。
BLOB
大二进制对象,每条记录可存储达4GB的数据,详细见后面章节。
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
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;
下面给出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 !=’赵元杰’; |
< |
小于测试 |
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 |
用于返回两个查询中的不同的行。 |
|
当我们可以用SQL*PLUS登录到SQL>下后,我们可以用DESC 显示某表的结构,也可以用select 语句简单查询表中的一些列的内容。
例:要查询EMP表中员工的姓名、工资及出生日期,则:
SQL>select ename, sal, hiredate from emp;
Oracle系统为了实现完整的关系数据库功能,系统专门提供了一组称为伪列(Pseudocolumn)的数据库列,这些列不是在建立对象(如建表)时由我们完成的,而是在我们建立对象时由自动Oracle完成的。Oracle目前有以下的伪列:
l CURRVALand 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') fromDUAL;
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
在新的Oracle版本里,系统提供了一个叫SQLWorksheet 的图形SQL工作环境,它是ORACLEEnterprise Manager 的一部分。使用它可以免去在SQL>下编辑行命令的不便。它完全是在图形方式进行。它的启动有以下几种方法:
l 从ORACLEEnterprise Manager中启动
l 从Administrtor工具中启动
l 从操作系统中启动
下面给出在操作系统下启动SQL Worksheet 工具工作的步骤:
1) 点击 SQL Worksheet 图标,即选择 开始->程序->Oracle-OraHome81->databaseAdministration->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 会结果显示在屏幕的下方:
图 1。10-2 登录成功后的画面
图1.10-3 查询命令及显示结果画面
从SQL Worksheet 工具中可以看出,该工具提供了相当丰富的功能。下面给出个功能的简要说明:
1.文件:
l 改变数据库连接:可以连接到另外的用户和数据库上去;
l 打开:可以打开现有文件;
l 将输入另存为:将当前命令存为一个文件;
l 将下方显示的结果存为一个文件。
2.编辑:
l 剪切:将当前选中字符进行剪切;
l 复制:将选中字符进行剪切;
l 粘贴:将缓冲区字符进行粘贴;
l 全选:对当前画面所有字符全选;
l 全部清除:清除目前的所有内容。
3.工作单:
l 执行:执行当前的命令;
l 运行本地脚本:运行操作系统下某个.SQL文件(点击后提示输入文件名);
l 命令历史记录:查看命令历史记录;
l 上一条命令:显示上一条命令。
提示:如果你的SQLWorksheet显示的不是汉字(出现乱字符),请你将你的NT/2000/98环境下的汉字变量设置与服务器的一样就好了。在WINDOWS NT环境设置汉字变量步骤:
用regedit修改注册表中的所有ORACLE字符集项,如:
1)点击:开始=》运行=》输入regedit;
2)点击“HEY_LOCAL_MACHINE”左边的“+”以展开目录;
3)点击“SOFTWARE”左边的“+”以展开目录;
4)点击“ORACLE”项;
5)修改ORACLE树下所有“NLS”变量与props$中的一致。
关于汉字环境变量的设置,请参阅《Oracle8i/9I初级数据库管理》。
下面给出查询的一些基本的操作描述,如果你是位Oracle老手则可以跳这一章。
在关系数据库中,使用频率最高要算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 原版《ORACLE8iSQL REFERENCE MANUAL》或《ORACLE9i SQL REFERENCE MANUAL》
许多资料(包括Oracle 的资料)把Oracle的SQL语句中用到的函数分为单值函数和多值函数,单值函数又分为字符函数和数字函数。下面分别介绍它们。
函 数 |
说 明 |
ASCII |
返回对应字符的十进制值 |
CHR |
给出十进制返回字符 |
CONCAT |
拼接两个字符串,与 || 相同 |
INITCAT |
将字符串的第一个字母变为大写 |
INSTR |
找出某个字符串的位置 |
INSTRB |
找出某个字符串的位置和字节数 |
LENGTH |
以字符给出字符串的长度 |
LENGTHB |
以字节给出字符串的长度 |
LOWER |
将字符串转换成小写 |
LPAD |
使用指定的字符在字符的左边填充 |
LTRIM |
在左边裁剪掉指定的字符 |
RPAD |
使用指定的字符在字符的右边填充 |
RTRIM |
在右边裁剪掉指定的字符 |
REPLACE |
执行字符串搜索和替换 |
SUBSTR |
取字符串的子串 |
SUBSTRB |
取字符串的子串(以字节) |
SOUNDEX |
返回一个同音字符串 |
TRANSLATE |
执行字符串搜索和替换 |
TRIM |
裁剪掉前面或后面的字符串 |
UPPER |
将字符串变为大写 |
NVL |
以一个值来替换空值 |
ASCII(
SQL> selectascii('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> selectchr(54740) zhao,chr(65) chr65 from dual;
ZH C
-- -
赵 A
CONCAT(
SQL> selectconcat('010-','8801 8159')||'转23' 赵元杰电话 from dual;
赵元杰电话
-----------------
010-8801 8159转23
INITCAP(
返回字符串c1 并第一个字母变为大写。例如:
SQL> selectinitcap('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
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> selectname,lengthb(name),length(name) from nchar_tst;
NAME LENGTHB(NAME) LENGTH(NAME)
------ ------------- ------------
赵元杰 6 3
LOWER (
返回字符串并将所有字符变为小写。
SQL> selectlower('AaBbCcDd') AaBbCcDd from dual;
AABBCCDD
--------
aabbccdd
UPPER(
与 LOWER 相反,将给出字符串变为大写。如:
SQL> select upper('AaBbCcDd') AaBbCcDd from dual;
AABBCCDD
--------
AABBCCDD
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])
对字串(或字段),从start字节 开始,连续取 count 个字节并返回结果,如果没有指count则一直取到尾。
REPLACE (‘string’ [,’string_in’,’string_out’])
String:希望被替换的字符串或变量。
String_in:被替换字符串。
String_out:要替换字符串。
SQL> selectreplace('Informaix中国公司','Informaix','IBM Informix')
2 IBM数据库from dual;
IBM数据库
--------------------
IBM Informix中国公司
SOUNDEX(
返回一个与给定的字符串读音相同的字符串(不管拼写是否一样)。
SELECT DPL_NAME FROMDENIED_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:要替换字符串。
SELECTREPLACE (‘Oracle’, ‘Or’, ‘Mir’) “Example“ FROM DUAL;
Example
-------
Miracle
TRIM( [
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 (0FROM 0009872348900) "TRIM Example" FROM DUAL;
TRIM example
--------------------------------
98723489
函数 |
说明 |
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的存储空间大小 |
ABS(
返回指定值的绝对值。如:
SQL> selectabs(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(
返回大于或等于给出数字的最小整数。如:
SQL> selectceil(3.14159) from dual;
CEIL(3.14159)
-------------
4
COS (
返回一个数字余弦值。如:
SQL> selectcos(-3.1415926) from dual;
COS(-3.1415926)
---------------
-1
COSH (
返回一个数字双曲余弦值。如:
SQL> select cosh(20)cosh from dual;
COSH
----------
242582598
EXP (
返回一个数字 e 的 n 次方的值。如:
SQL> selectexp(2),exp(1) from dual;
EXP(2) EXP(1)
---------- ----------
7.3890561 2.71828183
FLOOR (
对给定的数字取整数,如:
SQL> selectfloor(123.45),floor(45.56) from dual;
FLOOR(123.45) FLOOR(45.56)
------------- ------------
123 45
LN(
返回一个数字的对数值,n 是大于 0 的数字,如:
SQL> selectln(1),ln(2),ln(3) from dual;
LN(1) LN(2) LN(3)
---------- ---------- ----------
0 .693147181 1.09861229
LOG(
返回一个以n1为底的n2的对数,n1不是0或1的正数。如:
SQL> selectlog(2,1),log(2,2) from dual;
LOG(2,1) LOG(2,2)
---------- ----------
0 1
MOD(
SQL> Selectmod(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> selectpower(2,10),power(3,3) from dual;
POWER(2,10) POWER(3,3)
----------- ----------
1024 27
ROUND(value,precision)
按照指定的精度进行舍入;
selectround(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> selectsin(1.57079) from dual;
SIN(1.57079)
------------
1
SINH(
返回双曲余弦的值,如:
SQL> selectsin(20),sinh(20) from dual;
SIN(20) SINH(20)
---------- ----------
.912945251 242582598
SQRT(
返回 数字 n 的根,如:
SQL> selectsqrt(64),sqrt(10) from dual;
SQRT(64) SQRT(10)
---------- ----------
8 3.16227766
TAN(
返回数字 n的正切值,如:
SQL> selecttan(20),tan(10) from dual;
TAN(20) TAN(10)
---------- ----------
2.23716094 .648360827
TANH(
返回数字 n的双曲正切值,如:
SQL> selecttanh(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;
TRUNC1 TRUNC(124.16666,2)
----------------------------
100 124.16
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> selectto_char( add_months(to_date('199712','yyyymm'), 1),'yyyymm') add_month
2 fromdual;
ADD_MO
------
199801
SQL> selectto_char(add_months(to_date('199712','yyyymm'), -1 ),'yyyymm') add_mo
2 fromdual;
ADD_MO
------
199711
LAST_DAY( date)
返回日期date 所在月的最后一天,如:
SQL> selectto_char(sysdate,'yyyy.mm.dd'),to_char((sysdate)+1,'yyyy.mm.dd')
2 fromdual;
TO_CHAR(SYTO_CHAR((S
--------------------
2001.05.182001.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> selectmonths_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 |
阿拉斯加-夏威夷标准/日期时间 |
MST/MDT |
山区标准/日期时间 |
NST |
新大陆标准时间 |
PST/PDT |
太平洋标准/日期时间 |
YST/YDT |
Yukon标准/日期时间 |
SQL> selectto_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:252001.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> selectto_char(sysdate,'dd-mon-yyyy day') from dual;
TO_CHAR(SYSDATE,'DD
-------------------
18-5月 -2001 星期五
TRUNC(
按照 给出的 fmt 的要求将日期截断。如果 fmt=’mi’ 则表示截断掉秒保留至分。如:
SQL> selectto_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;
HH HHMM
--------------------------------------
2001.05.18 22:00:002001.05.18 22:27:00
函 数 |
描 述 |
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 fromscott.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
---------------
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> selectto_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. |
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(
将给出的字符转换为数字,如:
SELECT TO_NUMBER (‘1947’) “FISCAL_YEAR” FROM DUAL;
FISCAL_YEAR
-----------
1947
TO_MULTI_BYTE(
将单字节转换为多字节或从多字节转换为单字节。
BFILENAME(
指定一个外部二进制文件。如:
INSERT INTOfile_tbl
VALUES (BFILENAME(’lob_dir1’, ’image1.gif’));
CONVERT(‘x’,’desc_set’ [, ‘source_set’])
将x 字段或变量的源 source 转换为 desc,如:
selectsid,serial#,username,
DECODE(command,
0,’None’,
2,’Insert’,
3,’Select’,
6,’Update’,
7,’Delete’,
8,’Drop’,
‘Other’) cmd
from v$session wheretype != ‘BACKGROUND’;
关于DECODE 在优化方面的内容在《Oracle8i/9i 高级数据库管理》中查阅。
DUMP( s,[,fmt [,start [, length ] ] ] )
DUMP 函数以fmt指定的内部数字格式返回一个VARCHAR2类型的值。如:
SQL> col global_namefor a30
SQL> col DUMP_STRINGfor 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> selectgreatest('AA','AB','AC') from dual;
GR
--
AC
SQL> selectgreatest('啊','安','天') from dual;
GR
--
天
即 “天”的编码比“安”和“啊”都大。
LEAST (
返回一组表达式中的最小值,即比较字符的编码大小。如:
SQL> select least('啊','安','天')from dual;
LE
--
啊
UID 函数
返回标识当前用户的唯一整数,如:
SQL> show user
USER 为"SYSTEM"
SQL> l
1* select username,user_id from dba_userswhere user_id=UID
SQL> /
USERNAME USER_ID
------------------------------ ----------
SYSTEM 5
USER 函数
返回当前用户的名字,如:
SQL> select userfrom dual;
USER
------------------------------
SYSTEM
USERENV(
返回当前用户环境的信息,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> selectuserenv('ISDBA') from dual;
USEREN
------
FALSE
SQL> connectsys/sys@ora816
Connected.
SQL> selectuserenv('ISDBA') from dual;
USEREN
------
FALSE
SQL> connectinternal
Connected.
SQL> selectuserenv('ISDBA') from dual;
USEREN
------
TRUE
SESSIONID函数
返回审计会话标识,如:
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> selectuserenv('INSTANCE') from dual;
USERENV('INSTANCE')
-------------------
1
LANGUAGE函数
返回当前环境的语言,如:
SQL> selectuserenv('LANGUAGE') from dual;
USERENV('LANGUAGE')
----------------------------------------------------
SIMPLIFIEDCHINESE_CHINA.ZHS16GBK
LANG函数
返回当前环境的语言的缩写,如:
SQL> l
1* select userenv('LANG') from dual
SQL> /
USERENV('LANG')
----------------------------------------------------
ZHS
TERMINAL函数
返回用户的终端或机器的标识,如:
SQL> selectuserenv('TERMINAL') from dual;
USERENV('TERMINA
----------------
ZHAOYUANJIE
VSIZE(
返回 x 的大小(字节)数,如:
SQL> selectvsize(user),user from dual;
VSIZE(USER) USER
----------- -----------------------------
6 SYSTEM
AVG( [ { DISTINCT | ALL}] )
求平均值,ALL表示对所有求平均值,DISTINCT 只对不 同的求平均值,相同只取一个。
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> selectstddev(sal) from emp;
STDDEV(SAL)
-----------------
1182.50322
VARIANCE( [ { DISTINCT | ALL}] )
求协方差,ALL表示对所有求协方差,DISTINCT 只对不同的求协方差,相同只取一个。
SQL> selectvariance(sal) from emp;
VARIANCE(SAL)
------------------------
1398313.87
可以用 GROUP By 来实现对一组数进行分组统计(如SUM,count(*)等),如:
要列出部门代码、部门人数,部门工资总和,则用到GROUP BY :
SQL> selectdeptno,count(*) ,sum(sal) from emp group by deptno;
DEPTNO COUNT(*) SUM(SAL)
---------- --------- ----------
10 3 8750
20 5 10875
30 6 9400
在分组GROUP BY 中,一般都不管 统计的结果是多少都要全显示,我们可以在GROUP BY 前或后加 HAVING 子句来限制结果的统计,比如要求被统计的人数有5个人以上,则有两方法可以实现:
SQL> selectdeptno,count(*) ,sum(sal) from emp group by deptno
2 having count(*)>=5;
DEPTNO COUNT(*) SUM(SAL)
---------- ---------- ---------
20 5 10875
30 6 9400
SQL> selectdeptno,count(*) ,sum(sal) from emp having count(*)>=5
2 groupby deptno;
DEPTNO COUNT(*) SUM(SAL)
---------- ---------- ----------
20 5 10875
30 6 9400
Oracle 提供ORDERBY 子句,可用于对查询到的结果进行排序输出。这样的操作是在内存中进行的。比如按照部门代码顺序和员工的工资多少顺序进行输出,需要命令:
SQL> selectdeptno,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(工资) 按照降序排列。
一般可以用 BREAK ON column SKIP xx 来对查询结果进行排列,BREAK ON 命令的参数如下:
clear breaks 清除所有的 break 定义
break on column 在该列上中断
break on row 在每一行上中断
break on Page 在每一页上中断
break on report 在每一报告上中断
skip n 跳过n行
skip page 跳过未用完的页
使用方法请看下面例子:
SQL> break ondeptno
SQL> set pagesize100
SQL> selectdeptno,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 ondeptno skip 2
SQL> selectdeptno,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
SQL> break ondeptno 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行。
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
********* ----------
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’)
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
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.
一般在SQL>下进行SQLPLUS 操作,都需要进行必要的环境设置才能完成我们所需要的输出。所有环境的设置由 SET命令加相应的环境变量来完成。下面是常用的环境设置:
SET ARRAY[SIZE]{integer}
一次可以提取(Fetch)的行的数目,1->5000,当有较长字段时应设小些。
SET AUTO [COMMIT] {[ OFF | ON | IMM | n] }
用于在操作中是自动提交或是部分提交或是不自动提交。
1) ON或IMM使得在完成每条SQL语句时将未提交的改变立刻提交给数据库系统。
2) N 允许在用户发出COMMIT后,可以执行命令的数量(将n条SQL语句所做的改变进行提交)。
3) OFF 停止自动提交,用户必须用COMMIT命令才能被提交。
可以设置 LINESIZE 环境变量来控制行的显示宽度,缺省是80个字符。
SET Lin[esize]{80|integer}
Integer = 设置行宽度(字符个数),最大值999,如:
SQL>set linesize160
在缺省的SQL> 状态下,SQL>缓冲区用于显示LONG 的字节数只有80个字符。如果我们需要查询的列中含有 LONG类型的字段的话,就需要将LONG缓冲区设置大些。
SET LONG{80|integer}
Integer 是 显示或拷贝long值的最大宽度,n=1->32767(但必须小于Maxdata值)
SQL>show Maxdata (最大行宽)
SQL>set long 2000
在缺省的SQL> 状态下,SQL>缓冲区显示页的行数是24行,其中22行显示数据,2行显示标题和横线。我们将pagesize 设置大些以减少提示标题和横线。
SET pag[esize] {24|integer}
SQL>SET pagesize66
可以设置 PAUSE 为ON 或OFF来控制屏幕显示。当设置为ON时,在select 语句发出后需要按Enter键才能显示一屏。
SET PAUSE [ ON | OFF]
SQL> set pause on
提示:在发出select 语句并按Enter键后 还要再按Enter键才能显示结果.
可用 set space 来设置各列间的空格数,语法为:
SET SPA[CE] {1|n}
N为设置输出行列间的空格数,最大为10。
SQL>set space 2
建议:在一般情况下,不用设置space参数。
TERMOUT用于设置在屏幕上显示或不显示所输出的信息。
SET TERMOUT { ON | OFF }
set termout off
set termout on
set termout off 常用SPOOL XXX时,即关闭报表在屏幕上的显示(节省时间)
set termout on 常用SPOOL off之后,即恢复报表在屏幕上的显示
可以用ECHO命令来显示或不显示所执行的SQL命令。语法如:
SET ECHO{OFF|ON}
显示执行当中的各命令( 即用start 时)
set echo 受到 set termout 的影响
set pagesize 100
set echo on
select table_namefrom dict where rownum<20;
select * from catwhere rownum<30;
set echo off
--下面只显示结果不显示命令:
select table_namefrom dict where rownum<20;
select * from catwhere rownum<30;
一个很重要的事务环境设置是TRANSACTION。它包括两个部分的内容:
SET TRANSACTION { READ ONLY | USE ROLLBACK SEGMENTsegment_name }
READ ONLY 是用于保证读的一致性。即其他用户的修改不影响当前查询结果。
USE ROLLBACK SEGMENT segment_name 是为当前所处理的事务指定专门的回滚段。这主要是在进行大量的Insert 或Delete 或Update时,需要一个大的回滚段以保证事务正常完成。详细见数据库管理员。
可以用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 ""
compatibilityversion NATIVE
concat"." (hex 2e)
copycommit 0
COPYTYPECHECK 为 ON
define"&" (hex 26)
describe DEPTH 1LINENUM OFF INDENT ON
markup HTML OFFSPOOL OFF ENTMAP ON PREFORMAT OFF
echo OFF
editfile"afiedt.buf"
embedded OFF
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
shiftinoutINVISIBLE
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 语句的前几个字符
underline"-" (hex 2d)
USER 为"SYS"
verify ON
wrap : 行将为已换行
SQL>
你可以从上面的参数中看到其当前值,也可以修改某些参数的值。
在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的个数决定最多显示多少位
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> selectename,sal from emp;
例子:
SQL
COLUMN SALARY FOR $9,999,999.99
COLUMN LAST_NAME FOR A35.
Oracle系统提供了一个 NLS_DATE_FORMAT的环境变量来设置日期的显示格式。用它可以完成按照不同格式要求的显示,比如按照中国的习惯为 yyyy年mm月dd日等。
1.系统日期sysdate 的显示
用sysdate 可以显示ORACLE RDBMS 所在机器的日期及时间,如:
SQL> altersession set nls_date_format ='"公元"yyyy"年"mm"月"dd"日"';
会话已更改。
SQL> selectsysdate from dual;
SYSDATE
------------------
公元2001年05月30日
2.日期类型的显示
selectsysdate,to_char(sysdate,’yyyy.mm.dd hh24:mi;ss’)from dual;
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行。
有时在输出一些结果时,可能需要加一些标题,如表上面的顶标题,落款等。这样的要求可由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
我们可以用TTITLE、BTITLE、COLUMN、BREAKON、COMPUTE SUM及SET LINESIZE、SET PAGESIZE、SETNEWPAGE来设置查询结果的显示格式;在用 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
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 enameheading ‘姓名’ for a12
SQL>COL sal heading ‘工资’for a999,999.99
SQL>COLhiredate heading ‘出生’
SQL>SET LINESIZE 200
SQL>SET PAGESIZE 60
SQL>SPOOL c:\all_emp
SQL>selectename,sal,deptno,hiredate from emp order by deptno;
SQL>SPOOL OFF
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');
输入 usr 的值: sys
原值 2: Where USERNAME = upper('&usr')
新值 2: Where USERNAME = upper('sys')
SID SERIAL# USERNAME COMMAND
---------- ---------------------------------------- ----------
7 26 SYS 3
在变量说明中,可以使用多个变量,比如:
Alter systemkill session ‘&sid,&ser’;
或
Alter systemkill 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 ?
SQL> selectsid,serial#,username from v$session where username='?usr';
输入 usr 的值: SYS
原值 1: select sid,serial#,username fromv$session where username='?usr'
新值 1: select sid,serial#,username fromv$session where username='SYS'
SID SERIAL# USERNAME
-------------------- ------------------------------
7 26 SYS
次时由于我们修改了会话环境的参数值,可以用下面命令查看:
SQL> show define
define "?"(hex 3f)
在ORACLE数据库系统中,表是数据库的基本对象,与桌面数据库中的文件类似,我们可以把所有的基本实体都看成为表,不管应用中的表有多复杂,都可以使用(拆成)一个或多个表来表示。用以存放实体的数据。下面针对建表所需要的知识作简单的介绍。
建立表结构是每个应用系统都必须进行的工作。由于建立表结构是一项统一规划和统一设计的工作。应该是由总设计师根据用户的具体应用需要来定。表的设计是否合理关系到应用系统将来的成败与性能问题。因此,任何担当总设计师角色的人都不要轻视这项工作。
由于创建表的命令非常长,这里仅给出一些主要的部分,详细的请参考《ORACLE8i SQL REFERENCE》 。
CREATE TABLE 命令简要语法如下:
CREATE TABLE [USER.]table_name
( { COLUMN1 DATATYPE
[DEFAULT EXPN][COLUMN_CONSTRAINT] |TABLE_CONSTRAINT }
[, { COLUMN1DATATYPE
[DEFAULT EXPN][COLUMN_CONSTRAINT] |
TABLE_CONSTRAINT }]... )
[CLUSTER CLUSTER(COLUMN1 [,COLUMN2] ...) ]
[PCTFREE N]
[PCTUSED N]
[INITRANS N]
[MAXTRANS N]
[STORAGE N]
[TABLESPACETABLESPACE]
[ ENABLE | DISABLE]
[ AS QUERY]
其中:
schema 包括基表的模式(缺省:当前用户的帐号)
table_name 表名
column 列名(字段名),ORACLE7最多254列,ORACLE8可达1000个列。
datatype 列数据类型
DEFAULT 当前列的缺省值(常数)
Columnconstraint 列约束
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 初级数据库管理〉
例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:在建立表过程中对有限制的列使用NOTNULL:
CREATE TABLECHECKUP_HISTORY
(CHECKUP_NONUMBER(10,0) NOT NULL,
ID_NO NUMBER(10,0),
CHECKUP_TYPEVARCHAR2(30),
CHECKUP_DATE DATE,
DOCTOR_NAMEVARCHAR2(50));
本例除了要求CHECKUP_NO非空外,其它无任何限制.
例3:在建立表时指定列CHECKUP_TYPE为外部列:
CREATE TABLESEAPARK.CHECKUP_HISTORY
(
CHECKUP_NONUMBER(10) NOT NULL,
ID_NO NUMBER(10,0),
CHECKUP_TYPEVARCHAR2(30),
CHECKUP_DATE DATE,
DOCTOR_NAMEVARCHAR2(50),
FOREIGN KEY(CHECKUP_TYPE) REFERENCES
SEAPARK.CHECKUP(CHECKUP_TYPE),
PRIMARY KEY(CHECKUP_NO)
)
PCTFREE 20
PCTUSED 60
INITRANS 2
MAXTRANS 255
STORAGE ( INITIAL1250K
NEXT 2K
MINEXTENTS 1
MAXEXTENTS 121
Pctincrease 0)
TABLESPACE user_data;
例子指定了所有者,主键,外部键,表空间及存储参数等,主键和外部键在后面章节介绍。
Oracle现在可以使用 CREATE GLOBAL TEMPORARY TABLE命令来实现建立临时表结构。这样的表它的数据只在用户会话期间存在,当会话完成后就自动清除。看下面例子:
SQL> create global temporary table myemp as select * fromemp;
表已创建。
SQL> desc myemp
名称 空? 类型
------------------------------------------------- --------------
ENAME VARCHAR2(20)
SAL NUMBER(9,2)
DEPTNO NUMBER(4)
TEL VARCHAR2(20)
SQL> select *from myemp;
未选定行
SQL> insert intomyemp values('赵元杰',32456.99,10,'12');
已创建 1 行。
SQL> select *from myemp;
ENAME SAL DEPTNO TEL
------------------------------ ---------- ------------------
赵元杰 32456.99 10 12
SQL> connectsys/sys
已连接。
SQL> connectzhao/zhao
已连接。
SQL> l
1* select * from myemp
SQL> /
未选定行
从上面可看出当连接到SYS在连接回来后数据就不存在了。对于临时表,可以用DROP TABLE来删除其结构。如:
SQL> drop tablemyemp;
表已丢弃。
修改表结构是对已经创建完成(实际是存放在数据库字典里)的表的结构进行修改。不同的Oracle版本允许对表的修改也不一样。新版的Oracle8i可以对表中的列进行删除。
修改表结构的命令由ALTERTABLE来完成。该命令的参数较多,下面仅给出一些基本的部分。详细请参考《ORACLE8i SQLREFERENCE》 。
ALTER TABLE [user.] table
[ADD ({colum_element|table_constraint}
[,{column_element|table_constraint}]...)]
[MODIFY(column_element[,column_element]...)]
[DROP CONSTRAINT constraint]...
[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及以后版本)。
例1:对已经存在的表增加一新的列:
SQL>alter table dept add ( headcount number(3) );
例2:对表的列修改其大小:
SQL>alter table dept modify( Dname char(20) );
如果被修改的列没有空(已有数据),则被提示:
ORA-01439: Column tobe modified must be empty to change
datatype
ORA-01441: Column tobe modified must be empty to decrease
column length
例3:复制一个表:
CREATE TABLE HOLD_TANK AS SELECT TANK_NO, CHIEF_CARETAKER_NAME
FROM TANK;
例4:参照某个已存在的表建立一个表结构(不需要数据)
create table emp2 asselect * from emp where rownum<1;
例5:修改已存在表存储参数:
Alter table emp2 storage( next 256k pctincrease 0 );
例6:删除表中的列:
这是Oracle8i的新功能,它的基本语法为:
ALTER TABLE . .. . . . DROP COLUMN [ CASCADECONSTRAINTS ];
如:
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允许用户对表的结构进行修改。但建议你在工作中不要采用方式。因为表结构被多次修改会影响应用系统的性能。
Oracle提供DROP TABLE命令可以实现删除表数据和结构。提醒初学者,不要轻易使用DROP TABLE命令。DROP TABLE 命令语法:
DROP TABLE[user.]table_name[CASCADE CONSTRAINTS]
CASCADE CONSTRAINTS表示所有指向本表的主键,外部键被删掉。当删除一个表时,下面的对象也随之被删掉。
l 表的索引;
l 指向本表的外部键;
l 本表的触发器;
l 本表中的分区;
l 本表的快照;
l 本表的角色和用户权限;
l 加在本表的所有限制。
提示:如果你在定义表结构时,采用了主键、外部键来定义了一序列表。则在删除表结构时要小心。不要轻易用CASCADE子句。
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),
hiredate date,
sal number(7,2), /* 工资 */
comm number(7,2), /* 奖金 */
deptno number(2),
CHECK ( sal+comm >0 and sal+comm<=5000)
);
建议:在设计数据库表结构时,建议你分析用户的数据的取值范围,从而将那些取值范围一定的字段用CHECK进行描述。以保证以后数据的正确性。
对于特殊的需要,可以考虑将表创建成为不需恢复(UNRECOVERABLE)的表。如复制一个已存在的表就可以采用这种方法以减少系统的开销。如:
例:参考emp表创建一个新的emp_new 表:
SQL> create table new_emp as select * from emp UNRECOVERABLE;
表已创建。
或
CREATE TABLEnew_emp AS select * from emp NOLOGGING;
注:虽然上面提到UNRECOVERABLE,但是Oracle推荐你使用NOLOGGING或LOGGING;
最新的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)移动前表所使用的表空间情况:
SQL> selecttablespace_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> altertable emp move tablespace user_data
2 storage(initial 128k next 128k minextents 1 pctincrease 0);
Table altered.
SQL> altertable dept move tablespace user_data
2 storage(initial 128k next 128k minextents 1 pctincrease 0);
Table altered.
SQL> alter tableBONUS move tablespace user_data
2 storage(initial 128k next 128k minextents 1 pctincrease 0);
Table altered.
3)移动后的表及表空间的情况:
SQL> selecttablespace_name,table_name,initial_extent from user_tables;
TABLESPACE_N TABLE_NAME INITIAL_EXTENT
------------------------------------------------ ---------------------------
SYSTEM ABC 65536
USER_DATA BONUS 131072
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.
使用ALTER TABLE 加ALLOCATEEXTENT 选项来实现分配一个指定的空间。如:
ALTERTABLE emp
ALLOCATE EXTENT (SIZE 5K INSTANCE4);
前面介绍过,新版的Oracle8I可以删除某个 列。如:
例:从LONG_TAB表中将LONG_PICS列删除掉:
ALTER TABLE LONG_TAB DROP COLUMN LONG_PICS;
可以使用 ALTER TABLE . . . SET UNUSED 语句实现将表中的列设置为不用的状态以达到快速处理的目的。其结果是:
1)在显示结果时看不到该列;
2)不删除该列的数据(但可以将该列删掉);
例:
SQL> select *from emp;
EMPNOENAME JOB MGR HIREDATE SAL COMM DEPTNO
---------- ------------ ----------------------------- ---------------- ------------ ----------- ----------
7369 SMITH CLERK 7902 17-DEC-80 800 20
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> altertable 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)
可以用ALTER TABLE . . .DROP UNUSED COLUMNS 来删除不使用的列。它可以在物理上删除表的未使用的列,并重新声明磁盘空间。在使用该语句时可以在后面加上checkpoint 检查点关键字。它可以产生一个检查点。使用检查点可以在删除数据列的操作过程中减少恢复日志的容量积累,从而避免回滚段的空间消耗。
如:
SQL> altertable emp drop unused columns checkpoint;
Table altered.
注意:删除表中未使用列时不需要指定列名,它是根据alter table emp set unused(comm); 语句来删除未使用的列。
ORACLE 系统提供一个关键字 primary key 来建立一个主键。所谓主键,就是在一个表内该列具有唯一的值。一旦你为一个表的一列或几个列建立了主键,则ORACLE就自动为该表建立一个唯一索引。
要想为表的某个列建立主键,可以用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_deptPRIMARY KEY (deptno)
);
2 用alter table 创建主键
ALTER TABLE[schema.]tablename
ADD (constraint_name PRIMARY KEY (column1 [,column2,...])
例2:
ALTER TABLEPARK_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 时,不能建立相应的外部键。一定先用:
altertable dept enable primary key 后方可使用:
deptno constraint fk_deptnoReferences 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)
);
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一起组成主键,这种两个以上的字段组成的叫组合键(最多16个字段),不要指定过多的组合键以避免出现性能下降.
命令语法详见 altertable 命令
限制: 不许修改作为主键的列;
不许修改作为主键的名字
可以: 可以定义一主键;或使主键无效
ALTER TABLE[schema.]tablename
DISABLEconstraint_name
例1:
Alter table dept
Disable scott.pk_dept;
这样,如果有一外部键依赖于该主键,则系统给出下列错误:
ORA-02297: Cannot disable constraint (scott.pk_dept)-
Depentencies exist.
在这种情况下,必须先删掉依赖于该主键的外部键并使该外部键无效,然后查才能使主键无效。
ALTER TABLE[schema.]tablename
DROP CONSTRAINTconstraint_name [CASCADE]
删除顺序:
1) 使该外部键无效,删掉依赖于该主键的外部键;
2) 使该主键无效,删掉该主键
或:
当在删掉主键命令后加参数CASCADE , 则在删掉主键的同时把依赖于该主键的外部键一起删掉。
DROP INDEX index_name ;
建立外部键是保证完整性约束的一种唯一方法,也是关系数据库的精髓所在。许多曾使用过桌面数据库(如Dbase, Foxpro )的软件人员不太习惯或不使用关系数据库的主键与外部键的方法来设计自己的数据库结构,这是很不好的方法。应该在使用关系数据库中将习惯改过来。否则设计的应用结构和效率就不可能达到用户的要求。
外部键的建立与主键的建立类似,都可以在 CREATE TABLE命令或ALTER TABLE命令中来说明,详细语法见《Oracle SQL reference 》Create table 命令9和Altertable 命令。
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)
);
同样下面语句的效果与上面一样:
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,
Constraint TROUBLE.PK PRIMARY KEY(city,Sampledate)
);
由于ORACLE不允许改变已被定义的外部键的列,也不允许改变外部键的名字,所以你只能用ALTER TABLE 定义一个新的外部键或者使一个已存在的外部键无效:
ALTER TABLE[schema.]table_name
DISABLECONSTRAINT_NAME;
要删除已定义的外部键,要用Alter table 命令中的 DROP 关键字来实现,命令语法见Alter table 命令。
ALTER TABLE [schema.]table_name
DROP CONSTRAINTconstraint_name;
提示:关系数据库的核心主要体现在主键和外部键上。在进行数据库结构设计时,建议要采用主键和外部键来定义那些有关系的表。这样可以保证应用系统数据的完整性和一致性。
索引是关系数据库中用于存放每一条记录的一种对象,主要目的是加快数据的读取速度和完整性检查。建立索引是一项技术性要求高的工作。一般在数据库设计阶段的与数据库结构一道考虑。应用系统的性能直接与索引的合理直接有关。下面给出建立索引的方法和要点。
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]
[PCTFREE n]
[STORAGE storage]
[TABLESPACEtablespace]
[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) /* 零售价 */
);
注:提高查询速度的方法还有在表上建立主键,主键与唯一索引的差别
在于唯一索引可以空,主键为非空,比如:
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)
);
对于较早的Oracle版本,修改索引的主要任务是修改已存在索引的存储参数适应增长的需要或者重新建立索引。而Oracle8I及以后的版本,可以对无用的空间进行合并。这些的工作主要是由管理员来完成。
简要语法结构如下,更详细的语法图见电子文档《Oracle8i Reference 》 中的 Alter index.
ALTER [UNIQUE] INDEX[user.]index
[INITRANS n]
[MAXTRANS n]
REBUILD
[STORAGE n]
其中:
REBUILD 是 根据原来的索引结构重新建立索引,实际是删除原来的索引后再重新建立。
提示:DBA经常用 REBUILD 来重建索引可以减少硬盘碎片和提高应用系统的性能。
例:
alter index pk_detnorebuild storage(initial 1m next 512k);
ALTER INDEX emp_ixREBUILD REVERSE;
Oracle8i 的新功能可以对索引的无用空间进行合并,它由下面命令完成:
ALTER INDEX . . . COALESCE;
例如:
ALTER INDEX ename_idx COALESCE;
当不需要时可以将索引删除以释放出硬盘空间。命令如下:
DROP INDEX[schema.]indexname
例如:
sql> drop indexpk_dept;
注:当表结构被删除时,有其相关的所有索引也随之被删除。
Oracle8i为了性能优化而提供新的创建新类型的索引。这些新索引在下面介绍:
基于函数的索引就是存储预先计算好的函数或表达式值的索引。这些表达式可以是算术运算表达式、SQL或PL/SQL函数、C调用等。值得注意的是,一般用户要创建函数索引,必须具有GLOBAL QUERY REWRITE和CREATE ANY INDEX权限。否则不能创建函数索引,看下面例子:
例1:为EMP表的ename 列建立大写转换函数的索引idx :
CREATE INDEX idx ON emp ( UPPER(ename));
这样就可以在查询语句来使用:
SELECT * FROM EMPWHERE 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)
MGR NUMBER(4)
HIREDATE DATE
SAL NUMBER(7,2)
COMM NUMBER(7,2)
DEPTNO NUMBER(2)
2)没有授权就创建函数索引的提示:
SQL> createindex sal_comm on emp ( (sal+comm)*12, sal,comm)
2 tablespace users storage(initial 64k next 64k pctincrease 0);
create indexsal_comm on emp ( (sal+comm)*12, sal,comm)
*
ERROR at line 1:
ORA-01031:insufficient privileges
3) 连接到DBA帐户并授权:
SQL> connectsys/sys@ora816
Connected.
SQL> grantGLOBAL QUERY REWRITE to scott;
Grant succeeded.
SQL> grantCREATE ANY INDEX to scott;
Grant succeeded.
4)在连接到scott帐户,创建基于函数的索引:
SQL> connectscott/tiger@ora816
Connected.
SQL> createindex sal_comm on emp ( (sal+comm)*12, sal,comm)
2 tablespace users storage(initial 64k next 64k pctincrease 0);
Index created.
1)在查询中使用函数索引:
SQL> selectename,sal,comm from emp where (sal+comm)*12 >5000;
ENAME SAL COMM
-------------------------------------- ----------------
ALLEN 1600 300
WARD 1250 500
MARTIN 1250 1400
TURNER 1500 0
赵元杰 1234.5 54321
反向键索引通过反向键保持索引的所有叶子键上的插入分布。有时,可用反向键索引来避免不平衡的索引。对于反向键索引可以进行下面操作:
l 通过在ALTERINDEX命令后加REBUILD NOREVERSE或REBUILDREVERSE子句来使索引边为反向键索引或普通索引;
l 采用范围扫描的查询不能使用反向键索引;
l 位图索引不能反向;
l 索引编排表不能反向。
例1:创建一个反向键索引:
CREATE INDEX i ON t (a,b,c) REVERSE;
例2:使一个索引变为反向键索引:
ALTER INDEX i REBUILD NOREVERSE;
与普通的索引不一样,索引组织表(Index_Organized Table)是根据表来存储数据,即将索引和表存储在一起。这样的索引结构表(Index_organizedtable—IOT)的特点是:对表数据的改变,如插入一新行、删除某行都引起索引的更新。
索引组织表就象带一个或多个列所有的普通表一样,但索引组织表在B-树索引结构的叶节点上存储行数据。通过在索引结构中存储数据,索引组织表减少了总的存储量,此外,索引组织表也改善访问性能。
由于表中的行与B_树索引存放在一起,每个行都没有ROWID,而是用主键来标识。但是Oracle会“猜”这些行的位置并为每个行分配逻辑的ROWID。此外,你可以为这样的表建立第二个索引。
创建索引结构表也是用CREATE TABLE 命令加ORGANIZATIONINDEX关键字来实现。但是,这样的表在创建完后,你还必须为该表建立一个主键。
例子:
CREATE TABLE IOT_EXPAMPLE
(
Pk_col1 number(4),
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;
Oracle 提供了一种新的类型结构,叫做抽象数据类型。用于定义许多复杂的对象。
1.创建抽象类型的命令语法:
CREATE OR REPLACETYPE [schema.]type_name [IS|AS] OBJECT ( element_list );
详细命令语法见《ORACLE8i SQL REFERENCE》
2.例子:
例:为地址建立一个抽象数据类型 add_type
create type add_typeas object
(
street varchar2(10),--街道名
city varchar2(20), -- 城市名
state char(2), --州代码
zip number --邮编
);
在建立表时使用add_type 数据类型
create tablecustomer
(
name varchar2(20),
address add_type
);
向具有抽象数据类型的表插入数据
insert into customer values
(‘1’,add_type('mystaree','some city','st',10001));
除了 long 能在一行上存储多达2GB的字符和long raw 能存储多达2GB的二进制数据外,ORACLE还提供四种大的数据类型来完善大数据的存储。
下表列出在ORACLE8中可用的数据类型:
LOB数据类型 |
描述 |
BLOB |
二进制LOB,最多为4GB |
CLOB |
字符LOB, 最多为4GB |
BFILE |
二进制文件,存储在数据库之外的只读二进制文件,大小与OS有关 |
NCLOB |
支持多字符集(Multibyte Characters)的CLOB列 |
与LONG数据类型不同,在一个表内可以建立多个 LOB列,如:
Create tableproposal
(
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 /* 与提议有关的封面函件 */
);
由于LOB占用空间较大,所以应该为LOB所在的表制定存储空间。如:
Create tableproposal
(
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( initial1m next 500k pctincrease 0 )
tablespacePROPOSALS;
上面例子是将整个表存储在一个表空间中,为了达到高效目的,可以将LOB列存储在另外的表空间中,如:
Create tableproposal
(
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( initial1m next 500k pctincrease 0 )
tablespace PROPOSALS
LOB(proposal_text,budget) STORE AS
( TABLESPACEproposal_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。
可以有多种方法来检索和操作LOB数据,主要有:
1)通过DBMS_LOB包;
2)使用API(ApplicationProgramming 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 Phillipsfield.’,
EMPTY_BLOB(), NULL);
为了将budget 设置为一个空的定位器值,使用了EMPTY_BLOB函数,如果希望将CLOB数据类型设置为一个空的定位器,则可使用EMPTY_CLOB函数。由于cover_letter 是一个外部存储的BFILE值,所以设置为NULL。
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=’Thisis 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值
可以用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 );
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_textinto 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;
/
当我们创建了表、主键、外部键和索引后,相关的信息就被记录到Oracle的数据字典中,应用系统设计人员、程序人员和数据库管理员,应该了解有关数据字典的基本查询方法.下面给出表和索引有关的数据字典的简单介绍,更详细的内容请参考《Oracle8i/9I数据库管理》。
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 存放表的列的限制信息。
了解数据字典的目的就是查询有关表和索引的信息,下面是简单的查询例子。
例1.查询当前用户的表的基本信息,包括表名、存放的表空间、存储参数:
SQL> selecttable_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_MESSAGESSYSTEM 65536 65536
. . . . . .
例2.查询当前用户的索引的基本信息,包括表名、索引名及表空间、存储参数:
SQL> selectindex_name,tablespace_name,initial_extent,next_extent
2 fromall_indexes where owner=user;
INDEX_NAME TABLESPACE_NAME INITIAL_EXTENT NEXT_EXTENT
------------------------------------------------ -------------- -----------
AQ$_MSGTYPES_PRIMARY SYSTEM 65536 65536
AQ$_PROPAGATION_STATUS_PRIMARYSYSTEM 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
. . . . . .
这里的whereowner=user 表示只查当前用户的索引.
例3.查询当前用户的索引及索引的列名:
SQL> colcolumn_name for a40
SQL> colindex_name for a18
SQL> selectindex_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_PRIMARYAQ$_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> selectowner,constraint_name,table_name from user_constraints;
OWNER CONSTRAINT_NAME TABLE_NAME
-------------------------------------------------- -----------------
ZHAO SYS_C001009 WORKER
ZHAO SYS_C001010 WORKER
SQL> set long1000
SQL> selectSEARCH_CONDITION from user_constraints;
SEARCH_CONDITION
--------------------------------------------------------
age between 18 and 65
例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> colCONSTRAINT_NAME for a12
SQL> selectconstraint_name,table_name,SEARCH_CONDITION
2* from user_constraints;
CONSTRAINT_NTABLE_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行。
视图、同义词和序列是Oracle的常用对象,在Oracle系统安装完成后,就已经建立许多Oracle系统所用的视图、同义词和序列。此外,在应用系统设计中,也经常需要创建视图、同义词和序列来满足应用的需要。下面给出简要介绍。
视图的一个主要目的就是简化用于查询所使用的语句,另外就是可以实现安全和保密的目的。利用视图,我们可以在查询处理中完成复杂的操作。
可以用视图修改表中数据:
l 带有集合操作,如 intersect,union和minus的视图;
l 带有 groupby,connect by,或 start with子句的视图;
l 带有组合功能,如 avg , sum 或 max 功能的视图;
l 使用 distinct 功能的视图。
1 建立视图命令语法:
CREATE [OR REPLACE][FORCE/NO FORCE] VIEW [schema.]view
[column_name1,column_name2] AS query
[WITH OBJECT OID |DEFAULT]
[WITH CHECK OPTION]
[CONSTRAINTconstraint]
[WITH READ ONLY]
OR REPLACE 替换掉原来的视图(不需删除)
FORCE 强行创建一视图,无论视图的基表是否存在或拥有者是
否有权限,但作select、insert、update、delete前条件
必须为真。
Schema 帐户、缺省为当前登录的帐户。
VIEW 视图名
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,CONNECTBY,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;
用户不能往clerk视图中作insert(或update)非'clerk'的记录。
1.用命令删除视图
语法:
DROP VIEW [SCHEMA.]view_name;
如
drop view view_data;
建议:一般视图不占用多少空间,可以不必删除。
2.用SchemaManager 删除视图
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) 视图类型
当视图的状态不可用('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';
Oracle8i版本提供可以创建实体视图(MATERIALIZED VIEW),它确实存放有物理数据。实体视图包含定义视图的查询时所选择的基表中的行。在普通的视图中,Oracle在执行查询时临时进行查询操作来返回结果;而对实体视图的查询是直接从该视图中取出行。
在Oracle9i版本里,对实体视图进行了增强,如提供快速刷新等。下面简单介绍实体视图的使用。
1.关键内容:
使用实体视图需要了解下面几个关键点:
l 实体视图存放有物理数据;
l 实体视图背后的查询只在视图建立或刷新时执行,即如果创建后不进行刷新则只得到创建时的数据;
l 实体视图使用DBMS_MVIEW 程序包中含有刷新和管理实体视图的过程来进行管理;
l 在导出和导入(EXP、IMP)中使用MVDATA参数来实现实体视图数据的导出和导入;
l 使用CREATEMATERIALIZED VIEW 语句创建实体视图;
l 实体视图中的查询表叫主表(master tables)(复制项)或详细表(数据仓库项)。为一致起见,这些主表叫主数据库(master databases.);
l 为了复制目的,实体视图允许你在本地管理远程拷贝;
l 所复制的数据可以使用高级复制特性进行更新;
l 在复制环境下,通常创建的实体视图都是主键、ROWID和子查询实体视图。
2.创建实体视图前提:
l 要有授权创建实体视图的权限(CREATE MATERIALIZED VIEW 或CREATE SNAPSHOT);
l 必须有访问各个主表的权限,即 有SELECT ANY TABLE 的系统权限。
如果在另外的用户模式下创建实体视图,则:
l 需要有CREATE ANY MATERIALIZED VIEW或CREATE ANY SNAPSHOT、SELECTANY TABLE 权限;
l 必须有CREATETABLE、SELECT ANY TABLE系统权限。
如果带查询重写有效来创建实体视图,则:
l 主表的主人必须有QUERY REWRITE系统权限;
l 如果你不是主表主人,则必须有GLOBAL QUERY REWRITE系统权限;
l 如果模式主人没有主表,则该模式主人必须有GLOBAL QUERY REWRITE权限。
3.创建实体视图语法:
下面给出Oracle9i版本的实体视图的创建语法:
CREATE MATERIALIZEDVIEW [schema.] materializede_view
[ OF [schema .]object_type ]| [(scoped_table_ref_constraint)] |
ORGANIZATION_INDEXindex_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 ] QUERYREWRITE ] ]
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] ]
[ INCLUDINGcolumn_name ] OVERFLOW [ segment_attribute_clause]
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 PREBUILTTABLE 此项可以使你以原初始化实体视图(preinitializedmaterialized view)来注册一个存在的表。这对于大表来说非常有用。它有下面限制:
l 每个列的别名必须与表的列名一样;
l 如果使用ONPREBULT TABLE,则不能对列再指定 NOT NULL。
WITH REDUCED PRECISION 允许指定表或实体视图精度可以丢失。实体视图的列不能与子查询所返回的精度一致。
WITHOUT REDUCED PRECISION 表示不允许指定表或实体视图精度可以丢失。实体视图的列要与子查询所返回的精度一致。这是缺省值。
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 ONCOMMIT
BUILD IMMEDIATE
AS SELECT t.month, p.prod_name, SUM(f.sales) ASsum_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)
ENABLE QUERY REWRITE
BUILD IMMEDIATE
REFRESH COMPLETE
AS SELECT t.month, g.state, SUM(f.sales) ASsum_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) ASsum_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 表的视图:
CREATEMATERIALIZED VIEW sales.orders FOR UPDATE
ASSELECT * FROM [email protected] o
WHEREEXISTS
(SELECT* FROM [email protected] c
WHEREo.c_id = c.c_id);
例6.主键的实体视图:
下面语句创建一个主键实体视图human_genome:
CREATE MATERIALIZED VIEW human_genome
REFRESH FAST START WITHSYSDATE NEXT SYSDATE + 1/4096
WITH PRIMARY KEY
AS SELECT * FROM genome_catalog;
例7.ROWID实体视图:
下面语句创建一个ROWID实体视图emp_data:
CREATEMATERIALIZED VIEW emp_data REFRESH WITH ROWID
ASSELECT * 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中的职工表:
CREATEMATERIALIZED VIEW all_emps
PCTFREE5 PCTUSED 60
TABLESPACEusers
STORAGEINITIAL 50K NEXT 50K
USINGINDEX STORAGE (INITIAL 25K NEXT 25K)
REFRESHSTART WITH ROUND(SYSDATE + 1) + 11/24
NEXTNEXT_DAY(TRUNC(SYSDATE, ’MONDAY’) )+15/24
ASSELECT * 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来刷新实体视图:
CREATEMATERIALIZED VIEW sales_emp
REFRESHFAST START WITH SYSDATE NEXT SYSDATE + 7
USINGMASTER ROLLBACK SEGMENT master_seg
LOCALROLLBACK SEGMENT snap_seg
ASSELECT * FROM bar;
1.创建实体视图日志的目的
使用CREATEMATERIALIZED VIEW LOG语句可以创建实体视图日志。实体视图日志是一个包含有主表和实体视图的表。这些快照(snapshot)和实体视图(materializedview)其实都是同义词。它们都引用一个或多个包含查询结果的表,这些表可以是本地数据库或远程数据库的表。
DML的改变是由主表的数据组成的,Oracle在实体视图日志里存储那些改变行的描述,然后使用实体视图日志去刷新基于主表的实体视图,这个过程叫快速刷新。如果没有实体视图日志,Oracle必须重新执行实体视图查询,这个过程叫完全刷新。通常快速刷新要比完全刷新用的时间少。
一般,实体视图日志与模式中的主表放在一起。你需要为每个主表建立实体视图日志。因为Oracle 要使用这个实体视图日志来进行快速刷新。
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 PRIMARYKEY;
例2.建立仅包含更新行主键的实体视图日志
Oracle可以用实体视图日志在任何简单主键的实体视图中来执行一个快速刷新。下面语句建立一个只包含更新行主键的实体视图日志:
CREATE MATERIALIZED VIEW LOG ON emp
PCTFREE 5
TABLESPACE users
STORAGE (INITIAL 10K NEXT 10K);
下面语句建立一个只包含更新行主键的实体视图日志:
CREATE MATERIALIZED VIEW LOG ON sales WITHROWID, 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, dNUMBER);
CREATE MATERIALIZED VIEW LOG ON agg
WITH ROWID (u,a,b,c,d)
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;
1.修改实体视图目的
实体视图是Oracle的一个数据库对象。它包含有一个或多个表的查询结果。使用
ALTER MATERIALIZED VIEW 可以对已经存在的实体视图进行修改。修改方法如下:
l 修改存储特性;
l 修改刷新方法、模式及时间
l 改变实体视图的结构以使它有不同类型;
l 使查询重写有效。
2.修改实体视图命令语法
ALTER MATERIALIZEDVIEW [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 INDEXphysical_attribute_clause |
MODIFYscoped_table_ref_constraint |
REBUILD |
Refresh_cluse
]|
[
[ DISABLE | ENABLE ]QUERY REWRITE |
COMPILE |
CONSIDER FRESH
]
详细见《Oracle9iSQL 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 SEGMENTmaster_seg;
ALTER MATERIALIZED VIEW sales
REFRESH USING DEFAULT MASTER ROLLBACK SEGMENT;
例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;
ALTER MATERIALIZED VIEW LOG
1.修改实体视图日志目的
使用 ALTER MATERIALIZEDVIEW LOG 可以对已经存在的实体视图日志进行修改。可以修改存储特性、刷新模式、时间或已经存在实体视图日志的类型。
2.修改实体视图日志命令语法
( 创建实体视图日志命令语法 见《Oracle9iSQL Reference 》 )
3.修改实体视图日志命令例子
例1:修改扩展次数:
ALTER MATERIALIZED VIEW LOG ON dept
STORAGE MAXEXTENTS 50;
例2:修改已经存在的ROWID:
ALTER MATERIALIZED VIEW LOG ON sales
ADD PRIMARY KEY;
要在应用中使用实体视图,除了要实体视图的语句外,还需要进行数据库实例的初始化参数。并重新启动数据库实例才能使所写的实体视图有效。下面是操作步骤:
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 WITHSYSDATE NEXT round(SYSDATE + 16/24)
AS SELECT deptno,sum(sal)
from emp group by deptno;
实体化视图已创建。
22:29:28 SQL> create materialized viewlog on emp pctfree 5 tablespace users;
实体化视图日志已创建。
SQL> select * from emp_stat;
DEPTNO SUM(SAL)
---------- ----------
10 14116
20 54537
30 9400
SQL> altermaterialized 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点半(startwith 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
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 materializedview emp_stat
refresh complete
start withtrunc(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>
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 empvalues(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.停止实体视图的自动运行
序号是一个发布唯一数字的ORACLE 对象,在需要时,每次按1或一定增量增加。序号通常用于产生表中的唯一主键或唯一索引等。
建立序号可以在SQL*PLUS 中用命令来完成,也可以使用SchemaManager 工具来完成。
1. 命令语法:
CREATE SEQUENCE[user.]sequence
[INCREMENT BY{1|integer}]
[START WITH integer]
[MAXVALUEinteger|NOMAXVALUE]
[MINVALUEinteger|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;
3. 修改序号
有时需要对已建立的序号进行修改,比如在系统移植或升级时可能有的序号已经增长到某个值。现在需要从原先停止的地方开始等。
例2:修改sequence
Alter sequence emp_sequence
Increment by 1
Maxvalue 10000
Cycle
Cache 20;
建立序号的目的就是使用序号,使用序号主要是在插入和查询时使用。
例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 。
当不再使用时就可以删除序号,删除序号有两种方法:
1. DROP SEQUENCE [Schema.]seguence_name;
2. 使用 Schema Manager 工具;
同义词可以使多个用户使用同一个对象而不用将模式(Schema )作为前缀加在对象的前面,从而简化授权方面的操作。同义词有公有和私有两种。
要建立同义词,首先要有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 GeneratingScript To Drop User
set term off
SPOOL create_syn.sql
select 'drop publicsynonym '||object_name||' ;' from user_objects;
select ' createpublic synonym '||object_name||
' for sale.'||object_name||' ;' fromuser_objects;
SPOOL OFF
Start create_syn.sql
注意:当创建同义词后,还要将该同义词授权给public ,才能使其他的Oracle用户可以访问该同义词。
同义词数据字典:
DBA_SYNONYMS实例中所有同义词
USER_SYNONYMS(=SYN)用户的同义词
DROP PUBLIC synonym[schema.]synonym ;
Drop synonym emp;
例1:为当前所有对象建立同义词。为了省去编辑,可用下面个命令来完成:
* 需具有 dba, -- create any synonym,drop anysynonym 权限
select 'drop publicsynonym '||object_name||' ;' from user_objects;
select ' createpublic synonym '||object_name||
' for sale.'||object_name||' ;' fromuser_objects;
当我们创建了视图、同义词和序列后,相关的信息就被记录到Oracle的数据字典中,作为程序人员和数据库管理员,应该了解有关数据字典的基本查询方法.
与视图、同义词和序列有关的数据字典有:
l DBA_VIEWS –实例中所有的视图的基本信息;
l DBA_SYNONYMS–实例中所有的同义词;
l DBA_SEQUENCES–实例中所有的序列。
Oracle公司在Oracle7以后的版本提供了许多数据库厂商不能具备的分区和簇的存储管理技术。使用这些技术,可以实现将大的表和索引进行拆分,使得处理速度提高和便于管理。
簇(Cluster)是一组表,如果应用程序中的SQL 语句经常联结两个或多个表,可以把这些表以簇方式进行创建以改善性能。只要我们创建了簇并在创建表时指定到已经创建好的簇中,ORACLE 就把簇中的表存储在相同的数据块中,并且各个表中的相同的列值只存储一个。
簇(Cluster)就是将一组有机联系的表在物理上存放在一起并且相同的关键列的值只存储一份,用于提高处理效率的一项技术。如下图所示( 见Oracle8i concept ):
|
1.何时建立簇
如果通过引用完整性把两个或多个表联系起来并经常使用联结,则为这些表创建一个索引簇。如果一个表的多行经常与一个非唯一的列一起查询,则为该列创建一个单表簇,该列作为簇关键字,以提高性能。
2.有时簇会损害性能
对频繁更新或删除的表使用簇对性能有不利的影响。
3.限制:
l 簇中的每个表必须有一列与簇中指定的列的 大小和类型匹配;
l 簇码中可用列的最大数目是16,即一个簇最多有16列作为簇码;
l 列的最大长度为239字节;
l LONG 和LONG RAW 不能作为簇列码。
1.创建簇语法
CREATE CLUSTER cluster
( columndatatype[,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 clusteremp_unit;
create clusteremp_unit(acc_no varchar2(15))
tablespace user_data
storage(initial 1mnext 1m maxextents 121 pctincrease 0 );
/
create indexunit_inf_ind on cluster emp_unit
tablespaceuser_indx;
/
/******************************************************************/
/* 创建单位信息表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_cotectvarchar2(10) , -- 经办行联系人
bank_tel varchar2(15) , -- 经办行电话
enter_stampvarchar2(40) , -- 填报单位章
enter_date date , -- 填报日期
center_datedate , -- 中心盖章日期
status_code char(1) , -- "0未缴存","1缴存","2封存","3销户"
oper_no varchar2(10),-- 操作员
unit_pay_ratenumber(7,4) ,-- 单位缴交率
per_pay_rate number(7,4) -- 个人缴交率
)
cluster emp_unit ( acc_no ) ;
/
prompt 建立 单位开户登记 唯一键: acc_no_in
create unique indexunit_inf_in on unit_inf ( acc_no )
storage ( initial 1Mnext 512k maxextents 121 pctincrease 0 )
/
/******************************************************************/
/* 创建单位职工汇缴信息表pay_lst_det,并指定到 emp_unit 簇 */
/* 并为表pay_lst_det创建相应唯一索引pay_det_in1 */
/******************************************************************/
prompt 建立开户单位汇缴清册( pay_lst_det )
drop tablepay_lst_det;
create tablepay_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_rateNumber(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 ( initial10M next 2m maxextents 121 pctincrease 0 )
/
create unique indexpay_det_in2 on pay_lst_det( emp_acc_no )
storage ( initial 1Mnext 512k maxextents 121 pctincrease 0 )
/
在用户具有 ALTER ANY CLUSTER 的权限情况下,可以对已建好的簇(CLUSTER )改变其设置,如:
l 物理属性:PCTFREE,PCTUSED,INITRANS,MAXTRANS和STORAGE;
l 为CLUSTER关键字值存储所有行所需的一般空间容量;
l 缺省平行度。
命令语法:
ALTER CLUSTERCluster_name
{ PCTUSED integer
| PCTFREE integer
| SIZE integer
| INITRANS integer
| MAXTRANS integer
| STORAGE Cluase
}
例:ALTERCLUSTER emp_dept
PCTFREE 30
PCTUSED 60;
对于用ALTER TABLE语句只能改变表中非簇列的设置,不能对簇列进行任何的修改。
只要用户具有 DROP ANY CLUSTER权限均可以对所有的CLUSTER进行删除。
语法如下:
DROP CLUSTER[user.]cluster [INCLUDING TABLES]
如果使用INCLUDING TABLES 则删除 CLUSTER 的同时也删除所包含的表。簇表可以被单个删除而不影响该表所属的簇、其他簇表或者簇索引。删除一个簇表如同删除一个普通的表一样都可以用DROP TABLE 来完成。
注意:当用户从簇中删除单个表时,ORACLE单独删除表中的每一行。删除整个簇的最有效的方法是使用带有 INCLUDING TABLE 选项的DROP CLUSTER语句删除包含所有表的簇。只有当用户仍想保留簇中其它表时才会使用DROP TABLE从簇中删除单个表。
一个簇的索引可以被删除而不影响表的数据,但是当簇的索引被删除后,属于该簇的表就变为不可用,所以当删除簇的索引后还须再建立该簇的索引才行。有时为了消除盘空间的碎片我们常进行删除簇索引操作。删除索引命令见 DROP INDEX 命令。
当应用在设计时使用了簇,则用户或数据库管理员都可以通过查询簇的信息来了解簇的情况,从而进行必要的管理。使用下面命令可以收集属于用户本人的簇信息:
l DBA_CLU_COLUMNS或USER_CLU_COLUMNS
l DBA_CLUSTERS或USER_CLUSTER
DBA_CLU_COLUMNS 存放有系统实例中所有簇的数据情况。它的结构如下:
SQL> descdba_clu_columns
名称 空? 类型
------------------------------------------------- ---------------
OWNER NOT NULLVARCHAR2(30)
CLUSTER_NAME NOT NULLVARCHAR2(30)
CLU_COLUMN_NAME NOT NULLVARCHAR2(30)
TABLE_NAME NOT NULLVARCHAR2(30)
TAB_COLUMN_NAME VARCHAR2(4000)
其中:
OWNER 创建簇的主人
CLUSTER_NAME 簇的名字
CLU_COLUMN_NAME 簇中的列名
TABLE_NAME 与之相关的表名
TAB_COLUMN_NAME 表中的列名
DBA_CLUSTERS 数据字典存放有簇的详细数据情况,包括存储参数等。结构如下:
SQL> descdba_clusters
名称 空? 类型
------------------------------------------------- --------------
OWNER NOT NULLVARCHAR2(30)
CLUSTER_NAME NOT NULLVARCHAR2(30)
TABLESPACE_NAME NOT NULLVARCHAR2(30)
PCT_FREE NUMBER
PCT_USED NOT NULLNUMBER
KEY_SIZE NUMBER
INI_TRANS NOT NULLNUMBER
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/9Ireference》。
此外,你还可以用ANALYZE命令来分析某个簇的数据情况,ANALYZE 命令语法如下:
ANALYZE CLUSTERCluster_name
{ COMPUTE STATISTICS
| ESTIMATESTATISTICS
| DELETE STATISTICS
| VALIDATE REFUPDATE
| VALIDATE STRUCTURE
| LIST Chained ROWINTO table_name
}
例:ANALYZECLUSTER students COMPUTE STATISTICS;
当然我们可以从数据字典中查询所统计的结果,如:
SELECTAVG-BLOCKS_PER_KEY,INSTANCES,CACHE,BUFFER_POOL
FROM USER_CLUSTER
WHERE CLUSTER_NAME=’STUDENT_DEPT’;
小结:
l ORACLE8 可以对表及其各自的索引建立簇;
l 可以对基于主键的簇和基于哈希函数建立簇;
l 簇码只能存储一次;
l 簇如果正确使用可以涉及复杂的操作和降低磁盘I/O;
l 簇索引必须在任何簇表装入数据之前创建;
l 只对使用等号操作符的查询表和表的大小相对静态使用哈希簇;
l 建立簇时,可以用 STORAGE 参数分配来优化簇的性能。
现代企业运行的数据库一般都达几个 GB数据量。我们把这写数据库称为超大型数据库(VLDB=Vary LargeDatabase)。ORACLE 公司从 ORACLE7 开始就提出了分区的方法。到ORACLE8后,分区技术已经提供了非常完善的功能。为大型应用系统提供了可能。
oracle8i分区选项可以对超大规模数据库(VLDB=Vary large databast)进行分区、使之可以达到下面目的:
l 增强可用性,如果表的一个分区由于系统故障或者维护而得不到使用时,表的其余部分仍是可用的
l 减少关闭时间,如果系统故障只影响表的某部分,那么只有这部分需要修复,因此修复工作量减少,所以更快地完成
l 维护轻松,如果需重新连表,那么独立地管理而不是单个大型表的操作要轻松得多。
l 均衡的I/O,可以把不同分区映射到磁盘以平衡I/O并显著改善性能。
l 改善性能,对已分区对象的某些查询可以运行更快,因为搜索仅限于关心的分区。
|
表和索引分区的示意图
不是所有表都可以被分区,下面是不可分区的情况:
l 存在于oracle8簇(cluster)中的表不能被分区
l
l 如果一个表包含非结构性数据,则这个表不能被分区,下面的数据类型就不能进行分区:
l 1)LOBS
l 2)LONG RAW
3)对象类型
l 索引组织的表不能被分区。
ORACLE 提供了对表或索引的三种分区方法:
l 范围分区;
l 散列(hash)分区;
l 复合分区。
1.范围分区方法
根据表中列值的范围进行分区,如一年中的月份,当数据在范围内均匀分布时,性能最好,否则应考虑其它的分区方法。
当创建范围分区时,要考虑:
l 分区方法;范围
l 分区列
l 分区中说明指定分区边界
2.使用散列分区
如果数据不容易进行范围分区,而出现性能原因时就要进行散列分区。
3.复合分区法
复合分区的分区数据使用范围分区法,而在每个分区或子分区内使用散列分区。
1.范围分区法
1)表的单列分区
create tablestudents
(
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
可以用oracleschema Manager工具查看表的分区结果。
注:如果划分有空值,应指定MAXVALUE,这样oracle8i将具有空值的列排到大于其它分区值之后,但此MAXVALUE小。
2)表的多列分区
oracle8i把多列分区码值作为向量来决定一行应放在哪个分区,如:
例1:
create tablestudents
(
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_id,student_Dept_id)
partitionDept_id_1 values lessthan(1000,100)tablespace om1,
partitionDept_id_2 values lessthan(2000,250)tablespace om2,
partitionDept_id_3 values lessthan(3000,500)tablespace om3,
partitionDept_id_1 values lessthan(4000,750)tablespace om4,
partition Dept_id_1values 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 NOTNULL,
sale_month INT NOTNULL,
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设备上进行散列分区,使得这些分区在大小上一致。
建立散列分区,需要指定下面信息:
l 分区方法:散列;
l 分区列;
l 分区编号或各个分区的说明。
使用 CREATE TABLE 语句加PARTITIONBY HASH 子句可以指定所建的表被散列分区。
下面例子创建一个散列分区。分区列为ID,创建了四个分区并分配了由系统生成的分区名,它们被放置在四个被命名的表空间gear1,gear2,gear3,gear4上。
例1:
CREATE TABLEscubagear
( id NUMBER,
name VARCHAR2(60)
)
PARTITION BYHASH(id)
PARTITIONS 4
STORE IN (gear1,gear2,gear3,gear4);
散列分区表的每个分区内保存在不同的节中,且散列数据被放在缺省表空间中。
例2:
CREATE TABLE (deptno NUMBER,deptname VARCHAR2(32))
STORAGE( INITIAL 10k)
PARTITION BYHASH(deptno)
(
PARTITION p1TABLESPACE ts1,
PARTITION p2TABLESPACE ts2,
PARTITION p3TABLESPACE ts1,
PARTITION p4TABLESPACE ts3
);
指定了各个分区的名字及它们所存放的表空间。所有分区都继承表空间的初始分配 INITIAL 10k 参数。
3.复合分区方法
复合分区的分区方法数据使用范围分区,而在每个分区或子分区内使用散列分区法。复合分区对历史数据和带状数据都很理想,并提供范围分区和数据放置的改进的管理性能和散列分区的并行优点。
建立复合分区,须进行:
l 分区方法:范围分区;
l 分区列;
l 指定分区边界的分区说明;
l 子分区方法;散列;
l 子分区列;
l 每个分区的子分区数量或子分区说明。
例:下面例子创建了三个范围分区,每个分区又包含八个子分区,子分区没有名字,所以赋予它们系统生成的名字,“STORE IN”子句将它们分布在四个指定的表空间 ts1,ts2,ts3,ts4中。
CREATE TABLEscubager(equipno NUMBER,equipname VARCHAR(32),price NUMBER)
PARTITION BYRANGE(equipno)SUBPARTITION BY HASH(equipname)
SUBPARTITIONS 8STORE IN ( ts1,ts2,ts3,ts4)
(
PARTITION p1 VALUESLESS THAN(1000),
PARTITION p2 VALUESLESS THAN(2000),
PARTITION p3 VALUESLESS THAN(MAXVALUE)
);
4. 对表分区小结
把表的数据范围(range)进行分区存储;
只需在Createtable或Alter table命令中指定即可;
分区名在Createtable或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 empvalues (1226, ′sa′,′smith′);
Insent into empvalues (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) 指定分区的更新(提高效率)
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]
可以创建两种类型的索引分区:
l 局部索引
l 全部索引
这两种均遵从下列原则:
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 。按照上面对各个分区的进行局部索引的创建,则形象如下图:
|
局部索引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的情况
|
全局索引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
在了解如何建立表分区和索引分区后,在应用设计中还经常进行分区的维护。下面是维护分区的简要介绍。
1.用 ALTER TABLE 语句来维护表分区
维护操作 |
范围 |
散列 |
复合 |
加入分区 |
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 |
如果你在应用系统设计时采用了分区和簇技术,则你最好要了解与簇和分区有关的数据字典。这样对管理有好处。
下面给出的数据字典有三类,分别以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存放大对象类型的分区信息。
了解数据字典的目的是查询它们的信息和管理。下面给出几个常用查询例子。
例1.查询与簇有关的表的信息:
SQL> col owner fora20
SQL> coltable_name for a20
SQL> coltablespace_name for a20
SQL> selectOWNER,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#
SYS FET$ SYSTEM C_TS#
SYS CDEF$ SYSTEM C_COBJ#
. . . . . .
已选择33行。
例2.查询进行过分区的表的信息:
SQL> selectTABLE_OWNER,TABLE_NAME,PARTITION_NAME,TABLESPACE_NAME
2 fromDBA_TAB_PARTITIONS;
未选定行
SQL>
大家都知道,关系数据库中使用最频繁的SQL语句可以是SELECT 、INSERT、UPDATE及DELETE语句了,尽管它们使用简单,但也是变化最多和最能衡量一个编程人员水平的语句了。下面就增、删、改作简要介绍。
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);
INSERT intoemp_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 tableemp_house_fund_sum( per_id verchar2(20), tran_val number(9,2));
SQL> insert intoemp_house_fund_sum
select per_id,sum(tran_val)
From emp_house_fundgrou by per_id;
SQL>selecta.name, b.per_id,b.tran_val
from emp_house_funda,emp_house_fund_sum b
wherea.per_id=b.per_id;
INSERTINTO dept
VALUES(50, ‘PRODUCTION’,’SANFRANCISCO’);
INSERTINTO emp (empno, ename, job, sal, comm, deptno)
VALUES(7890, ‘LINKS’,’CLERK’,1.2E3,NULL, 40);
下面语句完成同样的功能,只是用了子查询:
INSERTINTO (SELECT empno, ename, job, sal, comm, deptno FROM emp)
VALUES(7890, ‘LINKS’,’CLERK’,1.2E3,NULL, 40);
INSERTINTO bonus
SELECTename, job, sal, comm
FROMemp
WHEREcomm > 0.25 * sal
ORjob IN (‘PRESIDENT’,’MANAGER’);
分区的例子:
插入到 SALES表的 OCT98 分区中:
INSERTINTO sales PARTITION (oct98)
SELECT* FROM latest_data;
绑定变量的例子:下面例子将插入结果返回到变量:
INSERTINTO emp VALUES (empseq.nextval, ‘LEWIS’ ‘CLARK’
7902,SYSDATE, 1200, NULL, 20)
RETURNINGsal*12, job INTO :bnd1, :bnd2;
插入 LOB 数据类型的例子:
1)插入一个带 long raw 的表:
CREATETABLE long_tab (long_pics LONG RAW);
2)建立一个带 LOB的表:
CREATETABLE lob_tab (lob_pics BLOB);
3)用下面预计完成将 long raw 插入到 LOB 中:
INSERTINTO lob_tab (lob_pics)
SELECTTO_LOB(long_pics) FROM long_tab;
4)可以将带有long raw 的列删除掉:
ALTERTABLE long_tab DROP COLUMN long_pics;
插入BFILE 的例子:
INSERTINTO emp
VALUES (1, BFILENAME (‘a_dir_alias’, ‘a_filename’);
1. UPDATE语法
UPDATE[user.]table[@db_link][alias]
SET {column1=express1[,column2=experss2]...|
(column1[,column2]...)=(subquery)}
[WHEREcondition|current of cursor];
2.一般的修改
如果起息日为空时以处理日作为该记录的起息日:
SQL>update emp_house_fund set tran_date=sysdate
Whereproc_date=sysdate and tran_date is null;
3. 带null 的修改
SQL>update empset per_id=null where length(per_id)<15 or
Substr(per_id,15,1)> 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类型进行更新。
在Oracle中,可以根据查询结果来更新表的数据。比如,在申请基金项目时,不允许一个人在大学申请项目又在大学的研究所中申请项目,则可使用下面例1的语句来实现检查。
例1:
SQL>update colle_subjectsset app_flag='0'
Where per_id in (select per_id from univ_subjects );
例2:
SQL>updatecomfort set ( noon, midnigt )=
(selecthumiddity,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);
同样可以在更新中使用相关的查询操作,如:
例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
SETp.budgets = p.budgets + 1;
在应用中,可以使用delete 语句实现将不需要的记录进行删除。值得注意的是,经常使用DELETE 语句对表的记录进行有条件的删除。而无条件的全表删除需要一定的技巧。请看下面的例子。
1. DELETE 语法
DELETE [ FROM ][user.]table [@db_link][Alias] [WHERE condition];
这里的condition 可以复杂的表达式或子查询。
2.例子:
SQL> delete fromhouse.emp_house_fund;
SQL>delete fromcolle_subjects
Where per_id in ( select per_id from univ_subjects );
删除语句用的最多应该是有条件的删除记录。如果我们不是有条件的删除的话,我们应该采用直接建立一个新表、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类型
有时我们需要删除大块的数据,在环境比较差的情况下,往往由于回滚段不够大而出现删除失败。这样我们可以采用以下两种方法来达到删除大量数据的目的。
例1:用rownum来限制每次删除的记录数目:
DELETE from emp where deptno=9999 and rownum < 1000;
例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
WHEREROWNUM<20;
COMMIT;
EXCEPTION
WHEN NO_DATA_FOUNDTHEN
EXIT;
END;
END LOOP;
END;
与桌面数据库最大的区别是,所有的关系数据库在事务处理操作中,可以对每个事务进行提交或撤消。当我们在进行insert、update、delete时,都可以根据当前的处理情况来确定目前的操作是提交或撤消。
为了保证在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
当设为imm时,每作一个修改操作均自动提交。
当设n(n为一个整数),当作过n个修改时自动提交。
l 设置为非自动提交:
SQL>setautocommit off
l 设置为自动提交:
SQL>setautocommit 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 wheredeptno=10;
已更新2行。
SQL> rollback;
重算已完成。
我们可以使用 ROLLBACK 命令撤消最近一次所做的操作,要想实现对前面的所有各个操作也要撤消的话,就必须在每个操作命令前设置相应的保留点。当对每个操作都设置了相应的保留点,我们就可以根据需要用ROLLBACK TO xx 来实现撤消到某一步。
l SAVEPOINT命令
SAVEPOINTsavepoint_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 empvalues('John',123.45,20,'56789');
已创建 1 行。
-- 设置第2个保留点b
SQL> savepoint b;
保存点已创建。
--插入第2条记录
SQL> insert into empvalues('Scott',456.78,20,'13601361234');
已创建 1 行。
-- 设置第3个保留点c
SQL> savepoint c;
保存点已创建。
-- 插入第3条记录
SQL> insert into empvalues('赵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命令的前提下才能有效。
在关系数据库中,select 语句是使用最频繁的语句。它的处理复杂程度可依据业务的要求的不同而不同。它是程序员和管理员必需的语句。前面已经进行过介绍,但下面从较为复杂的程度来介绍它的使用情况。
使用SELECT语句和子查询(SUBQUERY)可以从一个或多个表、视图、实体视图中返回数据。
可以将子查询(前面提到的 as subquery )或In 或exists当成 where 的一个条件的一部分,这样的查询称作子查询。
l where中可以包含一个select语句子查询;
l where中可以包含IN, EXISTS 语句;
l 最多可嵌套16层;
l 层数过多会影响性能。
例:比如一个查询是否有专家既以研究所的名义申请基金项目又以大学系为单位申请项目(按规定只能以一个单位来申请):
SQL>select name,per_id,dept_namefrom univ_subjects
Where per_id in ( select per_id from colle_subjects );
招生中,如果所有学生的信息放在 students 表中,而部分有特长的学生在另一个表student_skill 中同样有该学生信息。现在要全部列出所有学生,如果某个学生在表student_skill 中有其特长信息,就显示特长内容,如果某个学生没有特长(在表student_skill中无其特长信息)就显示特长为空:
SQL>selecta.st_id, name, age,skill from students a, student_skill b
Wherea.st_id=b.st_id(+)
Order by a.name;
Students 结构为:
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 跳高
... ...
自我连接是在同一个表或视图内进行条件连接。下面语句返回的是每个雇员的名字及该雇员的经理的名字:
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
JAMES works for BLAKE
MILLERworks for CLARK
连接条件是 e1.mgr =e2.empno
有时需要从多个表中组合具有一种相似类型的信息。Union 可以完成将两个以上的表的相类似的查询结果合并在一起,并且相同的只取其一;如果unionall 则表示返回所有行(不管是否重复)。Intersect返回在两个表中都有相同内容的信息。Minus 则返回只在一个表中出现的信息。
1. 语法:
select ...
union[all]
select ...
select ...
intersect
select ...
select ...
minus
select ...
例:
sql>
select sum(balance) into lf_return from
(
selectsum(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
selectsum(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 namefrom sutdents
intersect
select name from student_skill;
列出没有特长的考生(仅在表students出现):
sql>select namefrom sutdents
minus
select name from student_skill;
许多应用系统都可能有统计等功能,没有经验的开发者可能在开发工具端来写这些语句。比如在POWER BUILDER 中加上复杂的统计与排序等处理。其实,这样很不好。建议把这些复杂语句写成视图更好。下面就介绍几个常用的视图。
例1:
CREATE OR REPLACEVIEW dept_tot as
select a.dname dept,sum(b.sal)total_sal from dept a,emp b
wherea.deptno=b.deptno group by a.dname
例2:
CRATE OR REPLACEITEMTOT AS
SELECTPERSION,SUM(AMOUNT) ITEMTOT
FROM LEDGER
WHERE ACTIONDATEBETWEEN
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;
例:
CREATE VIEW empvi AS
SELECT DEPTNO,SUM(SAL),SUM(COMM)
FROM EMP GROUP BY DEPTNO;
例:
CREATE OR REPLACEVIEW BYITEM AS
SELECTL.persion persion.item,
Amount,
100*amount/itemtotalbypersion, 100*amount/total bytotal
from ledgerl L,iteamtotal I, total
whereL.persion=I.persion
and actiondatebetween
to_date(‘01-MAR-1901’,’DD-MON-YYYY’) and
TO_date(‘31-MAR-1901’,’DD-MON-YYYY’)
And ACTION IN(‘BOUGHT’,’PAID’);
ORACLE 提供了一个有趣的功能 connect by 子句,它可以对具有家族树结构的分枝进行排序。它的用途有 机构或公司的各层结构,财务的科目代码等。
要使用查询遍历,需要在将数据在基表中按照层次结构进行存储。比如一个组织机构就是这样的典型例子。
实现语句:
SELECT column
FROM table_name
START WITH column=value
CONNECT BY PRIOR 父主键=子外键
例1:在ORACLE的EMP 表中,每一条记录都有一个唯一标识当前雇员的empno和标识这个雇员的经理的mgr列。如果mgr 为空,则该雇员是该机构的最顶级。现在要列出每个雇员的层次结构(从顶到底):
select lpad(' ',4*(level-1))||ename name ,empno,mgr fromemp
start with mgr isnull
connect by prior empno=mgr;
NAME EMPNO MGR
-------------------- --------- ---------
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一样。
例2:现在要从某个雇员往他的上级列出该雇员的层次结构(从顶到底):
SQL> col enamefor a30
SQL> l
select lpad('',4*(level-1))||ename ename,mgr,empno from emp
start withmgr=7788
connect by priormgr= empno
SQL> /
ENAME MGR EMPNO
------------------------------ ----- ---------
ADAMS 7788 7876
SCOTT 7566 7788
JONES 7839 7566
KING 7839
例3:现在要列出所有雇员的层次结构(从顶到底):
select lpad('',4*(level-1))||ename name ,empno,mgr from emp
start with mgr isnot 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
KING 7839
38 rows selected.
在SELECT 语句中,当对一个表或视图查询时,语句要求视图是必须存在的。在ORACLE7.2版以后。当该视图不存在时,我们可以在 FROM子句后写上该视图即可。
详细例子如下:
1.假设有下面视图:
CREATE OR REPLACEVIEW TOTAL AS
Select SUM(amount)TOTAL
From ledger
Where actiondatebetween
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是视图):
SELECTPERSON,AMOUNT,100*AMOUNT/TOTAL
From LEDGER,TOTAL
Where actiondatebetween
To_date(‘01-MAR-1901’,’DD-MON-YYYY’) and
To_date(‘31-MAR-1901’,’DD-MON-YYYY’)
And action in(‘BOUGHT’,’PAID’);
3.如果不建立 TOTAL视图,也可以使用下面语句来完成同样的工作:
SELECTPERSON,AMOUNT,100*AMOUNT/TOTAL
From LEDGER,
( select SUM(Amount) TOTAL
from Ledger
Where actiondatebetween
To_date(‘01-MAR-1901’,’DD-MON-YYYY’) and
To_date(‘31-MAR-1901’,’DD-MON-YYYY’)
And action in(‘BOUGHT’,’PAID’)
)
Where actiondatebetween
To_date(‘01-MAR-1901’,’DD-MON-YYYY’) and
To_date(‘31-MAR-1901’,’DD-MON-YYYY’)
And action in(‘BOUGHT’,’PAID’);
这里给出一点不作为一般要求的内容,它虽然不是必需的,但对于应用开发来说很重要。希望Oracle应用设计者把它应用到系统的设计中。
DECODE是Oracle公司独家提供的功能,它是一个功能很强的函数。它虽然不是SQL的标准,但对于性能非常有用。到目前,其他的数据库供应商还不能提供类似DECODE的功能,甚至有的数据库的供应商批评Oracle的SQL不标准。实际上,这种批评有些片面或不够水平。就象有些马车制造商抱怨亨利。福特的“马车”不标准一样。
在逻辑编程中,经常用到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都可以是函数或计算表达式。
Oracle系统中就有许多数据字典是使用decode 思想设计的,比如记录会话信息的V$SESSION数据字典视图就是这样。我们从《Oracle8i Reference》资料中了解到,当用户登录成功后在V$SESSION中就有该用户的相应记录,但用户所进行的命令操作在该视图中只记录命令的代码(0—没有任何操作,2—Insert…),而不是具体的命令关键字。因此,我们需要了解当前各个用户的名字及他们所进行的操作时,要用下面命令才能得到详细的结果:
selectsid,serial#,username,
DECODE(command,
0,’None’,
2,’Insert’,
3,’Select’,
6,’Update’,
7,’Delete’,
8,’Drop’,
‘Other’) cmmand
from v$session whereusername is not null;
数据库中的表是由列和行构成的一个二维表。一般列在任何数据库中都是有限的数量,而行的变化较大,如果表很大,行的数量可能大上千万行。同一列的不同行可能有不同的值,而且不是预先定义的。
除上面描述表具有的一些特点外,有一些表可以看成是不变的或者是较稳定的,比如住房公积金系统是各个单位按照职工的工资数的比例交到本地的经办行中,它的处理流程如下:
例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, --系统日期
oper_id varchar2(10) --操作员代码
这样的表结构,一般按照将经办行作为行进行统计是很容易的,但是如果希望将经办行变为列这样的格式来输出就有困难。如果用DECODE函数来处理则变得很简单:
我们创建一个视图来对目前的pay_lst表进行查询。将经办行代码变为一些具体的经办行名称即可:
CREATE OR REPLACEVIEW 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 BYto_char(tran_date,’yyyy.mm’);
例2.希望将下面的列结果按照列的方式来显示JOB内容:
SQL> selectempno,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.
再看下面的查询结果:
SQL> selectdeptno,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 replaceview 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 orreplace 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 fromemp group by deptno;
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
在许多环境中,都可能需要访问远程数据库。现在的Oracle8i/9I的NET都支持远程访问技术。只要环境网络具备和在参数文件中进行相应的配置就能在SQL语句中进行访问。关于环境的安装和配置另见DBA资料。
Oracle本地要与远程进行连接,要通过数据库链接。
1.使用数据库链接进行查询和更新:
SELECT * fromworker;
这样的语句表示在本地进行查询。而对于远程,则需要在语句后加相应的数据库链接。如:
SELECT * FROM worker@remote_connect;
如果想省去@号后面的字串,可以采用建立一个本地的同义词来实现。如:
CREATE SYNONYMWORKER_SYN for WORKER@remote_connect;
如果希望进行远程更新的话,类似可以在UPDATE语句中加上远程连接符。如:
UPDATE worker@remote_connect
SET lodging=’CRANMER’ where lodging=’ROSEHILL’;
2.创建数据库链接的语法:
创建数据库链接的语法如下:
CREATE [PUBLIC]DATABASE LINK remote_connect
CONNECT TO usernameidentified by password using ‘connect string’;
一般PUBLIC有DBA来创建。个人用户可以不加PUBLIC就是私有的数据库链接。
Oracle系统可以创建链接,但是连接的数量有限制。缺省的并发数是4(由init.ora文件中的OP_LINKS来限制)。
为了建立数据库链接,需要有CREATEDATABASE LINKS 系统权限;要与远程的帐号进行连接还需要有CREATE SESSION普通权限。
CREATE database linkzhao 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)
)
)
在应用系统的生命周期内,为了方便和维护简便,经常采用建立同义词来实现透明的访问。
例1. 没有建立本地透明时的访问:
SELECT * FROMnorth.worker;
例2.建立一个同义词,然后进行访问:
CREATE SYNONYMWORKER FOR NORTH.WORKER;
SELECT * FROMWORKER;
在实际应用中,为了达到隐藏表的所有权,还可以通过使用数据库链接和同义词来隐藏数据的物理位置。通过使用对应远程端的本地表同义词,可以把另一个逻辑层从应用转移到数据库中。
例3.建立一个本地同义词的远程表:
CREATE SYNONYMWORKERSKILL
For WORKERSKILL@remote_connect;
Oracle提供一个伪列user, 它可以在创建视图中使用,从而实现对结果的返回的限制。如:
CREATE OR REPLACEVIEW emp_lst
AS select * from emp
Where ename=user;
这样的视图表示,只有使用者的用户名与ename中的名字一样,才能返回相关的记录。看下面的结果就会明白:
SQL> CREATE ORREPLACE VIEW emp_lst
2 ASselect * 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 769828-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
7844TURNER SALESMAN 7698 08-SEP-81 1500 0 3
7876 ADAMS CLERK 7788 23-MAY-87 1100 2
7934MILLER 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的记录。
如果我们用 CREATETABLE xxx AS select * from tablename@remote_connect; 不能完成带Long等列的操作时,请你使用Oracle提供的COPY命令。COPY可以实现在CREATE TABLE复制表时所不能实现的功能。
COPY命令的语法如下:
COPY { FROMusername[/password]@database | TO
username[/password]@database |
FROM username[/password]@databaseTO
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>setcopycommit m;/* m行提交一次 */
SQL>setarraysize n; /* 批操作的大小 */
例:
COPY from zhao/zhaoyuan@sun450
CREATE WORKER usingselect * from WORKER;
要保证与远程进程连接,DBA必须确保名称服务器配置的正确。另见DBA资料的“NET8 名称服务器”章节。
在Oracle系统中,可以支持对文本进行处理。要想对文本进行搜索,则需要对数据库环境进行设置。
为了在数据库中使用上下文功能,先要设置上下文选项。用以启动数据库上下文处理进程。可以用CTXCTL实用程序来启动上下文服务器:
$CTXCTL
… …
>help
The follwing commands are available:
Help[command] -- 命令信息
Status -- 正在运行的服务器情况
Start n [line |query | ddl | dml ] … --启动n服务进程
Stop pid… | all --停止ctxctl
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 fromCTX-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 toscott;
为了实现上下文的查询,需要在基表的某列建立主关键字和为表中的文本列设置相应的查询策略。比如有下面的求职表:
1.基本的设置:
1)创建基本表:
CREATE TABLE prospect( name varchar2(20),
Address varchar2(40),
Resume long )tablespace user_data
storage(initial 5mnext 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.建立文本索引:
要实现对文本的查询,除了设置参数外,还要用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’;
在CTX_DDL包中提供了一个OPTIMIZE_INDEX过程来重建所有的文本索引。OPTIMIZE_INDEX过程可以对压缩索引中的碎片,并且去掉或删除文本数据项中的引用和其他相关的数据项。OPTIMIZE_INDEX过程的用法如下:
EXEC CTX_DDL .OPTIMIZE_INDEX(‘prospect’);
Oracle8i提供一种新功能叫维(DIMENSION),用于在一对列之间定义一个“父-子”关系,这些列的全部列必须来自同一个表。但是,对于一个列(或层)可以来自不同的表。优化器可以在实体化视图中利用这种“父-子”关系来进行查询改写。
要建立维,你必须有CREATE DIMENSION 系统权限。如果你要在其他的模式下建立维,则需要具有CREATE ANY DIMENSION 系统权限。
注意,在建立完成维后,Oracle系统会自动有效这些维,如果希望对建立的维有效,则需要指定hierarchy_clause和join_clause, 你必须用DBMS_OLAP.validate_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 可以为一个包括多个表的维指定一个内部的等价连接。
attribute_clause
attribute_clause可以指定唯一确定的列。在level中的列必须来自同一个dependent_columns所指的表。在level_clause 中,dependent_columns不需指定。
例如,层次级为:city、state和 country,则city是可以作为市长(mayor),而state可以确定为 州长(governor),而country确定为总统(president)。
下面例子在time_tab表中创建一个维 time 和在CITY、STATE、COUNTRY表中创建维geog
CREATEDIMENSION time
LEVELcurDate IS time_tab.curDate
LEVELmonth IS time_tab.month
LEVELqtr IS time_tab.qtr
LEVELyear IS time_tab.year
LEVELfiscal_week IS time_tab.fiscal_week
LEVELfiscal_qtr IS time_tab.fiscal_qtr
LEVELfiscal_year IS time_tab.fiscal_year
HIERARCHYmonth_rollup (
curDateCHILD OF
monthCHILD OF
qtrCHILD OF
year)
HIERARCHYfiscal_year_rollup (
curDateCHILD OF
fiscal_weekCHILD OF
fiscal_qtrCHILD OF
fiscal_year)
ATTRIBUTEcurDate DETERMINES (holiday, dayOfWeek)
ATTRIBUTEmonth DETERMINES (yr_ago_month, qtr_ago_month)
ATTRIBUTEfiscal_qtr DETERMINES yr_ago_qtr
ATTRIBUTEyear DETERMINES yr_ago ;
CREATEDIMENSION geog
LEVELcityID IS (city.city, city.state)
LEVELstateID IS state.state
LEVELcountryID IS country.country
HIERARCHYpolitical_rollup (
cityIDCHILD OF
stateIDCHILD OF
countryID
JOINKEY city.state REFERENCES stateID
JOIN KEY state.country REFERENCES countryID);
在建立应用系统的各种对象(包括表、视图、索引等)前,就得先确定各个对象与用户的关系。也就是说,哪些用户需要建立,哪些用户都充当什么样的角色,他们应该有多大权限等。下面介绍基本的安全管理方面的内容,更详细的内容在DBA资料里介绍。
CREATE USER usernameIDENTIFIED BY password
Or IDENTIFIEDEXETERNALLY
Or IDENTIFIEDGLOBALLY AS ‘CN=user’
[DEAFULT TABLESPACEtablespace ]
[TEMPORARYTABLESPACE tablespace]
[QUOTA [integerK[M]][UNLIMITED] ON tablespace
[,QUOTA [integer K[M]][UNLIMITED] ONtablespace
[PROFILESprofile_name]
[PASSWORD EXPIRE]
[ACCOUNT LOCK orACCOUNT UNLOCK]
CREATE USER username用户名
IDENTIFIED BYpassword 用户口令
IDENTIFIED BYEXETERNALLY 用户名在操作系统下验证,这个用户名必须与操作
系统中所 定义的用户相同。
IDENTIFIED GLOBALLYAS ‘CN=user’ 用户名是ORACLE 安全域中心服务器来验证
,CN 名字标识用户的外部名。
[DEAFULT TABLESPACEtablespace ] 缺省的表空间
[TEMPORARYTABLESPACE tablespace] 缺省的临时表空间
[QUOTA [integerK[M]][UNLIMITED] ON tablespace 允许使用k[m]字节
[,QUOTA [integer K[M]][UNLIMITED] ONtablespace
[PROFILESprofile_name] 资源文件的名字
[PASSWORDEXPIRE] 立即将口令设成过期状态,用户在登录进入前必须
修改口令。
[ACCOUNT LOCK orACCOUNT UNLOCK] 用户不被加锁。
建立用户虽然不是经常的工作,但却是比不可少的工作。如果你的环境是一个较复杂的应用系统,你还是应该重视用户的建立和管理的事。下面是建立不同类型用户的方法。
外部识别的Oracle用户可以被客户端的操作系统验证,即在Oracle外放置了用于口令管理和用户验证的控制。此类登录不再需要Oracle 口令。操作系统验证的实现需要进行下面步骤:
1. 在INITsid.ORA文件中设置OS_AUTHENT_PREFIX 参数,在Oracle6里必须设置用户的前缀为OPS$。Oracle8可以不需要前缀OPS$。如在INITsid.ORA文件上加:
. . .
OS_AUTHENT_PREFIX=”OPS$”
. . .
2. 用CREATEUSER 建立外部用户:
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;
在Oracle数据库里,可以将用户配置成不需要验证口令的方式,用以替代来自X.509企业目录服务的口令检查。这种类型的用户一般都是在大的企业里的登录使用。一般企业验证启用Oracle安全服务(OSS)来实现单独的注册。建立全局验证的用户需要带 GLOABLLY AS
CREATE USER SCOTT IDENTIFIED GLOABLLY AS ‘CN=scott,
OU=division1, O=sybex, C=US’;
ALTER USER命令用于修改用户的资源限制和口令等。ALTER USER 命令语法如下:
ALTER USER usernameIDENTIFIED BY password
Or IDENTIFIED EXETERNALLY
Or IDENTIFIED GLOBALLY AS ‘CN=user’
[DEAFULT TABLESPACEtablespace ]
[TEMPORARYTABLESPACE tablespace]
[QUOTA [integerK[M]][UNLIMITED] ON tablespace
[,QUOTA [integer K[M]][UNLIMITED] ONtablespace
[PROFILESprofile_name]
[PASSWORD EXPIRE]
[ACCOUNT LOCK orACCOUNT UNLOCK]
[DEFAULT ROLE role[,role]
or [DEFAULT ROLE ALL [EXEPT role[,role]]]or[DEFAULT ROLE NOTE]
例:比如用户使用的资源超出限额的话,就如下提示:
ORA-01536:SPACE QUOTA EXCEEDED FOR TABLESPACE ‘USERS’
这时需要对该用户增加资源限额:
SQLPLUSSYSTEM/MANAGER
SQL>ALTER USERsideny QUOTA 10M ON SYSTEM;
对于不再需要的用户,可以用DROPUSER 来将不要的用户从数据库系统中删除。以释放出磁盘空间。DROP USER语句的语法如下:
DROP USER user [CASCADE]
如果加CASCADE 则连同用户的 对象一起删除。
SQL>drop user zhao cascade;
提示:不要轻易使用 DROP USER 命令。只有在确认某个用户没有保留时才使用该命令。
Oracle提供两个命令(grant和revoke)用于给用户(或角色)进行授权和从用户(或角色)中收回某些权限。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 | PUBLICWITH 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;.
可以使用REVOKE语句从用户或角色中撤消某些权限。REVOKE的语法如下:
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 CASCADECONSTRAINTS
system_privilege: 系统权限或角色
object_privilege:对象的权限,可以是:
l ALTER
l DELETE
l EXECUTE
l INDEX
l INSERT
l REFERENCES
l SELECT
l UPDATE
例:
REVOKE ALTER TABLESPACEFROM john;
REVOKE GRANT ANY ROLE FROMtodd;
REVOKE manager FROM imran;
REVOKE INSERT ON sales FROMjaved;
REVOKE ALL ON marketingFROM terry;.
为了管理复杂系统的不同用户,Oracle系统提供了角色和权限。权限可以使用户能访问对象或执行程序。而角色是一组权限的集合,同样,角色被授予用户后,用户也具有某些权限。Oracle有三种类型的权限:
l 对象权限(Object)
l 系统权限(System)
l 角色(Role)
角色是一组权限的集合。角色包含一个或多个权限;角色可以再包含角色。关于角色的详细描述参考另外的《Oracle8i初级数据库管理》--赵元杰著。
1.建立角色的命令语法如下:
CREATE ROLE role_name
[ NOT INDENTIFIED |
[ INDENTIFIED [BYpassword | EXTERNALLY|GLOABALLY] ]
];
role 指定角色名;
NOT IDENTIFIED 不需口令有数据库验证;
IDENTIFIED 需要口令,分别为三种情况:
l BY password 指定本地用户口令,如果在建立角色时用口令,则用户在使用时也要给出口令。
l EXTERNALLY 指定为外部用户,该用户用外部服务进行验证。
CREATEROLE role
NOTIDENTIFIED
IDENTIFIED
BYpassword
EXTERNALLY
GLOBALLY;
例:
CREATE ROLE vendor IDENTIFIED GLOBALLY;
2.三种标准角色:
自从Oracle6版本以后,Oracle系统一直有三种缺省的角色,即:
l CONNECT ( 连接角色)
具有CONNECT角色用户,可以进行 SELECT ,INSERT,UPDATE和DELETE操作。
l RESOURCE (资源角色)
具有RESOURCE角色的用户可以进行CONNECT所做的工作,此外,还可以进行CREATE TABLE、CREATESEQUENCE、CREATE PROCEDURE、CREATETRIGGER、CREATE INDEX及CREATECLUSTER等。
l DBA(数据库管理员角色)
具有DBA角色的用户可以进行除 RESOURCE外,还可以进行数据库的管理操作。
一旦创建完角色,用户就可以给角色授权。给角色授权的GRANT语句在前面介绍。通过GRANT语句可以对角色授各种权限,如用户对象的访问权,系统权限等。如果用户具有DBA权限的话,则用户有GRANT ANYPRIVILEGE系统权限。可以对角色授予各种权限。如:
GRANT CREATE SESSION TO clerk;
GRANT CREATE SESSION,CREATE Database link tomamager;
如果角色创建完毕并且已经给角色授了相应的权限,用户就可以将角色授权给用户了。这样的操作完成后,被授角色的用户就有了相应的权限。要完成这样的操作,只要操作者具有GRANT ANY PRIVILEGE系统权限就可通过GRANT语句对用户授各种权限。如:
例。假设clerk是一个角色,则可以将它授予用户:
GRANT clerk TO ZHAO;
无论对数据库管理员或是一般的用户,对Oracle有关数据字典的了解程度是衡量是否真正掌握Oracle核心的关键。如果你了解基本的Oracle数据字典,对于各种系统的信息查询将大有好处。下面给出与安全管理有关的数据字典简单介绍。
与用户、角色、权限有关的数据字典主要有:
DBA_USERS 实例中有效的用户及相应信息。
V$SESSION 实例中会话的信息。
DBA_ROLES 实例中已经创建的角色的信息。
ROLE_TAB_PRIVS 授予角色的对象权限。
ROLE_ROLE_PRIVS 授予另一角色的角色。
ROLE_SYS_PRIVS 授予角色的系统权限。
DBA_ROLE_PRIVS 授予用户和角色的角色。
SESSION_ROLES 用户可用的角色的信息。
对于一般的软件人员来说,应该掌握对数据字典的基本查询,如:
例1。查看当前已经创建了多少用户和用户缺省的表空间:
SQL> set line 120
SQL> col usernamefor a26
SQL> coldefault_tablespace for a20
SQL> selectusername,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$UNAUTHENTICATEDSYSTEM 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
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>
下面给出一些对于初学者来是常见问题的一点描述,目的是使那些使用Oracle系统时间不长的人员能尽快适应在Oracle环境下的开发。
下面是一些初学者常遇到的问题的解释。如果你是一位Oracle的老手可以不阅读本章的内容。
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年。
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');
SelectTo_char(Datefld,'DD-MON-YYYY') Datefld from abc;
01-JAN-2011
01-JAN-1990
建议:2000年问题在开发中的建议任何时应采用4位年表示如果用两位一定用YY或RR表示输入界面最好作判断和提示。
许多初学者都可能遇到这样的问题,就是往DATE类型的列插入日期数据时,经常被提示错误。
比如有下面的ABC表结构:
SQL> desc abc
名称 空? 类型
------------------------------------------------- ------------
RQ DATE
NAME VARCHAR2(20)
当用下面命令插入数据到ABC表时,系统提示如下信息:
SQL> insert intoabc values('02-JAN-2002','赵元杰');
insert into abcvalues('02-JAN-2002','赵元杰')
*
ERROR 位于第 1 行:
ORA-01843: 无效的月份
这是由于系统安装时的默认字符集引起的。虽然上面语句看上去没有错误,但是它不符合当前系统的日期格式要求。那么当前系统的日期格式是什么呢?我们可以用下面语句来查询:
SQL> selectsysdate from dual;
SYSDATE
----------
01-2月 -02
既然系统的日期格式是中文的月份,则将上面语句改为中文的月即可:
SQL> insert intoabc values('02-2月-2002','赵元杰');
已创建 1 行。
当然,你可以用altersession命令修改当前系统的日期格式为你喜欢的格式,如:
SQL> altersession set nls_date_format='yyyy/mm/dd';
会话已更改。
SQL> insert intoabc values('2002/02/02','赵元杰');
已创建 1 行。
SQL> select *from abc;
RQ NAME
------------------------------
2002/02/02 赵元杰
2002/02/02 赵元杰
关于日期格式的有关资料,请参见《Oracle8I数据库管理员》--赵元杰著
有时,我们关心的查询结果不是所有的记录,而是关心所查询的内容的存在性。如果我们不加特别的限制,满足条件的所有记录会源源不断地显示在屏幕上。为了只显示少量的内容,oracle提供rownum伪列来限制在查询时返回的记录数。例如:
Select * from dict where rownum < 10
Rownum是要显示的记录数
注意:
l 该用法在PL/SQL和Pro*C中常常不能用 ;
l 在条件中可以用 <= ,但不能用 = 或> 作判断。
在数据库管理操作中,经常需要将某个表的所有记录都删除而只保留表结构,这样的要求如果用delete 进行删除的话,Oracle系统会自动为该操作分配回滚段。如果回滚段较小,则可能导致操作失败。即使回滚段足够大,删除操作也需要较长的时间才能完成。为了加快删除操作,Oracle提供了一个特别的命令TRUNCATE,可以快速地完成对某个表的所有记录的删除。TRUNCATE的语法如下:
TRUNCATE [TABLE | CLUSTER]
schema.[table][cluster] [DROP | REUSE STORAGE]
删除表中或簇中的所有行,REUSE STORAGE保留被删除的空间作为该表的新行使用:缺省为DROP storge 即收回被删除的空间给系统。
特点:不可恢复。即不需rollback segment,不在日志文件中记录信息。
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行.第二个数据文件
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> selectename,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 fromemp where rowid = chartorowid('AAAFyUAADAAAAADAAB');
已删除 1 行。
3)删除操作完成,再查看emp表的数据:
SQL> selectename,sal,deptno,tel,rowid from emp;
ENAME SAL DEPTNO TEL ROWID
---------------------- ---------- -------------------- ------------------
赵元杰 9999.12 10 1360 136 5681 AAAFyUAADAAAAADAAA
从例子中可以看出,rowid的优势,建议在PL/SQL中的循环操作使用ROWID来提高处理速度。
要保证在统计(查询)执行过程中,记录不被其他用户更新,则可以使用For update子句进行加锁。这样在这个锁释放前其他用户不能对这些记录作update、delete和加锁。
SQL>Select daptno from dept
Where deptno=25 For update;
如果你使用了FORUPDATE来对表进行加锁,组必须用commit来释放加锁的记录。
前面介绍的主键的创建方法,如果我们对表创建了主键后,那么在查入记录时,Oracle会自动对插入数据进行唯一性检查,当出现有数据违反唯一性限定的情况时,一般用户可能只看到ORA-0001 Dup_val_on_index ( 试图破坏一个唯一性限制 ) 类似的提示,而没有看是哪条记录违反唯一性限定。为了使用户有针对性地修改违反唯一性限定的记录,Oracle提供了一种方法可以容许用户捕获那些导致限定产生失败的行的信息。方法是:
l 用户生成一个列为EXCEPTION的表,创建该表的脚本是UTLEXCPT.SQL,你可以从oracle.../rdbms/admin目录中找。如:
SQL> startc:\oracle\ora81\rdbms\admin\utlexcpt
表已创建。
l 在建表时声明EXCEPTIONS。
l 激活EXCEPTIONS,如:
Alter table newspaper enable primary key
Exceptions into EXCEPTIONS;
EXCEPTIONS 表有四个列:
Row_ID 违反限定的各行
Ower 违反限定的拥有者
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’;
一般来说,在处理存在性检查中,用户都会看到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;
可以弥补 createtable ... as select ... from ...的和imp,exp 的不足,主要功能有:
1) 从一个本地数据库将一个或多个表拷贝到一个远程数据库;
2) 将一个表的一些记录拷贝到远程或本地库的其它表中;
3) 将包含 long 类型的表的一些列拷贝到其他表中;
4) 从一个oracle 数据库向一个非oracle数据库的拷贝表。
语法如下:
COPY { FROMusername[/password]@database | TO
username[/password]@database |
FROM username[/password]@databaseTO
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>setcopycommit m;/* m行提交一次 */
SQL>setarraysize n; /* 批操作的大小 */
对于编程人员来说,如果对列的空值(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(工资+奖金)来列出结果时,则看到下面的结果:
SQL> selectename,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> selectename,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
缺省情况下,该表在oraclerdbms 中是不建立的,需要时可以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 intoproduct_user_profile
(product,userid,attribute,scope,numeric_value,
char_value,date_value,long_value)
values
('SQL*PLUS','SCOTT','HOST',NULL,NULL,'DISABLE',NULL,NULL);
例2:重新让scott用户使用sql*plus ,则
SQL>delete fromproduct_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
下面给出开发人员在工作中经常遇到的问题的解决方法。这里的所有例子都经过作者的精心调试通过。希望能对那些新手的读者有点帮助。
由于在SQLPLUS 下的缓冲区有限,并且LONG的缺省长度为80 个字符。所以要查询LONG类型的字段时,需要设置 LONG的值为一个合适的值。如:
SQL>set long 3000
SQL>col text for a90
SQL>select text from user_source;
在程序调试过程中,经常需要了解某个语句的执行时间。以选择较好的语句。用下面的设置可以显示每个语句所用去的时间(毫秒,毫秒/1000=秒)。
SQL> settiming on
SQL> selectcount(*) from emp;
COUNT(*)
--------------
14
real: 190
SQL>
实际需要 190/1000=0.19秒
有时由于系统资源紧张或需要进行系统的整理时,都希望将与系统处于连接的用户会话进行终止。可以用下面命令分两步实现:
1)先查询出所有用户的信息:
SQL> selectsid,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 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> selectsid,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> altersystem kill session '&sid,&ser';
Enter value forsid: 13
Enter value forser: 370
old 1: alter system kill session'&sid,&ser'
new 1: alter system kill session '13,370'
System altered.
real: 100
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
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;
有时需要用另外表的数据或本表的数据来修改某些记录。这样的应用在实际中经常使用。以下例子具有代表性:
例1:更新一个字段的情况:
UPDATE DEPT SETDEPT_NAME=(SELECT DEPART_NAME FROM DEPART
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 whereCHP8B.depart_number=CHP8a.dept_no);
有时,我们需要在新的环境创建用户,这些用户来自一个已经存在的应用环境中。比如希望重新创建用户的命令如何来产生。下面的例子从数据字典中查询数据自动完成创建用户、创建角色、授权角色给用户操作。
accept uname prompt'输入希望的用户名: '
spool c:\gen_user
SELECT username,'CREATE USER '||username||' '||
DECODE(password, 'EXTERNAL', 'IDENTIFIEDEXTERNALLY',
'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
可以通过查询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
selectdecode(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
FROMuser_tab_columns t1,user_tab_columns t2
WHERE t1.table_name = t2.table_name and
t1.table_name in (select distinctobject_name from user_objects
where object_type='TABLE')
group byt1.column_id,t1.table_name,t1.data_type,t1.nullable,
t1.data_length,t1.data_scale,t1.column_name,
t1.data_precision
order byt1.table_name,t1.column_id;
例2.从USER_TABLES和USER_TAB_COLUMNS来产生创建表的脚本:
/************************************************************/
/* 功能:自动产生创建表的脚本和相应的存储参数 */
/* 文件名:gen_cre_tab2.sql */
/* 作者:赵元杰 */
/* 日期:2001.12.10 */
/************************************************************/
set linesize 500
set pagesize 1000
set arraysize 8
set feedback off
set heading off
selectdecode(t1.column_id,1,'CRE