1 数据库对象(视图、序列、同义词、索引 都是DDL语句) 2 3 1 视图 4 视图是从一个或几个实体表(或视图)导出的表。它与实体表不同,视图本身是一个不包含任何真是数据的虚拟表。视图最终是定义在实体表之上的,对视图的一切操作最终也要转换为对实体表的操作。 5 有经验的数据库设计人员往往会为开发者将各个复杂的SQL语句封装成一个个独立的视图。 6 --创建视图 7 CREATE [FORCE|NOFORCE] [OR REPLACE] VIEW 视图名称 [(别名1,别名2,...)] 8 AS 9 子查询 ; 10 11 FORCE: 表示要创建视图的表不存在也可以创建视图。 12 NOFORCE:(默认)表示要创建视图的表必须存在,否则无法创建视图。 13 OR REPLACE : 表示视图的替换。如果创建的视图不存在,则创建新的视图;如果视图已经存在,则将其替换。 14 15 --用例1:创建一张基本工资大于2000的雇员信息的视图 16 CREATE VIEW v_myview 17 AS 18 SELECT * FROM emp WHERE sal>2000; 19 20 --用例2: 查看视图是否已经创建 21 SELECT * FROM tab WHERE tabtype='VIEW' and lower(TNAME)='v_myview'; 22 SELECT view_name,text_length,text FROM user_views WHERE lower(view_name)='v_myview'; 23 24 --用例3:替换 v_myview ,创建一张基本工资大于2000的雇员信息的视图, 25 CREATE OR REPLACE VIEW v_myview 26 AS 27 SELECT * FROM emp WHERE sal>2000; 28 29 --用例3:替换 v_myview ,为视图中查询的列起别名 30 CREATE OR REPLACE VIEW v_myview 31 (部门编号,部门名称,位置,人数,平均工资,总工资,最高工资,最低工资) 32 AS 33 SELECT d.deptno,d.dname,d.loc, 34 COUNT(e.empno) count, 35 NVL(ROUND(AVG(sal),2),0) avg, 36 NVL(SUM(sal),0) sum, 37 NVL(MAX(sal),0) max, 38 NVL(min(sal),0) min 39 FROM emp e,dept d 40 WHERE e.deptno(+)=d.deptno 41 GROUP BY d.deptno,d.dname,d.loc; 42 43 --用例4:在视图上执行DML操作 44 UPDATE 视图后,原表会同步更新,缺失字段默认为空。当用户对视图执行删除操作之后,会影响原始数据表中的数据。 但是无法通过多表映射的视图修改多个表。 45 重点: 能否有其他方式可以通过视图同步更新多张数据表? 46 视图如果由多张数据表组成,将无法进行增加及更新的操作。 47 答: 利用触发器完成多表同时更新。 48 49 1.1 WITH CHECK OPTION 子句: 保证视图的创建条件不被修改。 50 在创建视图的时候需要使用WHERE 子句做一些条件限制,但是默认情况下视图创建完成之后,是可以通过视图修改在WHERE子句中所使用的字段内容,此时就需要通过 WITH CHECK OPTION 子句来保证视图的创建条件不被更新。 51 语法:WITH CHECK OPTION 子句 52 CREATE [FORCE|NOFORCE] [OR REPLACE] VIEW 视图名称 [(别名1,别名2,...)] 53 AS 54 子查询 [WITH CHECH OPTION [CONSTRAINT 约束名称]]; 55 56 --用例1: 57 CREATE OR REPLACE VIEW v_emp20 58 AS 59 SELECT * FROM emp WHERE deptno=20 60 WITH CHECK OPTION CONSTRAINT v_emp20_ck; 61 62 1.2 WITH READ ONLY 子句: 创建只读视图,让视图的其他字段无法更新。 63 语法:WITH READ ONLY 子句 64 CREATE [FORCE|NOFORCE] [OR REPLACE] VIEW 视图名称 [(别名1,别名2,...)] 65 AS 66 子查询 [WITH CHECH OPTION [CONSTRAINT 约束名称]] 67 [WITH READ ONLY] 68 ; 69 70 --用例1 71 CREATE OR REPLACE VIEW v_emp20 72 AS 73 SELECT * FROM emp WHERE deptno=20 74 WITH READ ONLY; 75 --READ_ONLY 字段 76 SELECT view_name,text_length,text,READ_ONLY FROM user_views WHERE lower(view_name)='v_myview'; 77 78 1.3 删除视图 79 语法:DROP VIEW 视图名称; 80 81 --用例1: 82 DROP VIEW v_emp20; 83 SELECT view_name,text_length,text,READ_ONLY FROM user_views WHERE lower(view_name)='v_emp20'; 84 85 86 2 序列 87 序列是Oracle 中最为重要的对象,利用序列可以实现数据表流水号(自动增长列)的操作。 88 2.1 序列的作用及创建 89 语法:序列的完整创建语法 90 CREATE SEQUENCE 序列名称 91 [INCREMENT BY 步长] 92 [START WITH 开始值] 93 [MAXVALUE 最大值|NOMAXVALUE] 94 [MINVALUE 最小值|NOMINVALUE] 95 [CYCLE|NOCYCLE] 96 [CACHE 缓存大小|NOCACHE]; 97 98 SEQUENCE 99 100 --用例1:创建默认序列 101 CREATE SEQUENCE myseq; 102 --用例2:查看序列数据字典 103 SELECT * FROM user_sequences; 104 105 字段说明: 106 SEQUENCE_NAME:表示序列的名称,此处的名称为之前创建的MYSEQ。 107 MIN_VALUE:此序列开始的默认最小值(默认是0)。 108 MAX_VALUE:此序列开始的默认最大值(默认是27个9 ,即 999999999999999999999999999)。 109 INCREMENT_BY:序列每次增长的步长,默认是1。 110 CYCLE_FLAG: 循环标记,如果是循环序列则显示Y,非循环序列则显示为N(默认为N)。 111 CACAHE_SIZE:序列操作的缓存量,默认是20 。 112 LAST_NUMBER:最后一次操作的值。 113 序列名称.currval: 表示取得当前序列已经增长的结果,重复调用多次后序列内容不会有任何变化,同时当前序列的大小(LAST_NUMBER)不会改变。 114 序列名称.nextval: 表示取得一个序列的下一次增长值,每调用一次,序列都会增长。 115 116 117 --用例3:通过 nextval 属性操作序列。 118 SELECT myseq.nextval FROM dual; 119 120 --用例4:通过 currval 属性操作序列。 121 SELECT myseq.currval FROM dual; 122 123 --用例5:创建一张 member 表,并使用序列进行ID列的自动增长操作。 124 DROP TABLE member PURGE; 125 DROP TABLE advice PURGE; 126 CREATE TABLE member( 127 mid NUMBER PRIMARY KEY, 128 name VARCHAR2(200) NOT NULL, 129 email VARCHAR2(50), 130 CONSTRAINT uk_email UNIQUE(email), 131 CONSTRAINT pk_mid PRIMARY KEY(mid) 132 ); 133 INSERT INTO member(mid,name) VALUES(myseq.nextval,'XXXX学院'); 134 135 2.2 序列的删除 136 语法: 137 DROP SEQUENCE 序列名称; 138 139 --用例1:删除 myseq 序列 140 DROP SEQUENCE myseq; 141 SELECT * FROM user_sequences; 142 143 2.3 创建特殊功能的序列 144 --用例1:设置序列的增长步长 INCREMENT BY 145 CREATE SEQUENCE myseq INCREMENT BY 3; 146 SELECT * FROM user_sequences WHERE SEQUENCE_NAME='myseq'; 147 148 --用例2:设置序列的初始值 START WITH,创建序列,让其初始值设置为30,每次增长步长为2. 149 一个序列的默认初始值是1,用户在创建序列的时候可以直接通过 START WITH 属性设置。 150 CREATE SEQUENCE 序列名称 START WITH 开始值; 151 152 DROP SEQUENCE myseq; 153 CREATE SEQUENCE myseq 154 INCREMENT BY 3 155 START WITH 30; 156 157 SELECT myseq.nextval FROM dual; 158 159 --用例3:设置序列的缓存 CACHE 缓存大小|NOCACHE, 可能引起跳号的问题。 160 创建序列并由用户设置缓存操作。 161 CREATE SEQUENCE 序列名称 CACHE 缓存大小|NOCACHE。 162 163 --创建序列,缓存设置为100 。 164 CREATE SEQUENCE myseq CACHE 100; 165 166 --创建序列,不设置缓存 。 167 CREATE SEQUENCE myseq NOCACHE; 168 169 SELECT cache_size,last_number FROM user_sequences; 170 171 --用例4:设置循环序列。循环序列指的是一个序列在每次调用 nextval 属性后可以产生指定范围的数据。例如,现在希望一个序列的内容是在1/3/5/7/9 这5个数字之间循环,这就属于循环序列。 172 CREATE SEQUENCE 序列名称 173 [MAXVALUE 最大值|NOMAXVALUE] 174 [MINVALUE 最小值|NOMINVALUE] 175 [CYCLE|NOCYCLE]; 176 177 DROP SEQUENCE myseq; 178 CREATE SEQUENCE myseq 179 START WITH 1 180 INCREMENT BY 2 181 MAXVALUE 10 182 MINVALUE 1 183 CYCLE 184 CACHE 3; 185 186 2.4 修改序列 (不建议修改数据库对象 ) 187 语法: 188 ALTER SEQUENCE 序列名称 189 [INCREMENT BY 步长] 190 [START WITH 开始值] 191 [MAXVALUE 最大值|NOMAXVALUE] 192 [MINVALUE 最小值|NOMINVALUE] 193 [CYCLE|NOCYCLE] 194 [CACHE 缓存大小|NOCACHE]; 195 196 --用例1:修改 myseq 序列 197 ALTER SEQUENCE myseq 198 INCREMENT BY 10 199 MAXVALUE 98765 200 MINVALUE 1 201 CACHE 100; 202 203 SELECT cache_size,last_number FROM user_sequences; 204 205 2.5 自动序列,自动增长序列。 206 语法: 207 CREATE SEQUENCE 表名称( 208 列名称 类型 GENERATED BY DEFAULT AS IDENTITY( 209 [INCREMENT BY 步长] 210 [START WITH 开始值] 211 [MAXVALUE 最大值|NOMAXVALUE] 212 [MINVALUE 最小值|NOMINVALUE] 213 [CYCLE|NOCYCLE] 214 [CACHE 缓存大小|NOCACHE]), 215 列名称 类型 ,... 216 ); 217 218 --用例1:创建带有自动增长列的数据表。 219 DROP SEQUENCE myseq PURGE; 220 CREATE TABLE mytab( 221 mid NUMBER GENERATED BY DEFAULT AS IDENTITY(START WITH 1 INCREMENT BY 1), 222 name VARCHAR2(20) NOT NULL, 223 CONSTRAINT pk_mid PRIMARY KEY(mid) 224 ); 225 226 227 SELECT sequence_name,min_value,max_value,increment_by FROM user_sequences; 228 229 --用例2: 自动序列的删除 230 自动序列依附于数据表而存在,如果在执行数据表的删除操作时没有设置 PURGE 参数,那么表删除后序列依然会被保留,这时候不能利用 DROP SEQUENCE 命令删除序列,必须使用清空回收站的方式才可以删除。 231 PURGE recyclebin; 232 233 234 3 同义词 235 数据库中所谓的同义词实际上就是指为一个数据库对象其一个其他名字。 236 创建同义词语法: 237 CREATE [PUBLIC] SYNONYM 同义词名称 FOR 数据库对象; 238 239 删除同义词语法: 240 DROP SYNONYM 同义词名称; 241 242 --用例1:创建同义词 243 CREATE SYNONYM myemp FOR emp; 244 SELECT * FROM user_synonyms WHERE synonym_name='MYEMP'; 245 246 --用例2:删除同义词 247 DROP SYNONYM myemp ; 248 249 --用例3:创建公共同义词 myemp 250 CREATE PUBLIC SYNONYM myemp FOR emp; 251 252 253 4 Oracle 伪列 254 在 Oracle 数据库中为了实现完整的关系数据库的功能,专门为用户提供了许多的伪列,像之前在讲解序列时所使用的 NEXTVAL 和 CURRVAL 就是两个默认提供的操作伪列。同时在前面使用的 SYSDATE 与 SYSTIMESTAMP 也属于伪列(而想查询使用 DUAL 称为伪表)。这些数据伪列并不是用户在建立数据库对象时有用户完成的,而是 Oracle 自动帮助用户建立的,用户只需要按照要求使用即可。另外两个重要的伪列,分别是 ROWNUM 和 ROWID 。 255 1. ROWID 伪列 256 2. ROWNUM 伪列 257 3. NEXTVAL、CURRVAL 258 4. SYSDATE、SYSTIMESTAMP 259 5. DUAL 伪表 260 261 4.1 ROWID 伪列 262 在数据表中每一行所保存的记录,实际上 Oracle 都会默认为每条记录分配一个唯一的地址编号,而这个地址编号就是通过 ROWID 进行表示的,ROWID 本身是一个数据的伪列,所有的数据都利用 ROWID 进行数据定位。 263 264 --用例1: 265 SELECT ROWID,deptno,dname,loc FROM dept; 266 267 读讲解ROWID 的组成:AAAWecAAGAAAAC2AAA: 268 1.数据对象号(data object number):AAAWec 269 2.相对文件号(relative file number):AAG 270 3.数据块号(block number):AAAAC2 271 4.数据行号(row number):AAA 272 273 --ROWID 的操作函数: 274 1. DBMS_ROWID.rowid_object(ROWID) : 从一个 ROWID 中,取得数据对象号。 275 2. DBMS_ROWID.rowid_relative_fno(ROWID) : 从一个 ROWID 中,取得相对文件号。 276 3. DBMS_ROWID.rowid_block_number(ROWID) : 从一个 ROWID 中,取得数据块号。 277 4. DBMS_ROWID.rowid_row_number(ROWID) : 从一个 ROWID 中,取得数据行号。 278 279 --拆分 ROWID,取数据。 280 SELECT ROWID, 281 DBMS_ROWID.rowid_object(ROWID), 282 DBMS_ROWID.rowid_relative_fno(ROWID), 283 DBMS_ROWID.rowid_block_number(ROWID), 284 DBMS_ROWID.rowid_row_number(ROWID), 285 deptno,dname,loc 286 FROM dept; 287 288 -- 使用 ROWID 可以定位一个数据库中的任何数据行。因为一个段只能存在一个表空间内,所以通过使用数据对象号,Oracle 服务器就可以找到包含数据行的表空间。之后使用表空间中的相对文件号就可以确定文件,在利用数据块号就可以确定包含所需数据行的数据块,最后使用行号就可以定位数据行的行目录项。 289 290 --用例2 :经典题目 291 向 mydept 表中增加一些数据 292 INSERT INTO mydept(deptno,dname,loc) VALUES(10,'ACCOUNTING','NEW YORK'); 293 INSERT INTO mydept(deptno,dname,loc) VALUES(10,'ACCOUNTING','NEW YORK'); 294 INSERT INTO mydept(deptno,dname,loc) VALUES(20,'RESEARCH','DALLAS'); 295 INSERT INTO mydept(deptno,dname,loc) VALUES(20,'RESEARCH','DALLAS'); 296 INSERT INTO mydept(deptno,dname,loc) VALUES(20,'RESEARCH','DALLAS'); 297 298 现在要求用户将所有重复的数据删除到只剩1条,即:现在表中有3个10部门的信息,要求值保留1个10部门的信息,删除重复数据后,mydept表应只剩下4行单独的数据。 299 答案: 300 --1 对mydept 表分组,统计出唯一的ROWID数据。 301 SELECT deptno,dname,loc,MIN(ROWID) 302 FROM mydept 303 GROUP BY deptno,dname,loc; 304 305 --2 编写删除语句删除重复数据(必须要按照deptno 部门分组,否则会只保留一个值。) 306 DELETE FROM mydept 307 WHERE ROWID NOT IN ( 308 SELECT MIN(ROWID) 309 FROM mydept 310 GROUP BY deptno); 311 312 4.2 ROWNUM 伪列 313 ROWNUM 表示的是一个数据行编号的伪列,它的内容是在用户查询数据的时候,为用户动态分配的一个数字(行号)。 314 ROWNUM作用: 315 1.取出一个查询的第一行记录。 316 2.取出一个查询的前N行记录。 317 --用例1: 318 SELECT ROWNUM,deptno,dname,loc FROM dept; 319 320 --用例2:取出一个查询的第一行记录。 321 SELECT * FROM emp WHERE ROWNUM=1; 322 323 --用例3:取出一个查询的前N行记录。 324 SELECT * FROM emp WHERE ROWNUM>5; 325 326 --用例4:经典应用,分页显示。ROWNUM 数据伪列前N 行查询的语法 327 SELECT * FROM( 328 SELECT 列1[,列2,...],ROWNUM rownum 别名 329 FROM 表名称 [别名] 330 WHERE ROWNUM <= (currentPage(当前所在页) * lineSize(每页显示记录行数)) temp 331 WHERE temp.rownum 别名 >(currentPage(当前所在页)-1)*lineSize(每页显示记录行数); 332 333 334 --显示雇员表中前5条记录。 335 SELECT * FROM( 336 SELECT empno,ename,job,hiredate,sal,mgr,deptno,ROWNUM rn 337 FROM emp WHERE ROWNUM<=5) temp 338 ) temp.rn>0; 339 340 341 342 4.3 ORACLE 12C 新特性,(方便数据分页显示操作,指定范围内的操作数据) 343 FETCH语法: 344 SELECT [DISTIINCT] [][] 345 FROM 表名称1 [表别名1],表名称2 [表别名2],... 346 [WHERE 条件(s)] 347 [GROUP BY 分组字段1,分组字段2] 348 [HAVING 过滤条件(s)] 349 [ORDER BY 排序字段 ASC|DESC] 350 [FETCH FIRST 行数]|[OFFSET 开始位置 ROWS FETCH NEXT 个数]|[FETCH NEXT 百分比 PERCENT] ROW ONLY 351 352 1.获取前N行记录:FETCH FIRST 行数 ROW ONLY ; 353 2.取得指定范围的记录: OFFSET 开始位置 ROWS FETCH NEXT 个数 ROW ONLY ; 354 3.按照百分比取得记录:FETCH NEXT 百分比 PERCENT ROW ONLY 355 356 --用例1:取得emp表中的前5行记录。 357 SELECT * FROM emp FETCH FIRST 5 ROW ONLY; 358 359 --用例2:为数据排序,取得前5行记录。 360 SELECT * FROM emp 361 ORDER BY sal DESC 362 FETCH FIRST 5 ROW ONLY; 363 364 --用例3:取得指定范围的记录,取得4~5条记录。(下标为0,所有行从0行开始) 365 SELECT * FROM emp 366 ORDER BY sal DESC 367 OFFSET 3 ROWS FETCH NEXT 2 ROW ONLY; /*下标为0,所有行从0行开始*/ 368 369 --用例4:按百分比取部分数据。 370 SELECT * FROM emp 371 ORDER BY sal DESC 372 FETCH NEXT 10 PERCENT ROW ONLY ; 373 374 375 5 索引 (利用ROWID查找是最高效的做法) 376 在数据库中,索引是一种专门用于数据库查询操作性能的一种手段。在 Oracle中,为了维护这种查询性能,需要对某一类数据进行指定结构的排列。但是针对 Oracle 中,针对不同的情况会有不同的索引使用。 377 索引有: 378 1. B树索引 379 2. 降序索引 380 3. 位图索引 381 4. 函数索引 382 383 5.1 B*Tree 索引 (二叉树索引) 384 B树索引是最基本的索引结构,在 Oracle 中默认建立的索引就是此类型索引。一般B树索引在检索高基数数列(该列上的重复内容较少或没有)的时候可以提高性能的检索操作。 385 原理: 386 1. 取得第一个数据作为根节点。 387 2. 比根节点小的数据放在左子树,比根节点大的数据放在右子树。 388 389 --在Oracle 中想要创建 B*Tree 索引,有以下两种方式: 390 1. 当某一列上设置了主键约束或唯一约束,则会自动创建索引。(PK、UK) 391 2. 利用命令直接创建索引: CREATE INDEX [用户名.]索引名称 ON [用户名.]表名称 (列名称 [ASC|DESC],...); 392 393 --用例1: 394 CREATE INDEX emp_sal_ind ON emp(sal); 395 --查看哪张表上存在索引。 396 SELECT index_name,index_type,table_owner,table_name,uniqueness,status FROM user_indexes; 397 --查看索引所在列。 398 SELECT * FROM user_ind_columns WHERE lower(index_name)='emp_sal_ind'; 399 400 --用例2:在 hiredate 字段上设置降序索引 401 CREATE INDEX emp_hiredate_ind_desc ON emp(hiredate); 402 403 --用例3:创建函数索引 404 CREATE INDEX emp_ename_ind ON emp(LOWER(sal)); 405 406 407 5.2 位图索引 408 如果现在某一列上的数据都数据低基数(Low - Cardinality)列的时候,就可以利用位图索引来提升查询性能。例如deptno,春夏秋冬。 409 位图索引以一种压缩数据的格式存放,因此所占用的磁盘空间要比 B*Tree 索引小很多。 410 411 语法: 412 创建位图索引: 413 CREATE BITMAP INDEX [用户名.]索引名称 ON [用户名.]表名称 (列名称 [ASC|DESC],...); 414 --用例1: 415 CREATE BITMAP INDEX emp_deptno_ind ON emp(deptno); 416 SELECT index_name,index_type,table_owner,table_name,uniqueness,status FROM user_indexes; 417 418 5.3 删除索引 419 语法: 420 DROP INDEX 索引名称; 421 --用例1: 422 DROP INDEX emp_deptno_ind;
浙公网安备 33010602011771号