版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、软脑软件北京公司S QL 编 写 及 其 优 化 培 训温有飘2005年4月28日本培训包含的内容如下: 41. 表、索引相关知识及其在数据库内部相关的物理存储 41.1. 数据库中最小的物理存储单位:块 (block) 41.2. 表数据在块中的存储以及RowId 信息 41.3. 索引 41.4. Bitmap 索引介绍 52. 数据库查询操作的内部处理过程 62.1. 数据库的数据读取是以块为单位的 62.2. 查询操作内部过程以及索引的作用 62.3. 执行计划概念 72.4. 排序处理过程以及各种引起排序的操作 72.5. 多表join 操作的内部过程 73. 写 SQL 语句时在性
2、能方面的目标 83.1. select 列表中减少不需要的数据 83.2. from列表中去除不需要的表 83.3. where 条件中应该考虑到索引的使用,防止一些写法 83.3.1. 防止过滤字段中套用函数,如果必须,则考虑函数索引 83.3.2. 防止把列放入表达式中去比较 93.4. 防止不需要的排序 93.5. 防止数据类型的隐式转换 93.6. 程序代码中的注意点 103.6.1. 由多个 SQL 语句完成的一个操作尽可能写成一个SQL 就完成, 防止分解103.6.2. 使用数据库提供的约束来判断某些错误,如唯一性104. SQL 语句知识 114.1. SQL 语句串讲 114
3、.1.1. select f1 from A 114.1.2. select f1 from A where f2=v_1 114.1.3. select f1 from A order by f2 114.1.4. select sum(f1) from A 124.1.5. select f2,sum(f1) from A group by f2 124.1.6. select a_f2,b_f2 from A,B where A.f1=B.f1 124.1.7. Select * from report where SALES_CODE in (select SALES_CODE fro
4、manken where:.); 144.1.8. Select * from report where SALES_CODE exists (select 1 from ankenwhere );144.1.9. in,exists 的选择 144.1.10. select yadfw as t1,kopeew as t2 From A union all select uufger as t1,poeprvcx as t2 from B 144.2. 几种常见操作或函数 154.2.1. 比较符 like 154.2.2. is null ,isnot null 154.2.3. to_c
5、har,to_date,to_number 154.2.4. nvl 154.2.5. 其他 165. 表设计的一些建议 16参考文献 16本培训包含的内容如下:表、索引相关知识及其在数据库内部相关的物理存储;数据库查询操作的内部处理过程;写SQL语句时在性能方面的目标;SQL语句知识;表设计的一些建议下面阐述的内容以 Oracle为例来讲述的,在排版方面可能有不妥当的地方,或有些内容前 后重复,但各种知识应该比较容易理解和接受;1 .表、索引相关知识及其在数据库内部相关的物理存储1.1. 数据库中最小的物理存储单位:块(block)数据库最小的物理存储单位是块9i默认是8k,每个块只能属于一
6、个表;一行数据插入时会占用块中的一些存储,当块不能再容纳新数据时,则将启用新的块存储数据;数据缓冲池1.2. 表数据在块中的存储以及 RowId信息表的字段除了设计者设计的字段外, 还有个字段Rowid ; RowId是oracle为每个表自动 增加的一个字段。当表中插入一行记录时,此记录在块就有一个唯一的物理位置, 这个位置信息就保存在此行记录的RowId字段;1.3. 索引表中记录的存储顺序是以先后插入顺序存储的,在一个数据量很大的表中, 如果不引入其他的手段,每次查找小部分记录都是从第一条扫描到最后一条,这样,系统将慢得不能使用;使用索引可以有效解决问题;如图:Report表(100万条
7、记录)RowIdSession_codeSales_codeEmployee_codeJAaNs1AAQAAA7yTAah100061000017AAANslAAYAAAAmWAAX0007100015。 索引Employee_codeRowd_ |517AAANslAAYAAAAmWA aaansiaaqaaATytAA索引的本质用途是通过它使读取进程在扫描源表时的数据块范围大大减小了,因此性能 大幅度提高;一般情况下,当检索的记录与所有记录数比较 <=4%时,索引是很有效的,当比例更大 时,索引反而有可能降低性能, 因为即使使用了索引, 读取进程还是扫描了大部分的表 中的块,如果这样
8、,倒不如不用索引直接扫描源表,因为减少了读取索引的块的开销;当索引建好后,oracle优化器在执行sql时会选择是否使用索引,所以设计表者不用担 忧此索引会影响检索性能;创建索引的标准是那一列是否经常在where条件中出现,否则不应该建立,因为,每次表记录的增加、删除以及修改那个字段值时,还要维护索引,增加了开销;此节讲的索引叫 B_tree索引,在内部存储中类似树状结构,有枝和叶,枝是 oracle内 部存储的一些连接数据,叶才存储实际的值,如图:表中每条记录只要那个列是非NULL值,在索引中都有一个条目entry来存储如上图,类似于表在块中一条条记录存储;1.4. Bitmap索引介绍当表
9、中某列的distinct值比较少时,使用 B_tree索引效率就不高了,因为以此列来做 where条件过滤的话,结果集很可能超过总记录数的4%,正如前面说过的,超过 4%记录使用B_tree索引,效率反而下降。使用Bitmap位图索引可以解决这个问题;Bitmap索引使用一个位图来记录数据情况,举例:商品表product,有一个字段color存储颜色值,在所有商品中最多就10种不同的颜色,创建的位图图示如下:Indexstart ROWIDA A AK Al A AI A ft AC AAAROWIDAMKMhAIAAAFNOARq AAAKAIAMAMFNQARq aAAEAI AAIAAA
10、F HQ ABq kAAIAlbitmap100010010GQ1001D1CO> OCOIOIQDOOI0Q100QC0> 310OOCOailQO0QO10Cl> ooiooaioooooiooooio?其中,Start ROWID是表中的第一条记录的物理地址,end ROWID是表中最后一条记录的物理地址,bitmap是一张位图,存储一连串的0或1;列值为blue的bitmap中,每个bit的位置在源表中都能找到某个位置与它一一对应,它们在各自对象中的相对位置一样。bit值为1时,则源表对应位置那个 rowid所在的记录的color字段值为blue',为0时,则
11、非blue'值;类似的,Green, Red, Yellow 都有各自的bitmap;试想,当where条件中有过滤条件 A and B,条件A可以使用B_tree索引,条件B 可以使用bitmap索引,那么从A条件中可以得到一个 RowId的集合,从B条件也可以 得到RowId结合,这样,只要从第一个rowid集中去除第二个rowid集中的值,得到结 果集Rowid ,我们就可以从源表得到数据了;Bitmap使用了压缩技术,节约了存储,并且在一个bitmap上对某个位bit的值是1还是 0时速度是非常快的;2 .数据库查询操作的内部处理过程2.1. 数据库的数据读取是以块为单位的Or
12、acle读取表中的数据时,是以整个块为单位的,有可能一次读多个块;从索引中得到 rowid的物理位置时,也要把含rowid这个位置的块从磁盘中读出, 然后才处理个别行;2.2. 查询操作内部过程以及索引的作用举仞ij: select * from personal_function where employee_code= -200 ;上述查询,如果 employee_code上没有索引,则会把 personal_function表数据的块全部 读入内存中,同时从第一条记录查到最后一条记录,对符合条件的记录返回给用户;如果employee_code有索引,则使用索引检索出含符合条件的Rowid
13、的块读入内存,然后定位到rowid指示的位置上把记录返回给用户;2.3. 执行计划概念2.2节中,如果 employee_code=-200的记录数在占总记录数超过4%,则有可能就不会用索引查找,而是直接全表扫描,这是oracle的优化器经过各种检测后会自动选择的;Oracle对已存在数据统计特征会选择不同的执行路径或者全表,或者使用索引等,这就产生了不同的执行计划,使能到达最大的性能。执行计划选择的模式有RBO和CBO方式,采用CBO方式时(这是oracle公司强烈建议使用的),sql语句中from后表的先后顺序以及 where条件中各个条件的先后顺序变得 不是很重要了,如果 RBO方式则不
14、然;CBO全称 Cost-based Optimizer,基于代价的优化。 2.2节提到的 SQL语句,Oracle是 否使用索引,其内部会做各种比较,然后自动做出选择;为了使 Oracle做出更精确的 比较,我们应该周期性地对表进行统计,使 Oracle 了解到真实情况后做出更准确的判 断。因为要统计,所以称之为基于代价;RBO全称Rule-based Optimizer,基于规则,就是说 Oracle定义的一套执行先后顺序, 如,有索引则一定会用索引,就如 2.2节的SQL语句,但这样有时并不是最好的执行 选择。2.4. 排序处理过程以及各种引起排序的操作举仞ij: select * fr
15、om personal_function where employee_code= -200 order by func_name;由2.2节可知,如果没有 order by语句时,oracle只要检索到一条符合条件的记录就立 刻返回给用户,直到所有数据返回完毕。当有 order by时,情况就不一样了,oracle会把检索到的每一条记录先保存在一个用于排序的内存中,当所有符合条件的记录在那个区域完成排序后,再返回给用户;通过排序这个操作,oracle中间多处理了一个步骤。数据量越大,排序时间则更长,当 数据量到达所找的内存区域无法容纳时,将使用磁盘做为临时排序区,此时,性能会大大降低,用户将
16、等待更长的时间才能得到返回的结果;因此,在一个 SQL语句中,如果对返回的记录集没有顺序要求时,应该去除引起排序 的语句;弓I起排序的操作有:order by, distinct, union , group by2.5. 多表join操作的内部过程举例说明:Esm系统中的3张表结构如下:Employee:EMPLOYEE_CODE职员代码EMPLOYEE_NAME职员名称EMPLOYEE_KANA职员全称Emp_detialEMPLOYEE_CODE职员代码DepartDepart_CODE部门代码DEPART_NAME部门名称DEPART_CODE职员部门代码现在要求列出所有职员的名称和其
17、对应的部门名称,SQL语句如下:select aa.employee_name,cc.depart_namefrom employee aa,emp_detail bb,depart ccwhere aa.employee_code=bb.employee_code and bb.depart_code=cc.depart_code;执行时,oracle可以选择如下的一个执行计划可参考4.1.6节的流程图:Employe 表数据emp_detaildepart00001张三00002李四00003王五00002100、0000320000001300200开发2部300开发3部100开发1部1
18、) 读取employee的第一条记录,得到职员代码 A;2) 再在emp_detail查找职员代码为 A的第一条记录,得到部门代码 B;3) 在表depart中查找部门代码为 B的记录;4)在各个表的记录中中取出需要的信息返回给用户;5) ooo 2步和1步是个循环操作,2步嵌套于1步中,直到所有信息返回给用户;Oracle如果有其他的执行记录更好的话,会选择其他的;3. 写SQL语句时在性能方面的目标3.1. select列表中减少不需要的数据select列表需要的信息应该按需索取,不能因为图方便用 *'把所有字段内容取到客户端,这样,既增加服务器的负荷,又增加网络流量;3.2. f
19、rom列表中去除不需要的表出现在from后的表,oracle都会对它检索并与其他表进行join操作,如果把不需要的表不经意间放在了 from后面,可能会增加几倍甚至几十倍的负荷;如果 where条件中也没有加上进行join的条件,oracle将对它进行笛卡儿乘积的 join ,这种负荷可想而知;3.3. where条件中应该考虑到索引的使用,防止一些写法3.3.1. 防止过滤字段中套用函数,如果必须,则考虑函数索引举例:统计在某天的日报登记个数,其中,某天这个值V_date是从程序外面以参数的形式传递进去的字符串,格式如yyyy-mm-dd ;比较两种写法:第一种:Select count(*
20、) from report where to_char(day, yyyy-mm-dd )=V_date第二种:Select count(*) from report where day=to_date(V_date , yyyy-mm-dd ) ;必须选择第二种,因为如果day 上有索引,而day 作为函数 to_char 的参数, oracle将不使用它的索引, 因而进行全表扫描, 这样的后果是, 也许 2 秒内就能统计出来的结果,却可能要花几十分钟甚至几小时; report 表数据量越大,比照结果就更明显;有些情况确实需要使用函数,如:取出职员名称为 V_name 的职员代码,而V_na
21、me是从程序外面传进去的参数;由于在最初增加职员记录时, 每个存入的职员名称没有做大小写转化, 比方, 最初登 陆了一个ZhanSan'的职员,此时 V_name传进来的是zhansan,如果用如下语句查询将得不到记录:Select employee_code from employee where employee_name=V_name ;可使用如下语句Select employee_code from employee where UPPER(employee_name)= UPPER (V_name);此时由于套用了函数UPPER 而列 employee_code 上的索引将不
22、被使用,可以考虑创建函数索引,就是把UPPER(employee_name) 当成一个字段去创建索引,当查询时,则会使用此函数索引;3.3.2. 防止把列放入表达式中去比较请看下面 2 条语句:Select * from A where f1/5>300 ;Select * from A where f1>300*5 ;必须使用第二种,否则,如果f1 有索引,第一种情况将不使用;3.4. 防止不需要的排序2.4 节中已说明排序需要额外的负荷,所以,当不需要排序时,应该防止;3.5. 防止数据类型的隐式转换举例:表 A ,有一字段code , varchar2 类型,此字段存储的值都
23、是由数字组成的串;SQL 语句:Select * from A where code=v_number ; 其中, v_number 是由程序外面传入的数值;因为 v_number 是数值,而code 是 varchar2 类型,所以, Oracle 会进行类型的隐式转换,把此语句转化成如下形式执行:Select * from A where to_number(code)= v_number ;把列嵌套在函数里索引不能使用 ,这个是我们不期望的,所以正确的做法是我们应该进行显式的转换:Select * from A where code=to_char(v_number) ;3.6. 程序代
24、码中的注意点3.6.1. 由多个 SQL 语句完成的一个操作尽可能写成一个SQL 就完成,防止分解举个例子:需要得到 2004 年中,每个季度(1-3 月, 4-6 月, 7-9 月, 10-12 月 ) 的日报个数;第一种方法:比较容易想到的,用 4 个 SQL 语句分别去得到各个季度的统计:Select count(*) from report where day>=to_date(2004-01-01 , yyyy-mm-dd ) and day<=to_date( 2004-03-31 23:59:59 ,yyyy-mm-dd hh24:mi:ss ) ;Select co
25、unt(*) from report where day>=to_date(2004-04-01 , yyyy-mm-dd ) and day<=to_date( 2004-06-30 23:59:59 ,yyyy-mm-dd hh24:mi:ss ) ;Select count(*) from report where day>=to_date(2004-07-01 , yyyy-mm-dd ) and day<=to_date( 2004-09-30 23:59:59 ,yyyy-mm-dd hh24:mi:ss ) ;Select count(*) from re
26、port where day>=to_date(2004-10-01 , yyyy-mm-dd ) and day<=to_date( 2004-12-31 23:59:59 ,yyyy-mm-dd hh24:mi:ss ) ;第二种方法:一个SQL 语句完成SelectCount(case when day>=to_date( 2004-01-01 , yyyy-mm-dd ) to_date( 2004-03-31 23:59:59 ,yyyy-mm-dd hh24:mi:ss ) as one,andday<=Count(case when day>=to_
27、date( 2004-04-01 , yyyy-mm-dd ) to_date( 2004-06-30 23:59:59 ,yyyy-mm-dd hh24:mi:ss ) )as second,andday<=Count(case when day>=to_date( 2004-07-01 , yyyy-mm-dd ) to_date( 2004-09-30 23:59:59 ,yyyy-mm-dd hh24:mi:ss )as third,andday<=Count(case when day>=to_date( 2004-10-01 , yyyy-mm-dd )an
28、dday<=to_date( 2004-12-31 23:59:59 ,yyyy-mm-dd hh24:mi:ss )as forth,From report ;显然,第二种方法可以提高4 倍的性能;要到达这种转化,编码人员需要对数据库提供的 SQL 函数有充分的认识;3.6.2. 使用数据库提供的约束来判断某些错误,如唯一性有种情况,应用程序中经常出现,举个例子:有张全国居民身份表resident, 其中有个字段身份证号码ID_card , 是主键, 在登记一个居民时,为了防止发生主键冲突,应用程序往往保存之前用一个SqL 语句去查此ID_card 号是否已存在,存在则提示ID_car
29、d 冲突。上述情况完全可以防止使用写 SQL 语句的方法去查,因为 oracle 的每个错误都有一个唯一的错误号,只要在程序中去捕捉违例 (exception) ,然后进行比照是否是主键冲突即可;有些时候非主键的字段也要保持唯一性, 则可以使用唯一索引。 当发生唯一性冲突时,也有一个错误号;Oracle 在自身版本升级的时候,错误号的含义是向后兼容的;4. SQL 语句知识4.1. SQL 语句串讲4.1.1. select f1 from A这是一个最简单的 SqL 语句,想象一下A 表的块读入内存,然后从第1 条记录扫描到最后一条记录且每次立刻把f1 字段值返回给用户,这个过程是全表扫描;
30、Sql 语句中,有列别名和表别名,对很长表名或列名可以简化操作,如:表别名: Select aa. STATUS from REGULAR_REPORT_CONTENTS aa ;表别名前不应该使用as, SQL SERVER 支持,但 Oracle 里不支持;列别名: Select MODIFIED_STATUS_CODE_OUT as mod from TIMEBOOK_LOG;程序代码中引用的时候就可以使用 mod ,而非长串;如果在连接表中有同名表的时候,别名是必须的;4.1.2. select f1 from A where f2=v_1如果 f2 无索引,则第4 1 1 节中每次扫
31、描到一条记录时会根据条件进行过滤,符合条件则立即返回给用户,否则扫描下一条;F2 有索引且使用时,则从索引开始扫描,扫描时不象表一样从第一条目扫描到最后一条, oracle 会根据内部算法很快定位到符合条件的条目, 读取 Rowid 后根据物理地址定位到源表的记录上立即返回给用户, 然后再在索引中定位到第二个符合条件的条目,直到全部;4.1.3. select f1 from A order by f2在 4.1.1 节中讲到的每扫描的记录立即返回给用户,而当有排序时,则先发送到一个排序区中进行排序,等所有记录扫描完后,再把排序区中的数据集返回给用户;当 select 后带 distinct
32、时, 内部处理也有排序操作, 更靠近 distinct 的字段就更先排序,同时在排序过程发现有各个字段信息完全相同的行时, 只留一条记录, 废除其他相同的;排序完成后,再把排序区中的数据集返回给用户;4.1.4. select sum(f1) from Aoracle 处理时类似这样:使用一个变量V ,初始值0,每次扫描一个记录时,v=v+f1 ,直到扫描到最后,把v 返回给用户;类似的,函数avg,max,min,count 原理差不多,如果f1 有索引时,可能会扫描索引而不扫描表,因为索引的块更少,而且包含了需要的全部信息;4.1.5. select f2,sum(f1) from A g
33、roup by f2上节中是把f1 值加如到一个变量中,这里多了一个字段,可以这样理解:每扫描一条记录时,如果f2 值未出现过,则定义一个数组变量A , A1=f1 , A2=f2 ;如果 f2值以前出现过,则把当前f1 值增加到对应的数组变量中,这样,直到表扫描完毕,按 f2 字段分组的各个统计值都记录在了一堆的数组中, 最后, oracle 把数组的各个值按记录的方式返回个用户;Oracle 在处理每当一个新的 f2 的值出现时, 对应 f2 的数组变量都会按f2 值由小到大排序,因此,排序结果集中是按f2 排序的,用户无须再排序;分组语法中,在select列表中出现的非统计字段,者B要在
34、group by后出现;有时候需要对统计的结果进行过滤,例如 select f2,sum(f1) from A group by f2 中,用户只需要 sum(f1)>10000 的组的统计,这时用 having 过滤条件,如下:select f2,sum(f1) from A group by f2 having sum(f1)>10000where 条件是针对记录的过滤,被过滤掉的数据不参与统计。 having 是针对统计完成后,统计结果返回给用户时的过滤;4.1.6. select a_f2,b_f2 from A,B where A.f1=B.f1oracle 对连接 jo
35、in 的操作的内部处理过程,可以参考下列图:上图的流程只是执行计划当中的一种,但可以借助于理解, 当多于2张表时,情形是上述的连接也称内连接,其他连接还有左连接,右连接和全表连接的方式;左连接:select a_f2,b_f2 from A,B where A.f1=B.f1+,必须首先扫描 A 表以驱动 B扫描。此时,A标示的地方,如果针对 A表的一条记录,在 B表中1条也没有找到 符合条件的记录,则会把 A.f1值和以NULL值作为B.f1的值返回给用户;这样, A 表中的所有记录的且在select列表中的信息都会返回给用户;右连接:select a_f2,b_f2 from A,B wh
36、ere A.f1+=B.f1 ,首先扫描 B 表以驱动 A 扫描,其他操作可参考左连接;全连接:select a_f2,b_f2 from A full outer join B on A.f1=B.f1 ;它的记录集是 select a_f2,b_f2 from A,B where A.f1=B.f1的结果集加上A表中有,但在 B表中未找到符合条件的记录的集合B表中的信息是以Null值返回,再加上B表中有,但A表中未找到符合条件的记录的集合A表中的信息是以 Null值返回;各种连接通用写法是:内连接: select a_f2,b_f2 from A,B where A.f1=B.f1 或 s
37、elect a_f2,b_f2 from A inner joinB onA.f1=B.f1( 此标准在 symfoware 不支持,奇怪!)左连接:selecta_f2,b_f2 from A left outer join B on A.f1=B.f1右连接:selecta_f2,b_f2 from A right outer join B on A.f1=B.f1全连接:selecta_f2,b_f2 from A full outer join B on A.f1=B.f1 ;在symfoware 中不支持4.1.7. Select * from report where SALES_
38、CODE in (select SALES_CODE from anken where );上节讲的所有的表都在from 后的列表中,数据源都是直接的表,不含子查询,而这条是典型的含子查询的语句,内部执行时,可以有这种方式:首先,执行子查询语句,把结果集临时保存,作为外层查询的一个数据源;其次,类似4.1.6 节中的流程图,先检索report 表第一条记录,然后再检索上一个步骤得到的数据源,如果包含sales_code值,则返回report当前检索到的记录,如果没有,则 report 继续扫描下一条记录,重复上步操作,直到表的结尾;很多含子查询的语句 oracle 内部处理的时候会先转换成等价
39、的不含子查询的语句去执行,如:Select A.f1,B.f1 from A,(select * from C where C.f3=V_1) B where A.f2=B.f2;转换成:Select A.f1,B.f1 from A,C where A.f2=C.f2 and C.f3=V_1;4.1.8. Select * from report where SALES_CODE exists (select 1 from anken where );Oracle 先扫描 report 的一个记录, 然后去执行里层子查询里的语句, 只要能检索到一条记录,则立即返回给外层一个true 的值,
40、 report 的当前记录就可以返回给用户,扫描一下一条记录;如果子查询执行完毕都还没有检索到一条记录,则返回 false 给外层,则表示report 当前记录不符合条件,则继续扫描下一条记录,直到结尾;4.1.9. in,exists 的选择一般情况下, in 的子查询都可以写成exists 的子查询,以下两种选择可以优化性能:1) 当内层子查询的过滤条件有很强的过滤作用时,考虑使用in ,因为内层子查询返回的数据源比较少;2) 当外层查询的过滤条件有很强的过滤作用时,且内存查询可以使用索引快速定位,则考虑使用 exists ;4.1.10. select yadfw as t1,kopee
41、w as t2 From A union all select uufger as t1,poeprvcx as t2 from Bunion all 前后是两个独立的查询,它的作用是合并2 个记录集。内部处理时, oracle先执行 union all 之前的查询返回记录给用户,执行完毕后,接着执行union all 后面的查询,把查询结果返回给用户;应用程序中, 有很多报表或网格显示的上下行内容来自于互不相干的表, 但由于使用绑定数据源的方式,显示数据只能由一次SQL 语句检索得到,此时union all 就派上用场了;Union all 两端查询的字段个数以及对应的数据类型要一致;Uni
42、on 也有把多个查询的记录集合并的功能, 但它与 union all 的不同之处是, 当 oracle 检索到的每条记录时不会马上返回给用户, 会把它送到一个排序区中进行排序, 排序 中以字段在select列表中更靠前的则先排序,当不同记录中各个字段信息全部相同时,oracle 只留下一条记录,废除其他相同记录;所以,当不需要排序且允许相同记录存在时,使用 union all 性能比 union 好;4.2. 几种常见操作或函数4.2.1. 比较符 like这是一个模糊查询操作的字符串比较符,如 where A like Ww%',通配任意字符的符号%,如果单个字符通配是_ 。作比较的
43、串中,如果 % 或_放于最前面,oracle 将不用索引;4.2.2. is null , is not null当比较一个字段是否为 null 或非 null 时,应该使用 where f1 is null 或 where f1 is not null ,而不能用=或<> 比较符;任何值与 Null 做=,>,< , <> 比较时,都返回false ;任何值与null 进行+-*/数字运算操作时,得到的还是null ;字符串与null 值使用 |连接还是那个字符串值;4.2.3. to_char,to_date,to_numberto_char 可以把一个数字值转换成字符串,这个简单,不多讲;to_char 把日期型转换成字符串时, 最通用的格式 yyyy-mm-dd hh24:mi:ss , 其中 yyyy是 4 字符年份, mm 是 2 字符月份, dd 是 2 字符日期, hh24 是 24 小时制的时间,如果12小时制则用hh, mi是2字符分钟,ss是2字符秒数.格式可以灵活使用
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 钢琴高级教学计划钢琴老师教学计划
- 《健康保险知识手册》课件
- 山东聊城冠县2024年八年级上学期《数学》期中试题与参考答案
- 河南省禹州市2023年八年级上学期《数学》期中试题与参考答案
- 《说理式执法文书》课件
- 四年级数学(四则混合运算)计算题专项练习与答案
- 幼儿园学前教学计划
- 高二数学第二学期教学计划安排
- 互联网模拟试衣间建设运营项目创业计划书
- 开学第一课安全讲稿
- GA 573-2009警服材料精梳棉涤混纺染色斜纹布
- 钢筋工程施工技术交底课件
- 学科分类目录
- 招投标标书密封条
- 气相色谱检测器FID-培训讲解课件
- 列宁经典论著-《国家与革命》课件
- 四年级上册美术教案-18 适合纹样|苏少版
- 农业统计课件
- 《HSK标准教程1》-HSK1-L8课件
- 上册外研社六年级英语复习教案
- 替班换班登记表
评论
0/150
提交评论