Oracle培训教材


一.SQL语言简介

1. SQL概述
SQL是一种面向数据库的通用数据处理语言规范,能完成以下几类功能:提取查询数据,插入修改删除数据,生成修改和删除数据库对象,数据库安全控制,数据库完整性及数据保护控制。

数据库对象包括表、视图、索引、同义词、簇、触发器、函数、过程、包、数据库链、快照等(表空间、回滚段、角色、用户)。数据库通过对表的操作来管理存储在其中的数据。

2. 数据库查询

  1. 用SELECT语句从表中提取查询数据。语法为

SELECT [DISTINCT] {column1,column2,…} FROM tablename WHERE {conditions} GROUP BY {conditions} ORDER BY {expressions} [ASC/DESC];

说明:SELECT子句用于指定检索数据库的中哪些列,FROM子句用于指定从哪一个表或视图中检索数据。

  1. SELECT中的操作符及多表查询WHERE子句。(LIKE,IS,…)

WHERE子句中的条件可以是一个包含等号或不等号的条件表达式,也可以是一个含有IN、NOT IN、BETWEEN、LIKE、IS NOT NULL等比较运算符的条件式,还可以是由单一的条件表达通过逻辑运算符组合成复合条件。

比较操作符 = > < >= <= != <>

SQL操作符 BETWEEN … AND… IN LIKE IS NULL

NOT BETWEEN … AND… NOT IN NOT LIKE IS NOT NULL

逻辑操作符 AND OR NOT

  1. ORDER BY 子句

ORDER BY 子句使得SQL在显示查询结果时将各返回行按顺序排列,返回行的排列顺序由ORDER BY 子句指定的表达式的值确定。

  1. 连接查询

利用SELECT语句进行数据库查询时,可以把多个表、视图的数据结合起来,使得查询结果的每一行中包含来自多个表达式或视图的数据,这种操作被称为连接查询。

连接查询的方法是在SELECT命令的FROM子句中指定两个或多个将被连接查询的表或视图,并且在WHERE子句告诉ORACLE如何把多个表的数据进行合并。根据WHERE子句中的条件表达式是等还是不等式,可以把连接查询分为等式连接和不等式连接。

  1. 子查询

如果某一个SELECT命令(查询1)出现在另一个SQL命令(查询2)的一个子句中,则称查询1是查询2的子查询。

3. 基本数据类型(NUMBER,VARCHAR2,DATE)
ORACEL支持下列内部数据类型:

l VARCHAR2 变长字符串,最长为2000字符。

l NUMBER 数值型。

l LONG 变长字符数据,最长为2G字节。

l DATE 日期型。

l RAW 二进制数据,最长为255字节。

l LONG RAW 变长二进制数据,最长为2G字节。

l ROWID 二六进制串,表示表的行的唯一地址。

l CHAR 定长字符数据,最长为255。

4. 常用函数用法:
一个函数类似于一个算符,它操作数据项,返回一个结果。函数在格式上不同于算符,它个具有变元,可操作0个、一个、二个或多个变元,形式为:

函数名(变元,变元,…)

函数具有下列一般类形:

l 单行函数

l 分组函数

1)单行函数对查询的表或视图的每一行返回一个结果行。它有数值函数,字符函数,日期函数,转换函数等。

2)分组函数返回的结果是基于行组而不是单行,所以分组函数不同于单行函数。在许多分组函数中可有下列选项:

l DISTRNCT 该选项使分组函数只考虑变元表达式中的不同值。

l ALL该选项使分组函数考虑全部值,包含全部重复。

全部分组函数(除COUNT(*)外)忽略空值。如果具有分组函数的查询,没有返回行或只有空值(分组函数的变元取值的行),则分组函数返回空值。

l 单行函数

  1. 数字函数

ABS 取绝对值 POWER 乘方 LN 10为底数取冪

SQRT 平方根 EXP e的n次乘方 LOG(m,n) m为底数n取冪

数学运算函数:ACOS ATAN ATAN2 COS COSH SIGN SIN SINH TAN TANH

CEIL 大于或等于取整数

FLOOR 小于或等于取整数

MOD 取余数

ROUND(n,m) 按m的位数取四舍五入值如果round(日期): 中午12以后将是明天的日期. round(sysdate,'Y')是年的第一天

TRUNC(n,m) 按m的位数取前面的数值如果trunc(日期), 确省的是去掉时间

  1. 字符函数

CHR 按数据库的字符集由数字返回字符

CONCAT(c1,c2) 把两个字符c1,c2组合成一个字符, 和 || 相同

REPLACE(c,s,r) 把字符c里出现s的字符替换成r, 返回新字符

SUBSTR(c,m,n) m大于0,字符c从前面m处开始取n位字符,m等于0和1一样,

m小与0,字符c从后面m处开始取n位字符

TRANSLATE(c,f1,t1) 字符c按f1到t1的规则转换成新的字符串

INITCAP 字符首字母大写,其它字符小写

LOWER 字符全部小写

UPPER 字符全部大写

LTRIM(c1,c2) 去掉字符c1左边出现的字符c2

RTRIM(c1,c2)

TRIM(c1,c2) 去掉字符c1左右两边的字符c2

LPAD(c1,n,c2) 字符c1按制定的位数n显示不足的位数用c2字符串替换左边的空位

RPAD(c1,n,c2)

  1. 日期函数

ADD_MONTHS(d,n) 日期值加n月

LAST_DAY(d) 返回当月的最后一天的日期

MONTHS_BETWEEN(d1,d2) 两个日期值间的月份,d1

  1<d2 (week="" (说明:周计是按iso标准,从1月1日的星期数到后面七天为一周,不一定是从周一到周日)="" 4)="" 5)="" 6)="" day="" dd="" dual是sys用户下一个空表,它只有一个字段dummy="" dy="" hh="" hh12="" hh24="" hh24:mi:ss="" hh24:mi:ss可以在unix环境变量或者nt的注册表里的设置="" iw="" mi="" mm="" mon="" month="" month)="" next_day(d)="" nls_date_format="yyyy-mm-dd" of="" q="" session命令改变="" sql="" ss="" sysdate="" to_char(date,'日期显示格式')="" to_char(number)="" to_date(char,'日期显示格式')="" to_date里日期显示格式="" to_lob="" to_number(char)="" w="" ww,="" y="" year="" year)="" yy="" yyy="" yyyy="" 分钟="" 如果想固定日期的显示格式可以在数据库的参数文件initorasid.ora里新写一行参数="" 如果想固定日期的显示格式可以用alter="" 季度="" 小时="" 年="" 当前的系统时间="" 把long字段转换成lob字段="" 日="" 星期="" 月="" 用于显示或报表的格式对齐="" 用于计算或者比较大小="" 秒="" 转换函数(1)="" 转换函数(2)="" 转换函数(3)="" 返回日期值下一天的日期="" 返回负数=""> alter session set nls_date_format='yyyy-mm-dd hh24:mi:ss'; 
  2
  3它的作用顺序如下: 
  4
  5initialization parameter 
  6
  7Environment variable 
  8
  9ALTER SESSION command 
 10
 117) 转换函数 (4) 
 12
 13to_char(number)里数字显示格式 
 14
 159 数字位 
 16
 170 数字前面补0 to_char(-1200,'00000.00') 
 18
 19. 小数点的位置 
 20
 21, 标记位置的逗号 用在数字显示格式的左边 
 22
 23L 根据数据库字符集加货币符号 to_char(-1200,'L9999.99') 
 24
 25B 把数字0显示为空格,用在数字显示格式的右边 
 26
 27MI 右边的负数标记 to_char(-1200,'9999.99MI') 
 28
 29PR 括起来的负数 to_char(-1200,'9999.99PR') 
 30
 31EEEE 用指数方式表示 to_char(-1200,'9999.99EEEE') 
 32
 338) 输入字符,返回数字的函数 
 34
 35instr(c1,c2) 字符c2出现在c1的位置, 不出现, 返回0, 常用于模糊查询 
 36
 37length(c) 按数据库的字符集,算出字符c的长度,跟数据库的字符集有关, 一个汉字长度为1 
 38
 399) 有逻辑比较的函数NVL(EXPR1, EXPR2)函数 
 40
 41解释: IF EXPR1=NULL RETURN EXPR2 
 42
 43ELSE RETURN EXPR1 
 44
 4510) DECODE(AA﹐V1﹐R1﹐V2﹐R2....)函数 
 46
 47解释: IF AA=V1 THEN RETURN R1 
 48
 49IF AA=V2 THEN RETURN R2 
 50
 51..… 
 52
 53ELSE 
 54
 55RETURN NULL 
 56
 57举例: decode(id,1,'dept sale',2,'dept tech') 
 58
 59l 集合函数 经常和group by一起使用 
 60
 611) 集合函数列表 
 62
 63AVG (DISTINCT | ALL | N) 取平均值 
 64
 65COUNT (DISTINCT | ALL | N | expr | * ) 统计数量 
 66
 67MAX (DISTINCT | ALL | N) 取最大值 
 68
 69MIN (DISTINCT | ALL | N) 取最小值 
 70
 71SUM (DISTINCT | ALL | N) 取合计值 
 72
 73STDDEV (DISTINCT | ALL | N) 取偏差值,如果组里选择的内容都相同,结果为0 
 74
 75VARIANCE (DISTINCT | ALL | N) 取平方偏差值 
 76
 772) 使用集合函数的语法 
 78
 79SELECT column, group_function FROM table 
 80
 81WHERE condition GROUP BY group_by_expression 
 82
 83HAVING group_condition ORDER BY column;   
 84
 85
 863) 使用count时的注意事项 
 87
 88SELECT COUNT(*) FROM table; 
 89
 90SELECT COUNT(常量) FROM table; 
 91
 92都是统计表中记录数量,如果没有PK后者要好一些 
 93
 94SELECT COUNT(all 字段名) FROM table; 
 95
 96SELECT COUNT(字段名) FROM table; 
 97
 98不会统计为NULL的字段的数量 
 99
100SUM,AVG时都会忽略为NULL的字段 
101
1024) 用group by时的限制条件 
103
104SELECT字段名不能随意, 要包含在GROUP BY的字段里 
105
106GROUP BY后ORDER BY时不能用位置符号和别名 
107
108限制GROUP BY的显示结果, 用HAVING条件 
109
1105) 例子 
111
112SQL&gt; select title,sum(salary) payroll from s_emp 
113
114where title like 'VP%' group by title 
115
116having sum(salary)&gt;5000 order by sum(salary) desc;   
117
118
119找出某表里字段重复的记录数, 并显示 
120
121SQL&gt; select (duplicate field names) from table_name 
122
123group by (list out fields) having count(*)&gt;1; 
124
1255\. 数据操纵语言命令:   
126数据库操纵语言(DML)命令用于查询和操纵模式对象中的数据,它不隐式地提交当前事务。它包含UPDATE、INSERT、DELETE、EXPLAIN PLAN、SELECT和LOCK TABLE 等命令。下面简单介绍一下: 
127
1281) UPDATE tablename SET {column1=expression1,column2=expression2,…} WHERE {conditions}; 
129
130例如:S QL&gt;UPDATE EMP 
131
132SET JOB =’MANAGER’ 
133
134WHERE ENAME=’MAPTIN’; 
135
136SQL &gt;SELECT * FROM EMP; 
137
138UPDATE子句指明了要修改的数据库是EMP,并用WHERE子句限制了只对名字(ENAME)为’MARTIN’的职工的数据进行修改,SET子句则说明修改的方式,即把’MARTION’的工作名称(JOB)改为’MARAGER’. 
139
1402) INSERT INTO tablename {column1,column2,…} VALUES {expression1,expression2,…}; 
141
142例如:SQL&gt;SELECT INTO DEPT(DNAME, DEPTNO) 
143
144VALUES (‘ACCOUNTING’,10) 
145
1463) DELETE FROM tablename WHERE {conditions}; 
147
148例如:SQL&gt;DELETE FROM EMP 
149
150WHERE EMPNO = 7654; 
151
152DELETE命令删除一条记录,而且DELETE命令只能删除整行,而不能删除某行中的部分数据. 
153
1544) 事务控制命令 
155
156提交命令(COMMIT):可以使数据库的修改永久化.设置AUTOCOMMIT为允许状态:SQL &gt;SET AUTOCOMMIT ON; 
157
158回滚命令(ROLLBACK):消除上一个COMMIT命令后的所做的全部修改,使得数据库的内容恢复到上一个COMMIT执行后的状态.使用方法是: 
159
160SQL&gt;ROLLBACK; 
161
162二.Oracle扩展PL/SQL简介   
1631\. PL/SQL概述。   
164PL/SQL是Oracle对SQL规范的扩展,是一种块结构语言,即构成一个PL/SQL程序的基本单位(过程、函数和无名块)是逻辑块,可包含任何数目的嵌套了快。这种程序结构支持逐步求精方法解决问题。一个块(或子块)将逻辑上相关的说明和语句组合在一起,其形式为: 
165
166DECLARE 
167
168\---说明 
169
170BEGIN 
171
172\---语句序列 
173
174EXCEPTION 
175
176\---例外处理程序 
177
178END; 
179
180它有以下优点: 
181
182l 支持SQL; 
183
184l 生产率高; 
185
186l 性能好; 
187
188l 可称植性; 
189
190l 与ORACLE集成. 
191
1922\. PL/SQL体系结构   
193PL/SQL运行系统是种技术,不是一种独立产品,可认为这种技术是PL/SQL块和子程序的一种机,它可接收任何有效的PL/SQL块或子程序。如图所示: 
194
195PL/SQL块   
196  
197
198
199PL/SQL机可执行过程性语句,而将SQL语句发送到ORACLE服务器上的SQL语句执行器。在ORACLE预编译程序或OCI程序中可嵌入无名的PL/SQL块。如果ORACLE具有PROCEDURAL选件,有名的PL/SQL块(子程序)可单独编译,永久地存储在数据库中,准备执行。 
200
2013\. PL/SQL基础:   
202PL/SQL有一字符集、保留字、标点、数据类型、严密语法等,它与SQL有相同表示,现重点介绍。 
203
2041) 数据类型:如下表所示 
205
206  
207  
208数据类型   
209子类型   
210  
211纯量类型   
212数值   
213BINARY_INTEGER   
214NATURAL,POSITIVE   
215  
216NUMBER   
217DEC,DECIMAL,DOUBLE PRECISION,PLOAT,INTEGER,INT,NUMERIC,REAL,SMALLINT   
218  
219字符   
220CHAR   
221CHARACTER,STRING   
222  
223VARCHAR2   
224VARCHAR   
225  
226LONG   
227  
228  
229LONG RAW   
230  
231  
232RAW   
233  
234  
235RAWID   
236  
237  
238逻辑   
239BOOLEAN   
240  
241  
242日期   
243DATE   
244  
245  
246组合 
247
248类型   
249记录   
250RECORD   
251  
252  
253254TABLE   
255  
256
257
2582) 变量和常量 
259
260在PL/SQL程序中可将值存储在变量和常量中,当程序执行时,变量的值可以改变,而常量的值不能改变。 
261
2623) 程序块式结构: 
263
264DECLARE 
265
266变量说明部分; 
267
268BEGIN 
269
270执行语句部分; 
271
272[EXCEPTION 
273
274例外处理部分;] 
275
276END; 
277
2784\. 控制语句:   
279分支语句: 
280
281IF condition THEN 
282
283Sequence_of_statements; 
284
285END IF; 
286
287IF condition THEN 
288
289Sequence_of_statement1; 
290
291ELSE 
292
293Sequence_of_statement2; 
294
295END IF; 
296
297IF condition1 THEN 
298
299Sequence_of_statement1; 
300
301ELSIF condition2 THEN 
302
303Sequence_of_statement2; 
304
305ELSIF condition3 THEN 
306
307Sequence_of_statement3; 
308
309END IF; 
310
3115\. 循环语句:   
312LOOP 
313
314Sequence_of_statements; 
315
316IF condition THEN 
317
318EXIT; 
319
320END IF; 
321
322END LOOP; 
323
324WHILE condition LOOP 
325
326Sequence_of_statements; 
327
328END LOOP; 
329
330FOR counter IN lower_bound..higher_bound LOOP 
331
332Sequence_of_statements; 
333
334END LOOP; 
335
3366\. 子程序:   
337存储过程: 
338
339CREATE PROCEDURE 过程名 (参数说明1,参数说明2, 。。。) IS 
340
341[局部说明] 
342
343BEGIN 
344
345执行语句; 
346
347END 过程名; 
348
349存储函数: 
350
351CREATE FUNCTION 函数名 (参数说明1,参数说明2, 。。。) 
352
353RETURN 类型 IS 
354
355[局部说明] 
356
357BEGIN 
358
359执行语句; 
360
361END 函数名; 
362
363三.Decode()函数使用技巧   
3641\. 含义解释:   
365DECODE(条件,值1,翻译值1,值2,翻译值2,...值n,翻译值n,缺省值) 
366
367该函数的含义如下:   
368IF 条件=值1 THEN   
369RETURN(翻译值1)   
370ELSIF 条件=值2 THEN   
371RETURN(翻译值2)   
372......   
373ELSIF 条件=值n THEN   
374RETURN(翻译值n) 
375
376ELSE   
377RETURN(缺省值)   
378END IF 
379
3802\. 使用方法:   
3811) 比较大小   
382select decode(sign(变量1-变量2),-1,变量1,变量2) from dual; --取较小值   
383sign()函数根据某个值是0、正数还是负数,分别返回0、1、-1 
384
385例如:   
386变量1=10,变量2=20   
387则sign(变量1-变量2)返回-1,decode解码结果为“变量1”,达到了取较小值的目的。 
388
389表、视图结构转化   
390现有一个商品销售表sale,表结构为:   
391month char(6) --月份   
392sell number(10,2) --月销售金额 
393
394现有数据为:   
395200001 1000   
396200002 1100   
397200003 1200   
398200004 1300   
399200005 1400   
400200006 1500   
401200007 1600   
402200101 1100   
403200202 1200   
404200301 1300 
405
406想要转化为以下结构的数据:   
407year char(4) --年份   
408month1 number(10,2) --1月销售金额   
409month2 number(10,2) --2月销售金额   
410month3 number(10,2) --3月销售金额   
411month4 number(10,2) --4月销售金额   
412month5 number(10,2) --5月销售金额   
413month6 number(10,2) --6月销售金额   
414month7 number(10,2) --7月销售金额   
415month8 number(10,2) --8月销售金额   
416month9 number(10,2) --9月销售金额   
417month10 number(10,2) --10月销售金额   
418month11 number(10,2) --11月销售金额   
419month12 number(10,2) --12月销售金额 
420
421结构转化的SQL语句为:   
422create or replace view   
423v_sale(year,month1,month2,month3,month4,month5,month6,month7,month8,month9,month10,month11,month12)   
424as   
425select   
426substrb(month,1,4),   
427sum(decode(substrb(month,5,2),'01',sell,0)),   
428sum(decode(substrb(month,5,2),'02',sell,0)),   
429sum(decode(substrb(month,5,2),'03',sell,0)),   
430sum(decode(substrb(month,5,2),'04',sell,0)),   
431sum(decode(substrb(month,5,2),'05',sell,0)),   
432sum(decode(substrb(month,5,2),'06',sell,0)),   
433sum(decode(substrb(month,5,2),'07',sell,0)),   
434sum(decode(substrb(month,5,2),'08',sell,0)),   
435sum(decode(substrb(month,5,2),'09',sell,0)),   
436sum(decode(substrb(month,5,2),'10',sell,0)),   
437sum(decode(substrb(month,5,2),'11',sell,0)),   
438sum(decode(substrb(month,5,2),'12',sell,0))   
439from sale   
440group by substrb(month,1,4); 
441
442四.NULL 使用详解   
4431\. 含义解释:   
444问:什么是NULL?   
445答:在我们不知道具体有什么数据的时候,也即未知,可以用NULL,我们称它为空,ORACLE中,含有空值的表列长度为零。   
446ORACLE允许任何一种数据类型的字段为空,除了以下两种情况:   
4471、主键字段(primary key),   
4482、定义时已经加了NOT NULL限制条件的字段 
449
450说明:   
4511、等价于没有任何值、是未知数。   
4522、NULL与0、空字符串、空格都不同。   
4533、对空值做加、减、乘、除等运算操作,结果仍为空。   
4544、NULL的处理使用NVL函数。   
4555、比较时使用关键字用“is null”和“is not null”。   
4566、空值不能被索引,所以查询时有些符合条件的数据可能查不出来,count(*)中,用nvl(列名,0)处理后再查。   
4577、排序时比其他数据都大(索引默认是降序排列,小→大),所以NULL值总是排在最后。 
458
4592\. 使用方法:   
460SQL&gt; select 1 from dual where null=null; 
461
462没有查到记录 
463
464SQL&gt; select 1 from dual where null=''; 
465
466没有查到记录 
467
468SQL&gt; select 1 from dual where ''=''; 
469
470没有查到记录 
471
472SQL&gt; select 1 from dual where null is null; 
473
4741 
475
476\--------- 
477
4781 
479
480SQL&gt; select 1 from dual where nvl(null,0)=nvl(null,0); 
481
4821 
483
484\--------- 
485
4861 
487
488对空值做加、减、乘、除等运算操作,结果仍为空。 
489
490SQL&gt; select 1+null from dual; 
491
492SQL&gt; select 1-null from dual; 
493
494SQL&gt; select 1*null from dual; 
495
496SQL&gt; select 1/null from dual; 
497
498查询到一个记录. 
499
500注:这个记录就是SQL语句中的那个null 
501
502设置某些列为空值 
503
504update table1 set 列1=NULL where 列1 is not null; 
505
506现有一个商品销售表sale,表结构为: 
507
508month char(6) --月份 
509
510sell number(10,2) --月销售金额 
511
512create table sale (month char(6),sell number); 
513
514insert into sale values('200001',1000); 
515
516insert into sale values('200002',1100); 
517
518insert into sale values('200003',1200); 
519
520insert into sale values('200004',1300); 
521
522insert into sale values('200005',1400); 
523
524insert into sale values('200006',1500); 
525
526insert into sale values('200007',1600); 
527
528insert into sale values('200101',1100); 
529
530insert into sale values('200202',1200); 
531
532insert into sale values('200301',1300); 
533
534insert into sale values('200008',1000); 
535
536insert into sale(month) values('200009');(注意:这条记录的sell值为空) 
537
538commit; 
539
540共输入12条记录 
541
542SQL&gt; select * from sale where sell like '%'; 
543
544MONTH SELL 
545
546\------ --------- 
547
548200001 1000 
549
550200002 1100 
551
552200003 1200 
553
554200004 1300 
555
556200005 1400 
557
558200006 1500 
559
560200007 1600 
561
562200101 1100 
563
564200202 1200 
565
566200301 1300 
567
568200008 1000 
569
570查询到11记录. 
571
572结果说明: 
573
574查询结果说明此SQL语句查询不出列值为NULL的字段 
575
576此时需对字段为NULL的情况另外处理。 
577
578SQL&gt; select * from sale where sell like '%' or sell is null; 
579
580SQL&gt; select * from sale where nvl(sell,0) like '%'; 
581
582MONTH SELL 
583
584\------ --------- 
585
586200001 1000 
587
588200002 1100 
589
590200003 1200 
591
592200004 1300 
593
594200005 1400 
595
596200006 1500 
597
598200007 1600 
599
600200101 1100 
601
602200202 1200 
603
604200301 1300 
605
606200008 1000 
607
608200009 
609
610查询到12记录. 
611
612Oracle的空值就是这么的用法,我们最好熟悉它的约定,以防查出的结果不正确。 
613
614五.如何查找、删除表中重复的记录   
6151\. 问题提出:   
616当我们想要为一个表创建唯一索引时,如果该表有重复的记录,则无法创建成功。 
617
6182\. 方法原理:   
6191) Oracle中,每一条记录都有一个rowid,rowid在整个数据库中是唯一的,   
620rowid确定了每条记录是在ORACLE中的哪一个数据文件、块、行上。 
621
6222) 在重复的记录中,可能所有列的内容都相同,但rowid不会相同,所以只要确定出重复记录中   
623那些具有最大rowid的就可以了,其余全部删除。 
624
6253) 以下语句用到了3项技巧:rowid、子查询、别名。 
626
6273\. 实现方法:   
628SQL&gt; create table a ( 
629
6302 bm char(4), --编码 
631
6323 mc varchar2(20) --名称 
633
6344 ) 
635
6365 / 
637
638表已建立. 
639
640SQL&gt; insert into a values('1111','1111'); 
641
642SQL&gt; insert into a values('1112','1111'); 
643
644SQL&gt; insert into a values('1113','1111'); 
645
646SQL&gt; insert into a values('1114','1111'); 
647
648SQL&gt; insert into a select * from a; 
649
650插入4个记录. 
651
652SQL&gt; commit; 
653
654完全提交. 
655
656SQL&gt; select rowid,bm,mc from a; 
657
658ROWID BM MC 
659
660\------------------ ---- ------- 
661
662000000D5.0000.0002 1111 1111 
663
664000000D5.0001.0002 1112 1111 
665
666000000D5.0002.0002 1113 1111 
667
668000000D5.0003.0002 1114 1111 
669
670000000D5.0004.0002 1111 1111 
671
672000000D5.0005.0002 1112 1111 
673
674000000D5.0006.0002 1113 1111 
675
676000000D5.0007.0002 1114 1111 
677
678查询到8记录. 
679
680查出重复记录 
681
682SQL&gt; select rowid,bm,mc from a where a.rowid!=(select max(rowid) from a b where a.bm=b.bm and a.mc=b.mc); 
683
684ROWID BM MC 
685
686\------------------ ---- -------------------- 
687
688000000D5.0000.0002 1111 1111 
689
690000000D5.0001.0002 1112 1111 
691
692000000D5.0002.0002 1113 1111 
693
694000000D5.0003.0002 1114 1111 
695
696删除重复记录 
697
698SQL&gt; delete from a a where a.rowid!=(select max(rowid) from a b where a.bm=b.bm and a.mc=b.mc); 
699
700删除4个记录. 
701
702SQL&gt; select rowid,bm,mc from a; 
703
704ROWID BM MC 
705
706\------------------ ---- -------------------- 
707
708000000D5.0004.0002 1111 1111 
709
710000000D5.0005.0002 1112 1111 
711
712000000D5.0006.0002 1113 1111 
713
714000000D5.0007.0002 1114 1111 
715
716六.如何正确利用Rownum来限制查询所返回的行数   
7171\. 含义解释:   
7181) rownum是oracle系统顺序分配为从查询返回的行的编号,返回的第一行分配的是1,第二行是2,依此类推,这个伪字段可以用于限制查询返回的总行数。 
719
7202) rownum不能以任何基表的名称作为前缀。 
721
7222\. 使用方法:   
723现有一个商品销售表sale,表结构为: 
724
725month char(6) --月份 
726
727sell number(10,2) --月销售金额 
728
729create table sale (month char(6),sell number); 
730
731insert into sale values('200001',1000); 
732
733insert into sale values('200002',1100); 
734
735insert into sale values('200003',1200); 
736
737insert into sale values('200004',1300); 
738
739insert into sale values('200005',1400); 
740
741insert into sale values('200006',1500); 
742
743insert into sale values('200007',1600); 
744
745insert into sale values('200101',1100); 
746
747insert into sale values('200202',1200); 
748
749insert into sale values('200301',1300); 
750
751insert into sale values('200008',1000); 
752
753commit; 
754
755SQL&gt; select rownum,month,sell from sale where rownum=1;(可以用在限制返回记录条数的地方,保证不出错,如:隐式游标) 
756
757ROWNUM MONTH SELL 
758
759\--------- ------ --------- 
760
7611 200001 1000 
762
763SQL&gt; select rownum,month,sell from sale where rownum=2;(1以上都查不到记录) 
764
765没有查到记录 
766
767SQL&gt; select rownum,month,sell from sale where rownum&gt;5; 
768
769(由于rownum是一个总是从1开始的伪列,Oracle 认为这种条件不成立,查不到记录) 
770
771没有查到记录 
772
773只返回前3条纪录 
774
775SQL&gt; select rownum,month,sell from sale where rownum&lt;4; 
776
777ROWNUM MONTH SELL 
778
779\--------- ------ --------- 
780
7811 200001 1000 
782
7832 200002 1100 
784
7853 200003 1200 
786
787如何用rownum实现大于、小于逻辑?(返回rownum在4—10之间的数据)(minus操作,速度会受影响) 
788
789SQL&gt; select rownum,month,sell from sale where rownum&lt;10 
790
7912 minus 
792
7933 select rownum,month,sell from sale where rownum&lt;5; 
794
795ROWNUM MONTH SELL 
796
797\--------- ------ --------- 
798
7995 200005 1400 
800
8016 200006 1500 
802
8037 200007 1600 
804
8058 200101 1100 
806
8079 200202 1200 
808
809想按日期排序,并且用rownum标出正确序号(有小到大) 
810
811SQL&gt; select rownum,month,sell from sale order by month; 
812
813ROWNUM MONTH SELL 
814
815\--------- ------ --------- 
816
8171 200001 1000 
818
8192 200002 1100 
820
8213 200003 1200 
822
8234 200004 1300 
824
8255 200005 1400 
826
8276 200006 1500 
828
8297 200007 1600 
830
83111 200008 1000 
832
8338 200101 1100 
834
8359 200202 1200 
836
83710 200301 1300 
838
839查询到11记录. 
840
841可以发现,rownum并没有实现我们的意图,系统是按照记录入库时的顺序给记录排的号,rowid也是顺序分配的 
842
843SQL&gt; select rowid,rownum,month,sell from sale order by rowid; 
844
845ROWID ROWNUM MONTH SELL 
846
847\------------------ --------- ------ --------- 
848
849000000E4.0000.0002 1 200001 1000 
850
851000000E4.0001.0002 2 200002 1100 
852
853000000E4.0002.0002 3 200003 1200 
854
855000000E4.0003.0002 4 200004 1300 
856
857000000E4.0004.0002 5 200005 1400 
858
859000000E4.0005.0002 6 200006 1500 
860
861000000E4.0006.0002 7 200007 1600 
862
863000000E4.0007.0002 8 200101 1100 
864
865000000E4.0008.0002 9 200202 1200 
866
867000000E4.0009.0002 10 200301 1300 
868
869000000E4.000A.0002 11 200008 1000 
870
871查询到11记录. 
872
873正确用法,使用子查询 
874
875SQL&gt; select rownum,month,sell from (select month,sell from sale group by month,sell) where rownum&lt;13; 
876
877ROWNUM MONTH SELL 
878
879\--------- ------ --------- 
880
8811 200001 1000 
882
8832 200002 1100 
884
8853 200003 1200 
886
8874 200004 1300 
888
8895 200005 1400 
890
8916 200006 1500 
892
8937 200007 1600 
894
8958 200008 1000 
896
8979 200101 1100 
898
89910 200202 1200 
900
90111 200301 1300 
902
903按销售金额排序,并且用rownum标出正确序号(有小到大) 
904
905SQL&gt; select rownum,month,sell from (select sell,month from sale group by sell,month) where rownum&lt;13; 
906
907ROWNUM MONTH SELL 
908
909\--------- ------ --------- 
910
9111 200001 1000 
912
9132 200008 1000 
914
9153 200002 1100 
916
9174 200101 1100 
918
9195 200003 1200 
920
9216 200202 1200 
922
9237 200004 1300 
924
9258 200301 1300 
926
9279 200005 1400 
928
92910 200006 1500 
930
93111 200007 1600 
932
933查询到11记录. 
934
935利用以上方法,如在打印报表时,想在查出的数据中自动加上行号,就可以利用rownum。 
936
937返回第5—9条纪录,按月份排序 
938
939SQL&gt; select * from (select rownum row_id ,month,sell 
940
9412 from (select month,sell from sale group by month,sell)) 
942
9433 where row_id between 5 and 9; 
944
945ROW_ID MONTH SELL 
946
947\---------- ------ ---------- 
948
9495 200005 1400 
950
9516 200006 1500 
952
9537 200007 1600 
954
9558 200008 1000 
956
9579 200101 1100</d2>
Published At
Categories with 数据库类
Tagged with
comments powered by Disqus