泛型编程与C标准库_第1页
泛型编程与C标准库_第2页
泛型编程与C标准库_第3页
已阅读5页,还剩33页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、1第1章SQL核心)2345不管你是刚开始写 SQL语句还是已经写过很多年了,学会写岀“好的 SQL这个过程都需要具有很扎实的SQL核心语法和概念根底知识。本章对SQL语言的核心概念及其性能做了回忆,同时还描述了一些你应该已经很熟悉的常用SQL命令。对于那些以前曾经使用过SQL并且根底知识8相当牢靠的读者来说,本章就是一个简要的复习,让你为后面更详细的SQL论述做好准备。如果9你是一位SQL新人,你可能想要先阅读 Beginning Oracle SQL这本书以确保掌握 SQL的根底。不管10是哪种情况,第1章的目的就是通过对 5个核心SQL语句的快速浏览来衡量一下你的SQL水平,同时还了我们

2、用来执行 SQL语句的工具:SQL*Plus111.1 SQL语言12SQL语言最早是IBM公司于20世纪70年代开发岀来的,称为结构化英文查询语言,简称为13SEQUEL。该语言是基于 在1969年提岀的关系型数据库管理系统RDBMS 的。后来因14为商标的纠纷,其简称又进一步缩写为SQL。1986年和1987年,ANSI 美国国家标准化组织帖和ISO 国际标准化组织先后将 SQL语言采纳为标准语言。而人们并不熟悉的是,ANSI官方曾将SQL语言的读音确定为“ S-Q丄。绝大多数人,包括我本人,都还在使用“sequel的读音,只是因为这样读起来更顺口一些。SQL的目的就是简单地提供一个到数据

3、库的接口,在本书这指地是 Oracle数据库。每一条SQL语句对于数据库来说就是一条命令或指令。SQL与其他编程语言如 C或Java的区别就在于它是要处理数据集合而不是一行一行的数据。语言本身也不需要你提供如何导航到数据的指令一一这是在后台透明地进行的。但你将在后面的章节中看到,如果想在Oracle中写岀高效的SQL语句,了解数据及其在数据库中的存储方式,与存储位置是很重要的。由于不同的供给商例如甲骨文、IBM和微软实现SQL核心功能的机制相差无几,所以基于某一种数据库所学的技巧同样可以应用到其他类型的数据库上。你根本上可以利用同样的SQL语句来进行数据的查询、插入、更新和删除,以及创立、修改

4、和删除对象,而不必管数据库的供 应商是哪家。尽管SQL是各种关系型数据库管理系统的标准语言,但实际上它并不一定是关系型的。在本书后面我将就这一点稍作扩展。如果想要了解更多的细节,我推荐大家阅读的?SQL与关系理论?SQL and Relational Theory 一书。需要铭记于心的一点是SQL语言并不总是严格遵守关系模型的一一它根本就没有实现关系模型的某些要素,同时还不恰当地实现了一些要素。事实上,既然SQL是基于关系模型的,那么要想写岀尽可能正确高效的SQL语句,你不仅必须要理解SQL语言,还要理解关系模型。1.2数据库的接口多年以来人们开发岀多种途径来传递SQL语句到数据库并获得结果。

5、Oracle数据库的接口本2地界面是Oracle调用界面OCI 。OCI将由Oracle内核传送而来的查询语句发送到数据库。当使用某种Oracle工具如SQL*Plus或者SQL Developer时,你都在使用 OCI。其他的 ORACLE工具如4SQL*Loader、数据泵Data Pump以及 Real Applicatio n Testi ng RAT既使用 OCI,也可以使5用语言特定的接口,如Oracle JDBC-OCI、ODP.Net、Oracle预编译器、Oracle ODBC 以及 Oracle C+6调用接口 OCCI 驱动器。当使用编程语言如 COBOL或C语言时,你所

6、写的语句被称为嵌入式的SQL语句并且在应用程序编译之前会由 SQL预处理器进行预处理。代码清单1-1是一段可以在C/C+程序块中使用的8SQL语句的例子代码清单1-1C/C+程序块中所嵌入的 SQL语句intEXEC SQL SEI ECT salaiy INTO :aFROM hr.employees HHEISE employee_id IDS;printf('"nie salary is 垃hn",a); 严*/10111213其他工具,例如 SQL*Plus和SQL Developer,都是交互式的工具。你输入并执行命令,然后14获得相应的输岀。 交互式工具

7、并不需要在运行代码前先精确编译,你只需要输入想要执行的命令15即可。代码清单1-2是一段使用SQL*Plus执行语句的例子。16代码清单1-2 使用SQL*Plus执行SQL语句SOL> sele匚t salary2 from hrployees3 where e<nplDyee_id 108;SALARY12000在本书中,为了保持一致性我们所用的例如代码清单都使用SQL*Plus工具,但需要记住的是,不管你是用什么方法或工具来输入和执行SQL语句,所有的事情最后都要通过 OCI来传递到数据库。这里的主旨就是不管你所使用的是什么工具,其本地接口都是一样的。1.3 SQL*Plus

8、 回忆SQL*Plus是一个不管采用哪个安装平台Windows或Unix 都会提供的命令行工具。它是一个用来输入和执行 SQL语句并显示输岀结果的纯文本环境。用该工具可以直接输入、编辑命令, 可以一条条地保存和执行命令或者通过脚本文件来进行,然后将输出结果以很精美格式的报表输岀。要启动SQL*Plus你只需要在主机的命令提示符后敲入sqlplus 即可。连接到数据库有多种方法可以通过 SQL*Plus连接数据库。然而在连接之前,你还需要在$ORACLE_HOME/network/admi n/tnsn ames.ora这个文件中登记想要连接的数据库。有两种通常使用的方法,或者如代码清单1-3所

9、示那样在启动SQL*Plus时提供连接信息,或者如代码清单1-4所示那样在启动SQL*Plus以后使用connect命令。代码清单1-3通过窗口命令提示符连接到SQL*PlusE: piD_Diacle sql>Sqlplus hr(4ota 11 r2SOLPlus: Release +1.0 - Praduction on Sun Jun 6 11:22:24 2021Copyright (c) 19823 2021j Oracle. All rights reserved. Enter password:Connected to:Oracle Database llg Enterp

10、rise Edition Release 14.m - Production With the Partitioning, OLAP and Data Mining and Real Appliation Testing optionsSQL?2345如果想要启动SQL*Plus而又不显示登录到数据库后的提示,可以在启动SQL*Plus时使用6/n olog 选项代码清单1-4 通过SQL>命令连接SQL*Plus并登录到数据库E:pro ora匚le_$q1>$ qlplus /nd1d呂5QL*P1u£; Release- Production on Sun Jun

11、6 11; 22; 24 2021Copyright (C) 1982 2021: Oracle. All lights reserved.SOL> tonnect hroranriEnter password:Connected.SQL>1.3.2 配置 SQL*Plus 环境SQL*Plus有很多的命令可以让你来定制工作环境和显示选项。代码清单 示符下输入help index命令后显示岀来的可用的命令。1-5所示是在SQL提78910111213代码清单1-5 SQL*Plus命令列表1415SOL> help indexEnter Help |topic for hel

12、p.COPYPAUSESHUTDOWN典DEFINEPfilNTSPOOLfDELPfiOMPTSQLPLUSACCEPTDESCRIBEQUITSTARTAPPENDDISCONNECTRE MFRSTARTUPARCHIVE LOGEDITREMARKSTOREATTRIBUTEEXECUTEfiEPFOOTERHMIWGBREAKEXITREPHEADERTTITLEBTITLEGE'IRESERVED HQRD5 (SQL)UNDEFINECHANGEHELPEESERVED WORD、(PL/SIJL)VARIABLECLEARHOSTRUNWHENEVER OSERRORC

13、OLUMNINPUTSAVEWHENEVER SQLERRORCOMPUTELISTSETXQUERYCONNECTPASSWORDSHOK1-6为set命令的帮助文本。set命令是用来定制工作环境的最根本的命令。代码清单代码清单1-6SQL*Plus 的 SET命令5QL> help $etSETSeti a system variable to alter the SQL*Plus environment settings for your current session. For e颐卩 1% to:- set the display width for 曲枸- customize

14、 HTML -formatting- enab1e or disable printin呂 of column headingi- set the number of lines per pageSET 5ystett_variable valuewhere sy5tem_variable and value represent one of the -follciwing clauses:AFPINFOOFF|QN|textARRAYSIZE (15|nAUTOCOMMIT OFF|ON|IMMEDIATE|nALITOPRINT (OFF|0NMJTORECOVERY (OFF|ONJMr

15、nnRAE off | on | th ace only EXPLAIN STATfISTICSNEWPAGE l|n|N0NE null textNUMFORMAT formatNUMWIDTH 10 nPAGESflZE 14 nPAUSE OFF |OIM | textRECSEP NRAPPED|EAKH|OFFBLOCKTERHINATOR |c|ON|OFFCND5EP Je|OFF|QNJCOLSEP CKertC0NC4T Jc|ON OFFCOPYCOMMITC0PYT7PECHECK Oft|OFFDEFINE &|c|ON|CFFDE SCSI 旺 jlJEPTH

16、 l|in ALLLINENUH (OFF|0N (INDENT OFF|ONECHO OFF ONEDITFlLE) file_nmexext)EMBfEDDED OFFOtJERRORLOGGING ON|OFF TABLE schema.tablename TRUNCATE IDENTIFIER ldenti-FierESCfAPE |c|OFF ONFSCCHAR |?|X|$ OFFEXITCQMMIT ON OFF)FEEDfBACK 6 n CN OFFFLAGGER OFF |ENTRY INTERMEDIATE FULLFLJ5H ON|OFFHEADING ON|OFFHE

17、ADSEP |c|0N|0FFINSTANCE instance_path|LOCALLINESIZE 30|n-LQBOFFSET l|nLOGSOURCL pathnameLONG &O|nLONGCHUNK$IZE S0|nNARKJP HTML OFF|ON:HEAD text BODY text TABLE text ENTMAP ON OFFMpOOL OFF ONPREFORMAT OFF|OHSOL>RECSEPCHAR _|cSERVEROUTPUT ON|OFFSIZE n | UNLIMITED FDEMA'I WHIPPED | WORD_WRAP

18、PEO |WOTEDJH5HIFTIN0UT VIS(IELE |INV(ISIBLCSHOWMODE OFF|ON5QLBLANKLINES OFF|ON)SQLCASE (MIXED |LOWER | UPfPER 5QLC0NTINUE > | text SOLNfUMBER (ON|OFF 5QLPLU5OTPATIBILITYSQLPREfFIX f#|cSQLPRCiMPT SQL?|textSQLTERHINATQR ; c|ON|OFFSUF(FIX) SOL|t电Kt(ON|OFFTERMOUT (ON|OFFTIME (OFF|ONTIMIfNG (OFF ONTRI

19、M OUT ON OFF7RIM5POOL (OFF|ON UNDERLINE <-klON|OFF VERIF¥ ON|OFFWRAP (ON|OFFXQUERY BA5EURI text|ORDERlfiCUNORDERED|ORDERED|DEFAULT|NDDEB¥VALUE|BYREFERENCE|DEFAULT|CONTEXT text234567891011有了上面这些可用命令,你就能够很轻松地定制最适合你的运行环境了。但有一点要铭记于心的就是当你退岀或关闭 SQL*Plus的时候,这些设置命令就不再被保存了。为了防止每次使用12SQL*Plus时都重新

20、敲入一遍这些设置命令,你可以创立一个login.sql文件。事实上每次启动SQL*Plus的时候它都会默认去读两个文件。第一个是$ORACLE_HOME/sqlplus/admin 目录下的 13glogi n.sql 文件。如果找到了这个文件,它就会被读进来,文件中的命令语句也会被执行。这样就可以把那些定制你的会话体验的SQL*Plus命令和SQL语句保存起来。14在读取glogin.sql 文件以后,SQL*Plus会进一步寻找login.sql文件。这个文件必须在SQL*Plus的启动文件夹中或者包含在环境变量SQLPATH所指向的文件夹路径中。在login.sql15文件中的所有命令优

21、先级都比glogi n.sql文件中的命令高。从10g开始,Oracle在每次你启动SQL*Plus或者从SQL*Plus里执行connect 命令的时候都会同时去读取glogin.sql和 16login.sql这两个文件。在Oracle脚本10g之前,login.sql文件只有在SQL*Plus启动的时候才会被执行。代码清单1-7是一个常见的login.sql文件内容代码清单1-7一个常见的login.sql文件SET LINES 3000Sets width of display line (default &D characters)SET PACES 1000Sets mim

22、ber of lines per page (default 14 Lines)SET TIMING ONSets display Of elapsed time (defaul,t OFF)SET NULL <null>Sets display af null$ to show <null> (default empty)SET SQLPROMPT & usergfi connect identifier?'Sets the prompt 土心 show tonnected user and instance注意这里在 SET SQLPROMP中使用的

23、变量 _user和_connect_identifier。它们是预定义变量的两个两个例如。你可以在你的login.sql文件中或者任何你创立的脚本文件中使用下面这些预定义变量:_conn ect_ide ntifier_date_editor 这个变量指定了当你使用edit命令的时候启动哪个编辑器_o_vers ion_o_release.privilege_sqlplus_release_user执行命令有两种命令可以在 SQL*Plus中执行:SQL语句和SQL*Plus命令。代码清单1-5和代码清单1-6中所列岀的SQL*Plus命令对于SQL*Plus来说是特有的命令,可以用来定制运行

24、环境,并且可以 运行SQL*Plus特有的命令,例如 DESCRIBE和CONNECT要想执行一个 SQL*Plus命令,你只需在命令提示符后输入该命令然后敲回车,命令会自动被执行。另一方面,如果要执行SQL语句,就必须使用一个特定字符来说明你想要执行输入的语句,分号;或者斜线/都可以。使用分2号的话可以直接放在输入命令的后面或者放在接下来的空行中,而斜线那么必须放在接下来的空行中才可以被识别。代码清单1-8展示了如何使用这两种符号代码清单1-8执行字符的用法SQL?select tflipno, deptno -fron scotwtiere ename = 1 SMITH' EMP

25、NO OEPTNO齐曲20SOL>select eflipno, deptno from scott.emp wtiere enante = 1 SMITH' 2 ;EMPNO OEPTNO736920SOL>select empno, deptno -freini stfltt.emp where ename = 'SMITH' 2 /EMPNO DEPTNO736?20SOL>select efflpno, deptno from scott.emp wtiere enatne = 1 SMITH' 2SQL?/EMPNO OEPTNO73

26、6920SOL>select empnot deptnD +101 scatt.enip where enamE 'SMITH'/2SQL>11* select tmpntij deptna from seott. emp where ename = r SMI TH1 /SQL?/select empnfl, deptno fiom scott.emp where ename = 1 SMITH1/*EEROR at line 1:OflA-00936: misslna expiesslon注意第5个在语句最后面加了一个斜线/的例子。光标移动到了下一行而不是立即执

27、行语456789101112131415句命令。接下来,如果你再按一下回车键,语句就会被放入到SQL*Plus的缓冲器中,但是也不执16行。如果想要查看SQL*Plus缓冲器中的内容,可以使用 list命令也可以简写为I。接下来如果 你想在缓冲器中通过使用斜线/来执行语句尽管斜线/命令本来就是这样来用的 在这里也将会返回一个错误。这是因为你最初在SQL语句的结尾敲入了一个斜线/,而斜线/并不是一个有效的SQL命令,从而在语句想要执行的时候报错。另外一种执行命令的方法是把命令放到一个文件中。你可以在SQL*PIus之外直接用文本编辑器生成这些文件,也可以在SQL*PIus中使用EDIT命令来直接

28、调用编辑器。如果已经有了一个文件,EDIT命令可以翻开这个文件,如果没有的话就会创立新的文件。文件必须放在默认文件夹中,否 那么你必须指定文件的全路径。想要设定所选择的编辑器,你只需要利用命令define _editor= ' /vfull path>/myeditor.exe '来设置预定义变量 _editor 。具有.sql 扩展名的文件在执行的时候不必敲入扩展名,通过START命令都可以执行。代码清单1-9中列岀了这两个命令的用法。代码清单1-9执行.sql脚本文件SOL> ilist_deptsDEPTNO DNAMEL0<10 ACCOUNTINGM

29、Ekl YORK20 RESEARCHDALLAS30 SALESCHICAGO40 OPERATIONSBOSTONSOL>SQL> start list_d即材DEPTNO DNAMEL0匚10 ACCOUNTING'JEW YORK20 RESEARCHDALLAS30 SALESCHICAGO40 OPERATIONSBOSTON$QL> SQL>1i* &elect * from scott+d即t SQL>SQL*Plus具有很多特性和选项,以致于多得在这里不能一一列举。就本书需要而言, 这种概述就已经足够了。 但是,Oracle文档对

30、SQL*Plus的用法给岀了指导,而且很多的书,比方BeginningOracle SQL,都对SQL*Plus作了更为深入的阐述,如果感兴趣你可以参考1.45个核心的SQL语句SQL语言有很多不同的语句,但在整个职业生涯中,你可能只会用到其中很少的一局部。不过你所使用的几乎其他任何产品不也是这样的吗?据说有一个统计结果是,绝大多数人都仅使用8了他们常用的软件产品或编程语言所有功能的20%甚至更少。我不知道这个统计真实与否,但以9我的经验来看,这似乎是很准确的。我发现同样的根本SQL语句格式在大多数应用中使用了将近1020年了。极少数的人使用过 SQL提供的所有功能一一即使对于那些他们确实经常

31、使用的功能也常11常用得不是很恰当。显而易见,我们不可能覆盖SQL语言的所有语句以及它们的选项。本书的目12的在于让你能够深入理解那些最常用的SQL语句并帮助你更高效地使用它们。13在本书中,我们将重点讨论 5个最常用的SQL语句,它们分别为SELECT、INSERT、UPDATE、DELETE以及MERGE尽管这些核心语句都将逐个讲解,但重中之重还是SELECT语句。将这5个语句用好了将会为你在日常工作中用好SQL语言打下坚实的根底15161.5 SELECT 语句SELECT语句用来从一个或多个表中或者其他数据库对象中提取数据。你应该已经很熟悉 SELECT语句的根底知识了,所以我将不再从

32、一个初学者的角度来介绍SELECT语句,而是首先回顾一下SELECT语句的执行逻辑。对于如何来写一个根本的SELECT语句你应该已经学习过了,但为了培养根本的思维模式,你要一直是写出符合语法规那么的高效SQL语句,你需要理解 SQL语句是如何执行的。一个查询语句在逻辑上的处理方式可能会与实际物理处理过程大相径庭。Oracle基于查询成本的优化器(cost-based optimizer , CBO )用来产生实际的执行方案。我们在后面的章节中将会讲 解优化器是干什么的,如何来实现其功能的以及为什么要进行优化。目前,我们需要关心的是优 化器将会决定如何访问表、按照什么样的顺序来处理它们,以及如何

33、将多个表联结起来及如何使用筛选器。查询的处理在逻辑上是按照特定的顺序进行的,但是,优化器所选择的物理执行方案 可能会按照完全不同的顺序来实际执行这些步骤。代码清单1-10是一段包含SELECT语句的主要子句的查询片段,在其中标出了每一个子句的逻辑处理顺序。代码清单1-10查询语句的逻辑处理顺序5select<Colnnn listJ1FROH<source object lists1.1FROM<left source object? <joiiJOIN <right source objects ON2UtiERE<where predicates3GRO

34、UP BV<group by expression(s)>4HAVIWC<having predicates?6ORDER BY<ordei by list>| typ亡?<on predicates>你应该立刻注意到 SQL有别于其他编程语言的一点在于首先处理的并不是写在第一行的语句SELECT语句,而是FROM子句。注意在这个代码清单中我给岀了两个不同的FROM?句。标2记为1.1的那个FROM?句表示的是当使用 ANSI语法时的不同。我们可以把处理过程中的每一个步3骤想象为生成一个临时的数据集。随着每个处理步骤的进行,这个数据集被不断地操作直到生

35、成4最终的处理结果。查询返回给调用者的就是这个最终结果数据集。5为了更详细地了解 SELECT语句的每个局部,你可以参考代码清单1-11所示的查询语句,该6语句返回的结果集为下订单超过4次的女顾客的列表。代码清单1-11下订单超过4次的女顾客查询语句SQL> select c.eustomer_idT codnt(D.Drder_id) as orders_ct2 frcni oe .customers c3 join oe.ciders 04 on c,customer_itl = o.cus5 where c,gender = 'F1f> group by e.eust

36、CMiier_id7 having count(o+orderid > 4g order by ordei£_£tf c.custoflier_id9 /CU$TOMER_ID ORDERSCT146 5147 51.5.1 FROM 子句FROM子句列岀了所查询数据的源对象。这个子句可以包含表、视图、物化视图、分区或子分区,或者你可以建立一个子查询来生成子对象。如果使用了多个源对象,其逻辑处理阶段也将会应用到每一个联结类型以及谓词ON如步骤1.1所示。在本书后面的章节中你将会进一步了解78910111213141516联结类型的更多细节,但注意在处理联结语句的时候是

37、按照下面的顺序来进行的:(1) 交叉联结,也称为笛卡儿乘积;(2) 内联结;外联结在代表清单1-11所示的查询例子中,FROM子句列岀了两张表:customers 和orders ,通过customer_id列来联结。因此,当处理这一信息时,FROM子句所生成的初始数据集将会包含这两张表中customer_id相匹配的行。在本例中结果集将会包含105行。为了验证这一点,只要执行例子中的前4行,如代码清单1-12所示。代码清单1-12 截止到FROM子句的局部查询语句的执行SOL> Select c.cjstomer_id cu5t_idJ D.Diier_id ard_id, c.gen

38、der2 from oe.custofliers c3 join ce,orders o4 on e,tustoffler_id = o.cijstoffleir_id;ID0l!0 IDGCU5T ID ORD IDGCUST_IOORD_IDG1472450F10124301092394M1472425F1C1?413115M14723S5F1012447rt11624261472J66F101245S1162369M1472396F102243111624361482451 N1022414 N1172456 N1482426 M1022432 M1172429 M148M1022397

39、 M1172370 M1482367 M1Q32437 F1172446 H148240« M1032415 F1182457 N1492452 M1032433 F11S2371 M1432427 M1032454 F1202373 M149238? M1042438 F12123 7+ M14323翎«1Q42416 FXll2375 M1492434 M1042J55 F1232376 F1502388 M1Q42354 F1412377 M1512385 M1052439 F1432380 N1522390 n1052417 F1412445 N1532391 M1

40、052356 F14斗2422 M1542392 F1052358 F14423S2 N1552393 M1062441 M14423&3 M1562395 F1062418 N1442435 N15723無H1Q6235$ M1452443 M15S2399 K1062381 M14 S2421 M1592400 M1072442 F1452383 N1602401 M1072419 F1452364 M1612402 M1072360 F1452455 M1622403 rt1072440 F1192372 M1632404 M1082443 *11422373 N142405 M

41、1QB2420 M146244? F1652407 M10&2361 M1462424 F16624OB F1083357 N1462384 F167左4旳M1Q9立444 M1462365 F1692411 F1092421 N146切9 F1702412 M1的2362 M16S2410 M105 rends selected.12345678910注意为了使之很好地适应页面我手工调整了输岀结果,实际输岀结果在页面上超过105行。111.5.2 WHERE 子句12WHERE子句提供了一种方法,可以按照条件来限制查询最终返回结果集的行数。每个条件或13者谓语都是以两个值或表达式相比

42、拟的形式岀现的。比拟的结果要么是匹配值为TRUE要么14是不匹配值为FALSE o如果比拟的结果是 FALSE,那么相应的行不会被包含在最终结果集中。这里我需要稍微偏离一下主题,来谈一谈与这一步相关的SQL中的一个重要方面。事实上,SQL中逻辑比拟的可能结果是 TRUE、FALSE以及未知。当其中包含空值null 的时候比拟的结果就会是未知。空值与任何值比拟或者用在表达式中都会得到空值,或者是未知。一个空值代表 一个相应值的缺失,并且可能因为SQL语言中的不同局部对空值的处理不同而令人费解。关于空值是如何影响SQL语句执行的话题将会贯穿本书,但在这里我不得不先提及一下这个话题。我之 前所说的还

43、是根本正确的,一个比拟的返回值将会是 TRUE或者 FALSE。你会发现当进行筛选的比较条件中包含空值的时候,将作为 FALSE来对待。在我们的例子中,只有一个将结果限定为下了订单的女性消费者的谓语。如果你查看FROM子句执行之后的中间结果见代码清单1-12,你会发现105行中仅有31行是由女性消费者所下的订单gender =F'因此,在应用了 WHERE?句以后,中间结果集将从105行减少到31行。应用WHERE?句以后得到了更精确的结果集。注意,在这里使用的是“精确的结果集。我的意思是说现在已经得到了能够满足你查询需求的数据行。其他子句GROUP BY, HAVING也许可以用来聚

44、合并且进一步限制调用程序会接收到的最终的结果集,但需要注意的很重要的一点是,目前已经得到了查询计算最终结果所需的所有数据。WHERE?句的目的是限制或者减小结果集。你所使用的限制条件越少,最终返回的结果集中包含的数据就会越多。你需要返回的数据越多,执行查询的时间也就越长。1.5.3 GROUP BY 子句GROUP BY子句将执行FROM和WHERE?句后得到的经过筛选后的结果集进行聚合。查询岀来的结果按照GROUP BY子句中列岀的表达式进行分组,来为每一个分组得岀一行汇总结果。你可以按照FROM子句中所列岀对象的任意字段进行分组,即使你并不想在输岀结果列表中显示该列。相反,select列表

45、中的任何非聚合字段都必须包括在GROUP BY表达式中。GROUP BY子句中还可以包含两个附加的运算:ROLLUP和CUBE。ROLLUP运算用来产生局部求和值,CUBE运算用来求得交互分类值。当你使用这两种运算中任意一个的时候,你将会得到4不止一行的汇总信息。在第7章中将会对这两个运算进行更详细的讨论。5在例如查询中,需要按照customer_id来进行分组。这就意味着对于每一个唯一的6customer_id只会返回一行值。在WHERE?句执行后所得到的代表下订单的女性消费者的31行订单中,有11个独特的customer_id 值,如代码清单1-13所示。代码清单1-13 截至GROUP

46、BY子句的局部查询执行-I . , -I . I i -I102 from customers c3 join oe.orders a4 on c+U5tCHneT_icl = o+customer_id:.:! :- .- I 'I '11CUSTOMER_IO ORDERS_CT121314156 group by c+custon*er_id;156111661154116911054103 41074104 4147S146511 rows aelectel.你会发现查询的结果是经过分组的,但并没有排序。外表上看结果好似是按照order_ct 字段排序的,但这仅仅是个巧

47、合而不是确定的行为。需要记住的很重要的一点是:GROUP BY 子句并不确定结果数据的排序。如果你需要结果按照特定的顺序排列,那么必须中指定一个order by子句1.5.4 HAVING 子句HAVING子句将分组汇总后的查询结果限定为只有该子句中的条件为真的数据行。除非你使用HAVING子句,否那么将返回所有的汇总行。事实上,GROUP BY子句和HAVING子句的位置是可以互换的,谁先谁后都无关紧要。但是,似乎在编码中将GROUPBY子句放在前面更有意义一些,因为GROUP BY子句在逻辑上是先执行的。从本质上来说,HAVING子句是在GROUP BY子句执行后用来筛选汇总值的第二个WH

48、ERE子句。在我们的查询例子中,HAVING子句HAVING COUNT(o.order_id) > 4,将分组数据从11行减少到2行。这一点你可以通过查看 GROUPBY子句应用后返回的结果行来确认,如代码清单1-13所示。注意仅有146和147号消费者所下的订单数超过4次。这样就产生了组成最终结果集的两行数据。1.5.5 SELECT 列表SELECT列表列岀查询的返回最终结果集中需要显示哪些列。这些列可以是数据表中一个实际的列、一个表达式,或者甚至是一个SELECT语句的结果,如代码清单1-14所示。代码清单1-14 展现SELECT列表各种可能情况的查询实例SQL> sc

49、1 cct c.customc r_id? c.cust_fi rs t_ n a me|' ' |c.cust目航2 (select e+last_name -fron hr*employees w where e+efliployee_itl = c.account_mgr_id) a" t_mgr)3 from oe.custonners c;CUSrOHER_I& CUST_NAMEACCT_MGR147 Ishtwarya RobertsRussell匚ambrauLt Cambrault148 Gustav SteenburgenRussell羽1

50、 Buster Edwards 9B1 Daniel Gueriey 31 lows selected.当使用另外一个SELECT语句来产生结果中的一列的值的时候,这个查询必须只能返回一行一列的值。这种类型的子查询被称为标量子查询。尽管这可能是一个非常有用的语法,但需要牢5记于心的是标量查询在结果集中的每一行结果产生时都要执行一遍。在某些情况下可以进行优化以减少标量子查询的重复执行,但更糟糕的场景是每一行都需要标量子查询执行。你可以想象如6果你的结果集中有几千行甚至上百万行数据的时候所需要付岀的查询代价!在后面的章节中我们还将回忆标量子查询并讨论如何更好地来使用它们。在SELECT列表中你还有

51、可能用到的一个选项是DISTINCT子句。在例子中并没有使用它,但 7我想要简要地提及一下。DISTINCT子句用来在其他子句执行完毕以后从结果集中去除重复的行。SELECT列表执行完以后,你就得到了最终的查询结果集。所剩的唯一需要做的事情,如果8包含了的话,就是将查询结果集按照所需的顺序排序。1.5.6 ORDER BY 子句ORDER BY子句用来对查询最终返回的结果集进行排序。在本例中,需要按照orders_ct 和 °customer_id进行排序。orders_ct这一列是通过GROUPBY子句中的COUNT聚合函数计算得到的值。如代码清单1-13中所示,有两个消费者的订单

52、超过4个。由于这两个消费者的订单数都是5份,orders_ct这一列的值是相同的,所以要由第二个排序列来确定最终结果的显示顺序。如代 11码清单1-15中所示,该查询的最终经过排序的输岀结果是按照customer_id排序的两行数据集。12代码清单1-15 例如查询的最终输岀131415SQL> select c.eustomeidj cotint(D.Drder_id) as orders_ct2 froni oe customers c3 join oe.cider5 04 on c,cu5tomer_id = o,custon*er_id5 where engender = 

53、9;F1f> group by e.eusttjfner_id7 having count(Q+orderid > 4g order by Drdei£_ctf c.custofliei_id9 /CU$TCWER_IC ORDERSCT146 5147 5当输岀结果需要排序的时候,Oracle必须在其他所有子句都执行完之后按照指定的顺序对最终结果集进行排序。需要排序的数据量大小是非常重要的。我这里所说的大小是指结果集中所包含的总字节数。你可以通过用行数乘以每一行的字节数来估计数据集的大小。每行所包含的字节数通过将选择列表中包含的每一列的平均长度相加来确定。上面的查询实例在选择列表中仅需要列岀customer_id 和orders_ct两列的值。我们可以估算每一行输岀值的字节数为10。在第6章中我将阐述从哪里能找到优化器所估计的值。因此,如果我们在结果集中只有两

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论