DB2数据库SQL语法参考手册.docx
《DB2数据库SQL语法参考手册.docx》由会员分享,可在线阅读,更多相关《DB2数据库SQL语法参考手册.docx(22页珍藏版)》请在冰点文库上搜索。
DB2数据库SQL语法参考手册
DB2数据库SQL语法参考手册
DB2提供了关连式资料库的查询语言SQL(StructuredQueryLanguage),是一种非常口语化、既易学又易懂的语法。
此一语言几乎是每个资料库系统都必须提供的,用以表示关连式的操作,包含了资料的定义(DDL)以及资料的处理(DML)。
SQL原来拼成SEQUEL,这语言的原型以"系统R"的名字在IBM圣荷西实验室完成,经过IBM内部及其他的许多使用性及效率测试,其结果相当令人满意,并决定在系统R的技术基础发展出来IBM的产品。
而且美国国家标准学会(ANSI)及国际标准化组织(ISO)在1987遵循一个几乎是以IBMSQL为基础的标准关连式资料语言定义。
一、资料定义DDL(DataDefinitionLanguage)
资料定义语言是指对资料的格式和形态下定义的语言,他是每个资料库要建立时候时首先要面对的,举凡资料分哪些表格关系、表格内的有什麽栏位主键、表格和表格之间互相参考的关系等等,都是在开始的时候所必须规划好的。
1.建表格:
CREATETABLEtable_name(
column1DATATYPE[NOTNULL][NOTNULLPRIMARYKEY],
column2DATATYPE[NOTNULL],
...)
说明:
DATATYPE是资料的格式,详见表。
NUTNULL可不可以允许资料有空的(尚未有资料填入)。
PRIMARYKEY是本表的主键。
2.更改表格
ALTERTABLEtable_name
ADDCOLUMNcolumn_nameDATATYPE
说明:
增加一个栏位(没有删除某个栏位的语法。
ALTERTABLEtable_name
ADDPRIMARYKEY(column_name)
说明:
更改表得的定义把某个栏位设为主键。
ALTERTABLEtable_name
DROPPRIMARYKEY(column_name)
说明:
把主键的定义删除。
3.建立索引
CREATEINDEXindex_nameONtable_name(column_name)
说明:
对某个表格的栏位建立索引以增加查询时的速度。
4.删除
DROPtable_name
DROPindex_name
二、的资料形态DATATYPEs
smallint
16位元的整数。
interger
32位元的整数。
decimal(p,s)
p精确值和s大小的十进位整数,精确值p是指全部有几个数(digits)大小值,s是指小数点後有几位数。
如果没有特别指定,则系统会设为p=5;s=0。
float
32位元的实数。
double
64位元的实数。
char(n)
n长度的字串,n不能超过254。
varchar(n)
长度不固定且其最大长度为n的字串,n不能超过4000。
graphic(n)和char(n)一样,不过其单位是两个字元double-bytes,n不能超过127。
这个形态是为
了支援两个字元长度的字体,例如中文字。
vargraphic(n)
可变长度且其最大长度为n的双字元字串,n不能超过2000。
date包含了年份、月份、日期。
time包含了小时、分钟、秒。
timestamp包含了年、月、日、时、分、秒、千分之一秒。
三、资料操作DML(DataManipulationLanguage)
资料定义好之後接下来的就是资料的操作。
资料的操作不外乎增加资料(insert)、查询资料(query)、更改资料(update)、删除资料(delete)四种模式,以下分别介绍他们的语法:
1.增加资料:
INSERTINTOtable_name(column1,column2,...)
valueS(value1,value2,...)
说明:
(1)若没有指定column系统则会按表格内的栏位顺序填入资料。
(2)栏位的资料形态和所填入的资料必须吻合。
(3)table_name也可以是景观view_name。
INSERTINTOtable_name(column1,column2,...)
SELECTcolumnx,columny,...FROManother_table
说明:
也可以经过一个子查询(subquery)把别的表格的资料填入。
2.查询资料:
基本查询
SELECTcolumn1,columns2,...
FROMtable_name
说明:
把table_name的特定栏位资料全部列出来
SELECT*FROMtable_nameWHEREcolumn1=***[ANDcolumn2>yyy][ORcolumn3<>zzz]
说明:
(1)'*'表示全部的栏位都列出来。
(2)WHERE之後是接条件式,把符合条件的资料列出来。
SELECTcolumn1,column2FROMtable_nameORDERBYcolumn2[DESC]
说明:
ORDERBY是指定以某个栏位做排序,[DESC]是指从大到小排列,若没有指明,则是从小到大
排列,组合,查询组合查询是指所查询得资料来源并不只有单一的表格,而是联合一个以上的表格才能够得到结果的。
SELECT*FROMtable1,table2WHEREtable1.colum1=table2.column1
说明:
(1)查询两个表格中其中column1值相同的资料。
(2)当然两个表格相互比较的栏位,其资料形态必须相同。
(3)一个复杂的查询其动用到的表格可能会很多个。
整合性的查询:
SELECTCOUNT(*)FROMtable_nameWHEREcolumn_name=xxx
说明:
查询符合条件的资料共有几笔。
SELECTSUM(column1)FROMtable_name
说明:
(1)计算出总和,所选的栏位必须是可数的数字形态。
(2)除此以外还有AVG()是计算平均、MAX()、MIN()计算最大最小值的整合性查询。
SELECTcolumn1,AVG(column2)FROMtable_nameGROUPBYcolumn1HAVINGAVG(column2)>xxx
说明:
(1)GROUPBY:
以column1为一组计算column2的平均值必须和AVG、SUM等整合性查询的关键字
一起使用。
(2)HAVING:
必须和GROUPBY一起使用作为整合性的限制。
复合性的查询
SELECT*FROMtable_name1WHEREEXISTS(SELECT*FROMtable_name2WHEREconditions)
说明:
(1)WHERE的conditions可以是另外一个的query。
(2)EXISTS在此是指存在与否。
SELECT*FROMtable_name1WHEREcolumn1IN(SELECTcolumn1FROMtable_name2WHEREconditions)
说明:
(1)IN後面接的是一个集合,表示column1存在集合里面。
(2)SELECT出来的资料形态必须符合column1。
其他查询
SELECT*FROMtable_name1WHEREcolumn1LIKE'x%'
说明:
LIKE必须和後面的'x%'相呼应表示以x为开头的字串。
SELECT*FROMtable_name1WHEREcolumn1IN('xxx','yyy',..)
说明:
IN後面接的是一个集合,表示column1存在集合里面。
SELECT*FROMtable_name1WHEREcolumn1BETWEENxxANDyy
说明:
BETWEEN表示column1的值介於xx和yy之间。
3.更改资料:
UPDATEtable_nameSETcolumn1='xxx'WHEREconditoins
说明:
(1)更改某个栏位设定其值为'xxx'。
(2)conditions是所要符合的条件、若没有WHERE则整个table的那个栏位都会全部被更改。
4.删除资料:
DELETEFROMtable_nameWHEREconditions
说明:
删除符合条件的资料。
说明:
关于WHERE条件后面如果包含有日期的比较,不同数据库有不同的表达式。
具体如下:
(1)如果是ACCESS数据库,则为:
WHEREmydate>#2000-01-01#
(2)如果是ORACLE数据库,则为:
WHEREmydate>cast('2000-01-01'asdate)
WHEREmydate>to_date('2000-01-01','yyyy-mm-dd')
在Delphi中写成:
thedate='2000-01-01';query1.SQL.add('select*fromabcwheremydate>cast('+''''+thedate+''''+'asdate)');
如果比较日期时间型,则为:
WHEREmydatetime>to_date('2000-01-0110:
00:
01','yyyy-mm-ddhh24:
mi:
ss')
DB2基础:
编码DB2SQL以获得最佳性能
简介
当要保证用IBMDB2®UniversalDatabase™(DB2UDB)和Borland®工具(如Delphi™、C++Builder™或Kylix™)构建的企业应用程序拥有最优性能时,程序员可以利用DB2优化器的能力来处理即使是“难以处理的”SQL语句并给出有效的存取路径。
尽管如此,拙劣编码的SQL和应用程序代码仍可能给您带来性能问题,通过学习几条基本准则可以轻易地避免这些问题。
我将向您演示DB2优化器的工作方式,并提供编写能发挥优化器最大效率的SQL的准则。
但即使拥有了DB2的优化能力,编写有效的SQL语句仍可能是一件复杂的事情。
如果程序员和开发人员还不熟悉关系数据库环境,这件事就尤其显得棘手。
因此,在我们深入研究编码SQL以获得最佳性能的细节之前,先花一些时间来回顾SQL基础知识。
基础知识
由于SQL与过程化语言不同,它提供了更高的抽象级别,因此它可以让程序员把精力集中到他们需要什么样的数据,而不是如何检索数据。
您不必使用嵌入式数据导航指令来编码SQL。
DB2会分析SQL,并“在幕后”制定数据导航指令。
这些数据导航指令叫作存取路径。
让DBMS确定到数据的最优存取路径解除了程序员肩上沉重的负担。
此外,数据库可以更好地理解它存储的数据的状态,从而可以生成到数据的更有效和动态的存取路径。
其结果就是适当使用的SQL可以用于更快的应用程序开发。
另一个SQL特性是它不仅仅是一种查询语言。
您还可以使用它来定义数据结构;控制对数据的访问;以及插入、修改和删除数据的发生。
通过提供一种公共语言,SQL简化了DBA、系统程序员、应用程序员、系统分析员和最终用户之间的通信。
当项目的所有参与者都使用同一种语言时,他们之间所建立起来的协作就可以减少整体系统开发时间。
历史证明,保证SQL成功的最重要的一个特性就是它使用类似英语的语法轻松地检索数据的能力。
理解这种语言比理解数据页面的结构和程序源代码要容易得多:
SELECTLASTNAME
FROMEMP
WHEREEMPNO='000010';
想想看:
当访问文件中的数据时,程序员必须编码指令来打开文件、开始一个循环、读取记录、检查EMPNO字段是否等于适当的值、检查文件结尾、回到循环的开头等。
SQL本来就是非常灵活的。
它使用自由格式的结构,该结构可以让用户开发SQL语句来适合他们的需要。
DBMS在执行之前会分析每个SQL请求,以检查语法是否正确和优化该请求。
SQL语句不需要从任何给定的列中开始,您可以将它们串在一行中,或者把它们拆成几行。
例如,以下这条单行的SQL语句与我前面使用的三行示例等价:
SELECTLASTNAMEFROMEMPWHEREEMPNO='000010';
SQL的另一个灵活特性是您可以用许多形式不同但功能等价的方法来制定一个请求。
例如:
SQL可以连接表或嵌套查询。
您始终可以将嵌套查询转换成等价的连接。
您可以在大量的函数和谓词中看到这一灵活性的其它示例。
具有等价功能的特性的示例包括:
∙BETWEENvs<=/>=
∙INvs一系列和OR配合的谓词
∙INNERJOINvsFROM子句中串在一起并用逗号分隔的表
∙OUTERJOINvs带有UNION的简单SELECT和相关的子查询
∙CASE表达式vs复杂的UNIONALL语句
SQL展示的这一灵活性并不总是称心的,因为形式不同但功能等价的SQL公式可以提供非常不同的性能。
我将在本文的以后部分讨论该灵活性所造成的结果,并提供开发有效的SQL的准则。
如我所说的,SQL指定了要检索或操作什么数据,但没有指定数据库如何完成这些任务。
这就使SQL本身变得很简单。
如果您能够记得关系数据库的一次处理一个集合(set-at-a-time)的特点,您就开始掌握SQL的本质和性质了。
一条SQL语句可以作用于多行。
作用于一组数据而不需要建立如何检索和操作数据的能力将SQL定义成非过程化语言
因为SQL是一种非过程化语言,所以一条语句可以代替一系列过程。
同样,由于SQL使用集合级别的处理以及DB2优化查询来确定数据导航逻辑,所以这是可能的。
有时,如果不使用SQL语句,一条或两条SQL语句可以完成的任务就需要完整的过程化程序来完成。
优化器
优化器是DB2的心脏和灵魂。
它分析SQL语句并确定可以满足每条语句的最有效的存取路径(请参阅图1)。
DB2UDB通过解析SQL语句来确定必须访问哪些表和列,从而完成该操作。
DB2优化器然后查询存储在DB2系统目录中的系统信息和统计信息,以确定完成满足SQL请求所必需的任务的最佳方法。
图1.运行中的DB2优化
优化器在功能上等价于一个专家系统。
专家系统是一个标准规则集合,当与情境数据组合时,它返回一个“专家”意见。
例如,医学专家系统采用一个规则集合,用来确定哪些药可以用于哪些疾病,将规则集与描述疾病症状的数据组合,并将知识库应用于输入症状的列表。
DB2优化器会根据存储在DB2系统目录中的情境数据和SQL格式的查询输入来生成对数据检索方法的专家意见。
在DBMS中优化数据访问的概念是DB2最强大的能力之一。
请记住,您访问DB2数据时应告诉DB2要检索什么,而不是如何检索。
无论数据实际上是如何存储和操作的,DB2和SQL都可以访问该数据。
从物理存储特征中分离出访问标准叫作物理数据独立性。
DB2的优化器是完成该物理数据独立性的组件。
如果您不要索引,DB2仍然能够访问数据(尽管效率会降低)。
如果将一列添加到正在被访问的表中,DB2仍然可以在不更改程序代码的情况下操作数据。
因为到DB2数据的物理存取路径并不是由程序员在应用程序中编码的,而是由DB2生成的,所以这种情况是完全有可能发生的。
这个特点与非DBMS系统非常不同,在那种系统中,程序员必须知道数据的物理结构。
如果有索引,程序员就必须编写适当的代码来使用该索引。
如果某人删除了索引,程序就不能工作,除非程序员进行更改。
而使用DB2和SQL就不必如此。
这一灵活性完全归功于DB2自动优化数据操作请求的能力。
优化器根据许多信息执行复杂的计算。
要使优化器的工作方式直观化,可以将优化器想象成执行一个四步骤的过程:
1、接收并验证SQL语句的语法。
2、分析环境并优化满足SQL语句的方法。
3、创建计算机可读指令来执行优化的SQL。
4、执行指令或存储它们以便将来执行。
这个过程的第二步是最有趣的。
优化器怎样决定如何以它的方式执行您可以发送的大量SQL语句?
优化器有许多类型的优化SQL的策略。
它如何选择在优化存取路径中使用这些策略中的哪一个?
IBM并没有发布优化器如何确定最佳存取路径的真正和深入的详细信息,但优化器是一个基于成本的优化器。
这意味着优化器将始终尝试为每个查询制定减少总体成本的存取路径。
要实现这个目标,DB2优化器会应用查询成本公式,该公式对每条可能的存取路径的四个因素进行评估和权衡:
CPU成本、I/O成本、DB2系统目录中的统计信息和实际的SQL语句。
在DB2中提高Insert性能的技巧
INSERT处理过程概述
首先让我们快速地看看insert一行时的处理步骤。
这些步骤中的每一步都有优化的潜力,对此我们在后面会一一讨论。
1、在客户机准备语句。
对于动态SQL,在语句执行前就要做这一步,此处的性能是很重要的;对于静态SQL,这一步的性能实际上关系不大,因为语句的准备是事先完成的。
2、在客户机,将要插入的行的各个列值组装起来,发送到DB2服务器。
3、DB2服务器确定将这一行插入到哪一页中。
4、DB2在用于该页的缓冲池中预留一个位置。
如果DB2选定的是一个已有的页,那么就需要读磁盘;如果使用一个新页,则要在表空间(如果是SMS,也就是系统管理存储的表空间)中为该页物理地分配空间。
插入了新行的每一页最后都要从缓冲池写入到磁盘。
5、在目标页中对该行进行格式化,并获得该行上的一个X(exclusive,独占的)行锁。
6、将反映该insert的一条记录写入到日志缓冲区中。
7、最后提交包含该insert的事务,如果这时日志缓冲区中的记录还没有被写入日志文件的话,则将这些记录写到日志文件中。
此外,还可能发生很多类型的附加处理,这取决于数据库配置,例如,索引或触发器的存在。
这种额外的处理对于性能来说也是意义重大的,我们在后面会讨论到。
insert的替代方案
在详细讨论insert的优化之前,让我们先考虑一下insert的两种替代方案:
load和import。
import实用程序实际上是SQLINSERT的一个前端,但它的某些功能对于您来说也是有用的。
load也有一些有用的额外功能,但是我们使用load而不使用insert的主要原因是可以提高性能。
load直接格式化数据页,而避免了由于插入导致的对每一行进行处理的大部分开销(例如,日志记录在这里实际上是消除了)。
而且,load可以更好地利用多处理器机器上的并行性。
在V8load中有两个新功能,它们对于load成为insert的替代方案有着特别的功效,这两个功能是:
从游标装载和从调用层接口(CLI)应用程序装载。
从游标装载
这种方法可用于应用程序的程序代码(通过db2LoadAPI),或用于DB2脚本。
下面是后一种情况的一个例子:
declarestaffcursorcursorforselect*fromstaff;
loadfromstaffcursorofcursorinsertintomyschema.new_staff;
这两行可以用下面一行替代:
insertintomyschema.new_staffselect*fromstaff
同等效的INSERT...SELECT语句相比,从游标装载几乎可以提高20%的性能。
从CLI装载
这种方法显然只限于调用层接口(CLI)应用程序,但是它非常快。
这种技巧非常类似于数组插入,DB2附带了这样的示例,使用load时的速度是使用经过完全优化的数组插入时的两倍,几乎要比未经优化的数组插入快10倍。
所有insert可以改进的地方
让我们看看插入处理的一些必要步骤,以及我们可以用来优化这些步骤的技巧。
1.语句准备
作为一条SQL语句,INSERT语句在执行之前必须由DB2进行编译。
这一步骤可以自动发生(例如在CLP中,或者在一次CLISQLExecDirect调用中),也可以显式地进行(例如,通过一条SQLPrepare、CLISQLPrepare或JDBCprepareStatement语句)。
该编译过程牵涉到授权检查、优化,以及将语句转化为可执行格式时所需的其他一些活动。
在编译语句时,语句的访问计划被存储在包缓存中。
如果重复地执行相同的INSERT语句,则该语句的访问计划(通常)会进入到包缓存中,这样就免除了编译的开销。
然而,如果insert语句对于每一行有不同的值,那么每一条语句都将被看成是惟一的,必须单独地进行编译。
因此,将像下面这样的重复语句:
insertintomytablevalues(1,'abc')
insertintomytablevalues(2,'def')
等等,
换成带有参数标记的语句,一次准备,重复执行,这样做是十分可取的:
insertintomytablevalues(?
?
)
使用参数标记可以让一系列的insert的运行速度提高数倍。
(在静态SQL程序中使用主机变量也可以获得类似的好处。
)
2.发送列值到服务器
可以归为这一类的优化技巧有好几种。
最重要的一种技巧是在每条insert语句中包括多行,这样就可以避免对于每一行都进行客户机-服务器通信,同时也减少了DB2开销。
可用于多行插入的技巧有:
∙在VALUES子句中包含多行的内容。
例如,下面的语句将插入三行:
INSERTINTOmytableVALUES(1,'abc'),(2,'def'),(3,'ghi')
∙在CLI中使用数组插入(arrayinsert)。
这需要准备一条带参数标记的INSERT语句,定义一个用于存储要插入的值的数组,将该数组绑定到参数标记,以及对于每个数组中的一组内容执行一次insert。
而且,示例程序sqllib/samples/cli/tbload.c提供了数组插入的基本框架(但是执行的是CLILO