SQLSERVER总结
SQL 语言
SQL 全称是“结构化查询语言( Structured Query Language )”,最早的是 IBM 的圣约瑟研究实验室为其关系数据库管理系统 SYSTEM R 开发的一种查询语言,它的前身是 SQUARE 语言。 SQL 语言结构简洁,功能强大,简单易学,所以自从 IBM 公司 1981 年推出以来, SQL 语言,得到了广泛的应用。如今无论是像 Oracle 、 Sybase 、 Informix 、 SQL server 这些大型的数据库管理系统,还是像 Visual Foxporo 、 PowerBuilder 这些微机上常用的数据库开发系统,都支持 SQL 语言作为查询语言。 SQL (结构化查询语言)是大多数数据库使用的一种语言,使用 SQL ,就能使用任何数据库源和数据。
1 SQL 功能与特性
通过 SQL 命令,程序设计师或数据库管理员( DBA )可以:
( 1 )建立数据库的表格;(包括设置表格所可以使用之空间)
( 2 )改变数据库系统环境设置;
( 3 )针对某个数据库或表格,授予用户存取权限;
( 4 )对数据库表格建立索引值;
( 5 )修改数据库表格结构;(新建、删除或是修改表格字段)
( 6 )对数据库进行数据的新建;
( 7 )对数据库进行数据的删除;
( 8 )对数据库进行数据的修改;
( 9 )对数据库进行数据的查询。
SQL 广泛地被采用正说明了它的优点。它使全部用户,包括应用程序员、 DBA 管理员和终端用户受益非浅。下面介绍 SQL 的特点。
( 1 )非过程化语言
SQL 是一个非过程化的语言,因为它一次处理一个记录,对数据提供自动导航。 SQL 允许用户在高层的数据结构上工作,而不对单个记录进行操作,可操作记录集。所有 SQL 语句接受集合作为输入,返回集合作为输出。 SQL 的集合特性允许一条 SQL 语句的结果作为另一条 SQL 语句的输入。 SQL 不要求用户指定对数据的存放方法。 这种特性使用户更易集中精力于要得到的结果。所有 SQL 语句使用查询优化器,它是 RDBMS 的一部分,由它决定对指定数据存取的最快速度的手段。查询优化器知道 存在什么索引,哪儿使用合适,而用户从不需要知道表是否有索引,表有什么类型的索引。
( 2 )统一的语言
SQL 可用于所有用户的 DB 活动模型,包括系统管理员、数据库管理员、 应用程序员、决策支持系统人员及许多其它类型的终端用户。基本的 SQL 命令只需很少时间就能学会,最高级的命令在几天内便可掌握。以前的数据库管理系统为各类操作提供单独的语言,而 SQL 将全部任务统一在一种语言中。
( 3 )是所有关系数据库的公共语言
由于所有主要的关系数据库管理系统都支持 SQL 语言,用户可将使用 SQL 的技能从一个 RDBMS 转到另一个。所有用 SQL 编写的程序都是可以移植的。
2 SQL 语法的分类
其实 SQL 命令并不是非常多,可是要把 SQL 用到出神入化,却也只需要短短几个命令便够,因为 SQL 命令是针对关系型数据库所建立出来的语法叙述,所以 SQL 在这类数据库中所发挥的功能非常的强。
( 1 )属性词( Predicates )
在 SQL 命令中用来指明所要选择的记录的方式。如 ALL 、 TOP 与 DISTINCT 等等。
( 2 )声明( Declaration )
针对 SQL Parameter 或 Parameter Query 的名称与数据类型做声明,如 PARAMETERS 的声明等。
( 3 )条件子句( Clause )
在 SQL 的查询中,利用一些表达式定义出查询的条件,以缩小寻找的范围,如 WHERE 语句。
( 4 )运算符( Operator )与操作数( Operation )
在 SQL 的查询中,与 Operation 共同组成表达式( Expression ),如 BETWEEN....AND 运算符与 INNER JOIN 操作数。
( 5 )函数( Function )
一些 SQL 常见的函数,像 AVG() 是求算数平均数的函数。
( 6 ) SQL 语句( Statement )
SQL 的语句,可以说是 SQL 语法的主体,用来对某一个特定的数据库发出指示,并返回相关的数据,而 SQL 的语法结构,基本上可以利用下面的式子来表示:命令+条件子句
例如: SELECT*FROM TAB WHERE TAB.NAME='A'
其中的“ FROM....WHERE ”便是一个条件子句,其实 SQL 的语法并不难,只需记住这样的一个规则,相信可以很快的了解 SQL 用法。
3 SQL 语句
SELECT 语句
SELECT 语句用于数据库中选取信息,完整的 SELECT 语句的格式如下:
SELECT[ predicate]{*|table.*|[table.]field [,[table.]field2[ ,...]]} [AS alias1 [,alias2[,...]]]
FROM tableexpression [,... ][IN externaldatabase ]
[WHERE...]
[GROUP BY...]
[HAVING...]
[ORDER BY...]
[WITH OWNERACCESS OPTION]
SELECT 语句包括下面几个部分:
( 1 ) Predicate :如前面所述,包括了 ALL 、 DISTINCT 、 DISTINCTROW 、与 TOP 我们可以利用这样的语句去限制查询后所得的结果。
( 2 ) * :从指定表格中指定所有的字段。
( 3 ) Table :针对被选择出的记录的字段,所指定表格的名称。
( 4 ) field1, (用中文标点符号) field2 :想要读取数据的字段名称,如果包含了一个以上的字段,会依照列出的顺序来读取数据。
( 5 ) alias1,alias2 :用来替代在表格实际字段名称的化名。
( 6 ) Tableexpression :表格名称或包含我们所想要的数据的表格。
( 7 ) Externaldatabase :若使用到不是目前的数据库则将其名字定义在 externaldatabase 当中。
下面先讨论 ALL,DISTINCT,DISTINCTROW,TOP 属性词用法:
SELECT [ALL|DISTINCT|DISTINCTROW|[ TOP n[PERCENT]]] FROM table
语句中各参数的涵义如下:
( 1 ) ALL :若是不指定任何的字段数据,则 Microsoft Jet 数据库引擎( database engine )将会选择所有的字段,并依据所定的条件查询出需求数据集。例如下面这个例子将会从职员表格中返回所有字段的数据。
【例 1 】若是要查询出职员表格中的所有记录,可以通过下面的语句来完成:
SELECT ALL* FROM 职员表格 ;
( 2 ) DISTINCT :对某个表格所选择的字段数据,略过重复的情况,也就是说,针对某个字段查询出来的记录结果是唯一的。例如有许多存放在职员表格的职员数据,也许会具有相同的姓名,所以若是用 SQL 语句中的 SELECT DISTINCT ,则查询出来的结果将会针对不一样的姓名加以筛选。若是您把 DISTINCT 加以省略,则这样的查询会显示所有的记录。
( 3 ) DISTINCTROW :将整条记录重复的记录忽略掉,而不是只有针对某一个字段的数据。
( 4 ) Table :指定查询记录所需要的表格。
【例 2 】
SELECT DISTINCTROW 公司名称
FROM 顾客表格 INNER JOIN 订单表格
ON 顾客表格 . 顾客 ID =订单表格 . 顾客 ID
ORDER BY 公司名称 ;
如果您忽略, DISTINCTROW 则会对每个公司产生一行以下的订单数据。此外,若是 DISTINCTROW 只有用在一个表格当中,则会被省略掉。
( 5 ) TOP :从第一条或最后一条开始(利用 ORDER BY 条件子句),返回特定条数的数据。
【例 3 】当想要知道在 2000 年,班上前 25 名的学生姓名数据时,您可以输入这样的语句:
SELECT TOP 25 学生姓名
FORM 学生表格
WHERE 毕业年份 =1994
ORDER BY 毕业成绩平均分数 DESC ;
如果没有加上 ORDER BY 这行条件的话,所得到的数据,将会随机的数据。此外,在 TOP 语句之后,除了可以加上数字以外,还可以利用保留字 PERCENT 来查询。
【例 4 】利用保留字 PERCENT 来查询:
SELECT TOP 10 PERCENT 学生姓名
FROM 学生表格
WHERE 毕业年份 =1994
ORDER BY 毕业成绩平均 DESC ;
PARAMETERS (参数)声明
对于参数型的查询语法中,对参数的名称以及数据类型需要做声明, PARAMETERS (参数)声明的作用正在于此。具体格式如下:
PARAMETERS name datatype [ ,name datatype [,...]]
name : PARAMETERS 的名称。您可以把参数名称当作字符串来使用,若是名称中包含了空字符串,可以利用中括号来处理,例如:“ VBeden ”。
datatype :输入参数的数据类型。
【例 5 】若是在查询时,需要机动的输入姓名,可以利用下列的方式完成:
PARAMETERS “输入姓名” Text;
SELECT *
FROM 职员表格
WHERE 姓名 = “输入姓名:” ;
ORDER BY 条件语句
ORDER BY 条件子句,通常与 SELECT 语句合并使用目的是将查询的结果,依照指定字段加以排序。
SELECT fieldlist
FROM table
WHERE selectcriteria
ORDER BY field[ ASC|DESC][,field2[ASC|DESC][,...]]
fieldlist :欲查询的字段名称。其中可以与 ALL , DISTINCT , DISINCTROW ,或 TOP 一起来使用。
table :欲查询的表格名称。
selectcriteria :查询的标准设置。
field1 :指定要依照那个字段作为排序的依据,若是你没有加上 ORDER BY 查询出的数据集将不会作排序的操作。
ASC :递增顺序类别。 ( 默认值 )
DESC :递减顺序类别。
【例 6 】若要将输出数据依据出生的先后次序排列,可以利用下面的命令:
SELECT 姓名,生日
FROM 职员表格
ORDER BY 生日
IN 条件子句
IN 条件子句指定被查询的一个外部数据库的表格。(必须是 Microsoft Jet 数据库引擎所可以连接的数据库,如 dBase,Paradox 等等)
SELECT|INSERT]INTO destination IN
{path|[ "path" "type"]|[""[type;DATABASE =path]]}
FROM tableexpression IN
{path|[ "path" "type"]|[""[type;DATABASE =path]]}
destination :欲插入数据的外部表格名称。
tableexpression :表格名称或是被读取数据的表格名称。这个参数可以是一个单一的表格名称,或是一段已经被存储的 SQL 查询等。
path :包含该表格的完整路径名称。
type :数据库的类型名称, 通常是当数据库部属于 Jet database 时才会使用。 ( 例如: dBASE III,dBASE IV,Paradox 3.x,Paradox 4.x, 或 Btrieve )
【例 7 】下面这两段的意义相同:
PartA ....FROM Table
IN ""[dBASE IV;DATABASE =C:\DBASE\DATA\SALES;];
PartB ....FROM Table
IN "C:\DBASE\DATA\SALES" "dBASE IV;"
HAVING 条件子句
HAVING 条件子句指定一 特定的分组记录,并满足 HAVING 所指定的条件或状态,但条件是针对分组的条件设置,格式如下:
SELECT fieldlist
FROM table
WHERE selectcriteria
GROUP BY groupfieldlist
HAVING groupcriteria
f ieldlist :显示被查询的字段名称。 ( 可与 ALL , DISTINCT , DISTINCTROW ,或 TOP 相结合 )
table :欲查询数据的表格名称。
selectcriteria :选取标准。
groupfieldlist :分组记录的字段名称,到多 10 个字段。而这些字段的顺序决定最高到最低的分组阶层。
groupcriteria :决定什么样的分组记录要被显示。
HAVING 跟 WHERE 的用法相当类似,不同之处在于 HAVING 必须用于 GROUP 之后的分组数据上。
【例 8 】 HAVING 条件子句用法:
SELECT 分类编 ,Sum( 库存数量 )
FROM 产品表格
GROUP BY 分类编号
HAVING Sum( 库存数量 )>100 AND 产品名称 LIKE "* 纸 " ;
GROUP BY 条件子句
GROUP BY 条件子句依据指定的字段,将具有相同数值的记录合并成一条,格式如下:
SELECT fieldlist
FROM table
WHERE criteria
GROUP BY groupfieldlist
fieldlist :读取的字段名称。(可与 ALL , DISTINCT , DISTINCTROW ,或 TOP 合并使用)
table :查询的表格名称。
groupfieldlist :组记录 的字段名称,到多 10 个字段,而这些字段的顺序决定最高到最低的分组层次。
【例 9 】 GROUP BY 条件子句用例:
SELECT 姓名 ,Count( 姓名 )AS 职员姓名
FROM 职员表格
WHERE 部门名称 =' 业务部 '
GROUP BY 姓名
FROM 条件子句
FROM 条件子句指定表格名称或是查询,其中包含列在 SELECT 语句的字段数据,格式如下:
SELECT fieldlist
FROM tableexpression [ IN externaldatabase ]
fieldlist :表格中的字段名称。 ( 可与 ALL,DISTINCT,DISTINCTROW, 或 TOP 相结合 )
tableexpression :表格名称,或多个表格的算式。
externaldatabase :若该表格参考到外部的数据库时,将其完整的路径名称记下。
【例 10 】从职员表格下,查询出所有姓名字段的数据(只有姓名字段被查询,其他则不显示)。
SELECT 姓名 FROM 职员表格;
WHERE 条件子句
WHERE 条件子句指定查询的条件与限制,格式如下:
SELECT fieldlist
FROM tableexpression
WHERE criteria
fieldlist :字段名称。 ( 可与 ALL,DISTINCT,DISTINCTROW, 或 TOP 相结合 )
tableexpression :表格名称,或多个表格的算式。
criteria :查询的结果,必须依照这一限制标准。
【例 11 】要查询出职员表格中,所有姓氏是李的数据,可以用下面的语句:
SELECT 姓名
FROM 职员表格
WHERE 姓氏 =' 李 ' ;
BETWEEN...AND 运算符
BETWEEN...AND 运算符决定某一人数值是否介于特定的范围之内,此运算符只可以用在 SQL 的语句中,格式如下:
expr [ Not]BETWEEN value1 AND value2
expr :指定要加以计算的字段与表达式的组合。
value1,value2 :所指明的数值范围。
【例 12 】若是要从职员表格查询出所有年龄介于 25-30 岁的员工,可以利用下面的程序来做:
SELECT 姓名 , 年龄 BETWEEN 25 AND 30
FROM 职员表格;
LIKE 操作数
用来将一字符串与另一特定字符串样式( pattern )比较,并将符合该字符串样式的记录过滤出来,格式如下:
expression LIKE "pattern"
expression :使用在 WHERE 条件子句, SQL 表达式。
pattern :用以比较的字符串样式。
【例 13 】若是你要查询出所有以“李”为首的姓氏,可以利用下面的式子。
Like " 李 *"
LIKE 操作数的多种范例:
( 1 )多个字符:
( a ) "a*a" ,可筛选: "aa","aBa","aBBBa " ,不能筛选: "aBC "
( b ) "*ab *" ,可筛选: "abc","AABB","Xab " ,不能筛选: "aZb ","bac "
( 2 )特殊字符: "a“*”a" ,可筛选: "a*a" ,不能筛选: "aaa "
( 3 )单一字符: "a? a " ,可筛选: "aaa","a3a","aBa" ,不能筛选: "aBBBa "
( 4 )单一数字: "a#a " ,可筛选: "a0a","a1a","a2a" ,不能筛选: "aaa ","a10a"
( 5 )字符范围: "“a-z”" ,可筛选: "f","p","j " ,不能筛选: "2","&"
( 6 )指定字符以外部范围: "“!a -z”"
( 7 )指定非数字: "“!0 -9”" 可筛选: "A","a ","&","~" ,不能筛选: "0","1","9"
( 8 )组合式结构: "a“!b -m”#" ,可筛选: "An9","az0","a99" ,不能筛选: "abc","aj0"
SQL 数字函数
( 1 ) AVG :算数平均数,格式如下:
AVG(expr )
expr :字段名称或表达式。
【例 14 】若要计算职员身高超过 165 厘米的职员平均身高,可以利用下面的 SQL 语句来完成:
SELECT Avg ( 身高 )
AS 平均身高
FROM 职员表格 WHERE 身高 >165 ;
( 2 ) COUNT :计算记录条数,格式如下:
COUNT(expr )
expr :字段名称或表达式。
【例 15 】若是要统计出业务部门的职员人数,并查询出职员的姓名,可以利用下面的程序:
SELECT Count( 姓名 ) AS 职员姓名
FROM 职员表格
WHERE 部门名称 =' 业务部 ' ;
( 3 ) FIRST 与 LAST :返回某字段的第一条数据与最后一条数据,格式如下:
FIRST(expr )
LAST(expr )
expr :字段名称或表达式。
【例 16 】若是要找出货品数量字段的第一条数据与货品价格字段的最后一条数据时,可以利用下面的查询方式:
SELECT FIRST( 货品数量 ) , LAST( 货品价格 )
FROM 订单表格
( 4 ) MAX ,与 MIN :返回某字段的最大值与最小值,用法同 FIRST 与 LAST 。
( 5 ) SUM :返回某特定字段或是运算的总和数值,格式如下:
SUM(expr )
expr :字段名称或表达式。
【例 17 】要计算出货品总价,可使用下面的程序。
SELECT
Sum( 单位价格 * 货品数量 )
AS 货品总价 FROM 订单表格
多层 SQL 查询
顾名思义,多层的 SQL 查询的便在于:“在一个 SQL 语句中可以包含另一个 SQL 查询语句,形成内部嵌套的查询类型。”
comparison[ANY|ALL|SOME](sqlstatement )
expression[NOT]IN (sqlstatement )
[NOT]EXISTS(sqlstatement )
comparison :将表达式与内层查询的结果比较的操作。
expression :对内层查询的结果作搜索的表达式。
sqlstatement :为 SELECT 语句构成的 SQL 查询,必须用 () 将该语句括起来。
【例 18 】我们先从订单表格当中,查询出所有的单位,再将产品表格中的单位与的一一对比,查询出所有高于订单表格的单位价格的记录。
SELECT * FROM 产品表格
WHERE 单位价格 >ANY (SELECT 单位价格 FROM 订单表格 WHERE 折扣 >=.25) ;
4 SQL 与数据库的维护
表格的建立
将 SQL 中的基本语法作了一番介绍以后,但大多是偏向于数据库数据的查询与过滤,但实际上,我们通过 SQL 命令所可以做的事还有很多,接下来要介绍的便是如何利用 SQL 的语法命令来建立一个数据库中的表格。
CREATE TABLE 语句
我们可以利用这个命令,来建立一个全新的表格,但前提则是:数据库必须已经存在。
CREATE TABLE table
(field1 type[(size)][index1][,field2 type[(size)] [index2][,...]] [, multifieldindex [,...]])
table :欲建立的新的表格名称。
field1,field2 :在新表格中的新的字段名称,到少要一个字段以上。
type :字段的数据类型。
Size :字段的大小。
index1,index2 :利用 CONSTRAINT 条件子句定义一个单一字段的索引名称。
multifieldindex :利用 CONSTRAINT 条件子句定义一个多重字段的索引名称。
使用 CREATE TABLE 语句来定义新表及它的字段以及字段条件。如果将一字段指定为 NOT NULL ,则新记录的该字段值必须是有效的数据。
CONSTRAINT 子句在字段上可创建不同的限制,并可用来建立主键。可以使用 CREATE INDEX 语句在当前表上建立一个主键或附加索引。
可以在单一字段上使用 NOT NULL ,或在用于单一字段或多重字段 ( 名为 CONSTRAINT) 的 CONSTRAINT 子句中使用 NOT NULL 。但是,一个字段只能使用一次 NOT NULL 限制。尝试多次应用此限制将导致运行错误。
建立 TEMPORARY 表时, 只能在建表的会话期间看见它。会话期终止时它就被自动删除。 Temporary 表能被不止一个用户访问。
WITH COMPRESSION 属性只能和 CHARACTER 及 MEMO (也被称作 TEXT ) 数据类型和它们的同义字一起使用。
WITH COMPRESSION 属性被加入 CHARACTER 列是因为单码字符表示格式的变化。 Unicode 字符一律需要两个字节。对于现有的主要包含字符数据的 Microsoft Jet 数据库,这可能意味着数据库文件被转换成 Microsoft Jet 4.0 格式时字长会增加将近一倍。然而,从前由单字节字符群 (SBCS) 指示的众多字符群的 Unicode 表示可以很容易地被压缩成一个单字节。 如果你用这一属性定义一个 CHARACTER 列,数据被储存时会自动压缩,从列中恢复时会自动解压缩。
MEMO 列也能被定义用来把数据存储成压缩格式。然而有个局限。只有在压缩时能达到最多 4096 字节的事例才可被压缩。 所有其他事例则不会被压缩。这就是说,在一个给定的表中,一个给定的 MEMO 列中有的数据会被压缩,有的则不会。
【例 19 】建立一个拥有职员姓名与部门字段的表格。
CREATE TABLE 职员表格
( 姓名 TEST ,部门 TEST ,职员编号 INTEGER CONSTRAINT 职员字段索引 PRIMARY KEY)
在这一个范例中,我们建立了一个表格名称为“职员表格”的表格,并且定义了该表格的主键值,以限制数据不能重复输入。
表格索引的建立
CREATE INDEX 语句主要是对一个已存在的表格建立索引,其用法如下:
CREATE[UNIQUE]INDEX index ON table(field[ASC|DESC][,field[ASC|DESC],...])
[WITH {PRIMARY|DISALLOWNULL|IGNORENULL}]
index :欲被建立的索引名称。
table :欲建立索引的表格名称。
field :欲被建立的索引的字段名称。并可通过 DESC 保留字,来决定索引的顺序。
在不同记录的索引字段之中不允许有重复值时,请使用 UNIQUE 保留字。在可选的 WITH 子句中,可以强制数据有效性规则:通过使用 DISALLOW NULL 选项来禁止在新记录的索引字段中使用 Null 项。 通过使用 IGNORE NULL 选项,避免在索引中包含索引字段为 Null 值的记录。
使用 PRIMARY 保留字指定带索引的字段为主键。这里隐喻此键是唯一的,所以可以省略 UNIQUE 保留字。可以使用 CREATE INDEX 把虚拟索引 建立在连接表 上,此表位于 ODBC 数据源中,例如未建立索引的 SQL 服务器。不需要权限或访问远程服务器来创建虚拟索引,且远程数据库并不会察觉到虚拟索引也不受虚拟索引的影响。对于由外部链接之表和数据库内部之表皆可使用相同的语法。在一个通常为“只读”状态的表格上创建虚拟索引将尤为有用。也可以使用 ALTER TABLE 语句 在表中添加单一或多重字段索引,也可以使用 ALTER TABLE 语句或 DROP 语句 删除用 ALTER TABLE 或 CREATE INDEX 创建的索引。在已经具有主键的表上创建新索引时,不得使用 PRIMARY 保留字;否则,会发生错误。
【例 20 】在职员表格中建立一个索引。
CREATE INDEX 新索引名称
ON 职员表格 ( 姓名部门 ) ;
CONSTRAINT 条件子句
CONSTRAINT 的功能是类似索引( INDEX )的,虽然 CONSTRAINT 也可以建立表格之间的关联性。
单一字段索引:
CONSTRAINT name
{PRIMARY KEY|UNIQUE|REFERENCES foreigntable [(foreignfield1,foreignfield2)]}
多字段索引:
CONSTRAINT name
{PRIMARY KEY(primary1[,primary2[,...]])
|UNIQUE(unique1[,unique2[,...]])
|FOREIGN KEY (ref1[,ref2[,...]])
|REFERENCES foreigntable [(foreignfield1[,foreignfield2[,...]])]}
name :要被建立的 CONSTRAINT 名称。
primary1,primary2 :被用来设计成主键值的字段名称 ( 可一个以上 ) 。
unique1,unique2 :被用来设计成唯一键值的字段名称 ( 可一个以上 ) 。
foreign key :字段名称,或是参考到别的表格中字段的字段名称。
foreigntable :如前所述,被参考到的表格。
foreignfield1,foreignfield2 :在参考到的表格当中,被 ref1,ref2 字段所指定的字段。如果被参考的字段是参考表格中的主键值,也可以省略这个条件子句。
可以使用 UNIQUE 保留字将字段设计为唯一键。这意味着在同一个表中没有两个记录的这个字段的值是相同的。可以强制任何字段或字段列表为唯一的。如果多重字段条件被设计成唯一键,在索引之中的所有字段的组合值必须也是唯一的,即使在这些字段之中有两个或两个以上的记录有相同的值。
可以用 PRIMARY KEY 保留字,将表中的字段或一组字段设计为主键。在主键之中所有的值必须是唯一的,且不可为 Null ,一个表只能有一个主键。在一个已经设有主键的表中,不能再设置 PRIMARY KEY 条件,否则会发生错误。
可以使用 FOREIGN KEY 保留字 将一个字段设置为外部键。如果外部表的主键是由一个以上的字段所组成,则必须使用多重字段条件定义,列出全部的引用字段、外部表名、以及以列出引用字段相 同的顺序在外部表中列出引用字段的名称。若所引用的字段是外部表的主键,则无须指定所引用的字段。根据默认,数据库引擎在认为外部表的主键是所引用字段的 情况下执行操作。
外部键条件限定具体的活动在一个相应的主键值被改变时来执行:
可以指定外部表上执行的活动,此活动基于一个在定义了 CONSTRAINT 的表中主键上执行的相应的活动。例如,考虑以下对“客户”表的定义
CREATE TABLE Customers (CustId INTEGER PRIMARY KEY, CLstNm NCHAR VARYING (50))
考虑表的以下定义,定义外部键与 Customers 表的主键关系的顺序为:
CREATE TABLE Orders (OrderId INTEGER PRIMARY KEY, CustId INTEGER, OrderNotes NCHAR VARYING (255), CONSTRAINT FKOrdersCustId FOREIGN KEY (CustId ) REFERENCES Customers ON UPDATE CASCADE ON DELETE CASCADE
ON UPDATE CASCADE 和 ON DELETE CASCADE 子句都定义于外部键上。 ON UPDATE CASCADE 子句的含义是:如果用户的标识符 (CustId ) 在用户表中更新,此更新将通过顺序表级联。各个含有相应用户标识符值的顺序随着新值自动更新。 ON DELETE CASCADE 子句的含义是:如果一个用户被从用户表中删除,顺序表中所有包含同样用户标识符值的位序也会被删除。
考虑到表中下列不同的定义,用 SET NULL 活动代替 CASCADE 活动的顺序为:
CREATE TABLE Orders (OrderId INTEGER PRIMARY KEY, CustId INTEGER, OrderNotes NCHAR VARYING (255), CONSTRAINT FKOrdersCustId FOREIGN KEY (CustId ) REFERENCES Customers ON UPDATE SET NULL ON DELETE SET NULL
ON UPDATE SET NULL 子句的含义是:如果用户的标识符 (CustId ) 在用户表中更新,顺序表中相应的外部键值将会被自动设为 NULL 。相似地, ON DELETE SET NULL 子句的含义是:如果一个用户被从用户表中删除,顺序表中所有相应的外部键将会被自动设为 NULL 。
为阻止外部键索引的自动生成,可使用变址器 NO INDEX 。这一形式的外部键定义仅用于经常要复制形成索引值的情况。在外部键索引中的数值经常被复制的场合,使用索引不如直接进行表搜索有效。对这种索引和表中插入和删除的行列的维护会降低性能,没有任何好处。
【例 21 】当我们要建立一个新的职员数据表格,表格包含姓名、部门名称与生日三个字段,且由这三个字段建立一个唯一的索引时,可以使用下面这段 SQL 的语句。
CREATE TABLE 职员数据表格
( 姓名 TEST ,部门名称 TEST ,生日 DATETIME , CONSTRAINT 职员数据表格限制 UNIQUE( 姓名,部门名称,生日 )) ;
以上是 SQL 中,与数据库表格建立相关的命令,你可以利用这些命令,通过 SQL 的语句,将数据库表格完整的建立出来,接下来的章节,将针对数据库建立之后的维护与增删所要使用的 SQL 语句作一介绍。
表的删除
可以利用 DELETE 语句,将表格中的记录删除。(注意,记录被删除后,无法再复原,所以条件设置要正确)
DELETE[table.*]
FROM tableexpression
WHERE criteria
table :欲删除记录的表格名称,也可以用 * 来取代。
tableexpression :一个或一个以上表格的名称。此一参数可以为单一的表格名称或是从 INNER JOIN , LEFT JOIN ,或 RIGHTJOIN 等运算所得到的结果。
criteria :决定表格中记录要被删除的标准。
可以使用 DELETE 删除多个记录。可以用 Execute 方法和 DROP 语句(后面章节讲到)从数据库中删除整个表。不过,若用这种方法删除表,将会失去表的结构。不同的是当使用 DELETE ,只有数据会被删除;表的结构以及表的所有属性仍然保留,例如字段属性及索引。可以用 DELETE 从与其他表有着 一 对多关系的表中清除记录。若在一个查询中删除了关系中‘一’的一方的表的相应记录,级联删除操作将删除关系中‘多’的一方的表的记录。例如,在客户表与订 单表之间的关系中,客户表是‘一’方,而订单表是‘多’方。如果指定使用级联删除,从客户数据中删除一个记录,相对应之订单记录也会被删除。删除查询不只 删除指定字段之中的数据,它会删除全部的记录。如果要删除指定字段值,可创建更新查询使该值变为 Null 。
当使用删除查询删除记录之后,不能取消此操作。如果想要知道哪些记录已被删除,首先验证使用相同条件的选定查询的结果,然后运行删除查询。随时注意维护数据的复制备份。如果误删除记录,可以从备份副本中将数据恢复。
【例 22 】若要将职员表格中姓名叫做 ' 李名 ' 的记录删除,我们可以利用下面的 SQL 语句来完成。
DELETE * FROM 职员表格
WHERE 姓名 =' 李名 ';
SELECT...INTO 语句
通过 SELECT...INTO 命令,利用既存表格查询,来建立一个新表格的查询语句。
SELECT field1[,field2[,...]]INTO newtable [IN externaldatabase ]
FROM source
field1,field2 :欲拷贝到新表格的字段名称。
newtable :欲建立之新表格的名称,不能是已经存在的表格。
externaldatabase :若是该表格在另外的外部数据库时,该数据库的名称。
source :记录数据拷贝的来源表格名称,可以是单一的表格或是一段 SQL 查询之语句。
改语句可以使用生成表查询来存档记录、生成表的复制备份、或生成输出至另一个数据库的表的副本、或用作定期显示数据的报表的依据。例如,可以每月运行一次同样的生成表查询,生成地区的销售月报。 - 或许你想要为新表定义一个主键。创建新表时,新表中的字段将继承查询基本表中每一个字段的数据类型及大小,但不传递其他的字段或表属性。
使用 INSERT INTO 语句时不用创建追加检索来把数据加入当前表中。在运行生成表查询之前,若要知道会选择哪些记录,可以先看一看使用相同选择条件的 SELECT 语句的结果。
【例 23 】通过下面的 SQL 语句,来建立一个新的“训练名册”表格。
SELECT 职员表格 . 姓名,职员表格 . 部门
INTO 训练名册 FROM 职员表格
WHERE 职称 =' 新进人员 ';
INNER JOIN 操作数
当某一个共同的字段数据相等时,将两个表格的记录加以组合。
SELECT fields
FROM table1 INNER JOIN table2
ON table1.field1 compopr table2.field2
table1,table2 :欲进行记录组合的表格名称。
field1,field2 :欲组合的字段名称。 ( 必须具有相同的数据类型 )
compopr :比较关系运算符如下:“ = ”,“ < ”,“ > ”,“ <= ”,“ <> ”等。
可以在 FROM 子句中使用 INNER JOIN 运算。 . 这是最普通的联接类型。只要在这两个表的公共字段之中有相符值,内部联接将组合两个表中的记录。可以使用 INNER JOIN 与部门表及员工表选择每一个部门中的全部员工。反之,可以使用 LEFT JOIN 或 RIGHT JOIN 运算创建 outer join ,从而选择所有部门(即使有些并没有员工)或所有员工(即使有些尚未分配到部门)。
若试图联接包含 Memo 或 OLE Object 数据的字段,会导致错误。
可以联接任何两个相同类型的数值字段。例如,可以联接 AutoNumber 和 Long 字段,因为它们类型相似。但不能联接 Single 和 Double 类型的字段。
下列示例显示如何在类标识符字段联接类表及产品表:
SELECT CategoryName , ProductName
FROM Categories INNER JOIN Products
ON Categories.CategoryID = Products.CategoryID ;
在上面的示例中,类标识符是已被联接的字段,但是它并不包含在查询输出中,因它并非被包含在 SELECT 语句之中。在这个示例中,若要包含联接字段,将字段名包含在 SELECT 语句中, Categories.CategoryID .
也可以使用下列语法,在一个 JOIN 语句中链接多个 ON 子句:
SELECT fields
FROM table1 INNER JOIN table2
ON table1.field1 compopr table2.field1 AND
ON table1.field2 compopr table2.field2) OR
ON table1.field3 compopr table2.field3)];
也可以使用下列语法,嵌套 JOIN 语句:
SELECT fields
FROM table1 INNER JOIN
(table2 INNER JOIN [( ]table3
[INNER JOIN [( ]tablex [INNER JOIN ...)]
ON table3.field3 compopr tablex.fieldx )]
ON table2.field2 compopr table3.field3)
ON table1.field1 compopr table2.field2;
在一个 INNER JOIN 之中,可以嵌套 LEFT JOIN 或 RIGHT JOIN ,但是在 LEFT JOIN 或 RIGHT JOIN 中不能嵌套 INNER JOIN 。
【例 24 】若要把分类表格与产品表格作组合,可参考下面的 SQL 语句。
SELECT 分类名称,产品名称
FROM 分类表格 INNER JOIN 产品表格
ON 分类表格 . 分类编号 = 产品表格 . 分类编号;
UNION 操作数
通过 UNION 操作数来建立连接的查询条件, UNION 操作数可以将两个以上的表格或是查询的结果组合起来。
[TABLE]query1 UNION [ALL][TABLE]query2 [UNION [ALL]
[TABLE]queryn [...]]
query1,query2,queryn :为一个 SELECT 的语句,或是一个已存在的查询名称,或是一个已存在的表格名称。
【例 25 】利用下面的 SQL 语句,将订单数量超过 1000 的顾客表格记录,与新客户表格作 UNION 的操作。
TABLE 新客户表格 UNION ALL
SELECT *
FROM 顾客表格
WHERE 订单数量 >1000 ;
ALTER 语句
在一个表格被建立之后,利用 ALTER 语句,可以去修改表格的字段设计。
ALTER TABLE table
{ADD {COLUMN field type[(size)][CONSTRAINT index]
|CONSTRAINT multifieldindex }
|DROP {COLUMN field|CONSTRAINT indexname }}
table :欲被 ALTER 的表格名称。
field :要被增加或删除的字段名称。
type :字段数据类型。
size :字段大小。
Index :对此字段的索引。
使用 ALTER TABLE 语句,可用多种不同方法更改当前已存在的表:
使用 ADD COLUMN 在表中添加新的字段。需要指定字段名、数据类型、还可以 ( 对文本和二进制字段 ) 指定长度。例如,下列语句在员工表中增加一 25 个字符的、名为 Notes 的文本字段: ALTER TABLE Employees ADD COLUMN Notes TEXT(25)
也可以定义此字段的索引。关于单一字段索引的详细信息,请参阅 CONSTRAINT 子句主题。
如果对一字段指定 NOT NULL ,则在这字段中添加的新记录必须有有效的数据。
使用 ALTER COLUMN 改变一个当前字段的数据类型,需要指定字段名、新数据类型、还可以 ( 对文本和二进制字段 ) 指定长度。例如,下列语句把雇员表中一个字段的数据类型 , 被称为 ZipCode (最初被定义为整数),改变成一个 10 字符文本字段:
ALTER TABLE Employees ALTER COLUMN ZipCode TEXT(10)
注意不能同时添加或删除一个以上的字段或索引。可以使用 CREATE INDEX 语句在一个表中增加一个单字段或多重字段,你还可以使用 ALTER TABLE 或 DROP 语句删除一个由 ALTER TABLE 或 CREATE INDEX 建立的索引。可以在单一字段上使用 NOT NULL ,或在用于单一字段或多重字段 ( 名为 CONSTRAINT) 的 CONSTRAINT 子句中使用 NOT NULL 。但是,一个字段只能使用一次 NOT NULL 限制。尝试多次应用此限制将导致运行错误。
【例 26 】在职员表格中新建一个“薪水”的字段。
ALTER TABLE 职员表格
ADD COLUMN 薪水 CURRENCY ;
【例 27 】在职员表格中删除一个“薪水”的字段。
ALTER TABLE 职员表格 DROP COLUMN 薪水;
DROP 语句
DROP 语句针对所指定的表格或字段加以删除,或是把索引删除。
DROP {TABLE table|INDEX index ON table}
table :欲删除之表格或索引依附之表格名称。
index :欲从表格中删除的索引名称。
使用 DROP COLUMN 删除字段。只要指定欲删除的字段名即可。
使用 DROP CONSTRAINT 删除多重字段索引。只要在 CONSTRAINT 保留字后面指定索引名即可。
【例 28 】从职员表格中,删除编号索引。
DROP INDEX MyIndex ON Employees;
【例 29 】从数据库中,删除整个表格。
DROP TABLE 职员表格;
INSERT INTO 语句
INSERT INTO 语句的功能是新建一条数据到表格当中。添加一个或多个记录至一个表。这叫作追加查询 .
多重记录追加查询格式如下:
INSERT INTO target [IN externaldatabase ][(field1[,field2[,...]])]
SELECT [source.]field1[,field2[,...]
FROM tableexpression
单条记录新建查询:
INSERT INTO target[(field1[,field2[,...]])]
VALUES(value1[,value2[,...])
target :新建记录的表格名称。
externaldatabase :外部数据库的路径,搭配 IN 条件子句使用。
source :若是记录从其它表格中拷贝时,指明该表格的名称。
field1,field2 :欲增加数据的字段名称。
tableexpression :表格名称或描述记录是从哪一个表格中插入的表格名称。配合 INNER JOIN , LEFT JOIN ,或 RIGHT JOIN 运算符一起使用。
value1,value2 :欲插入表格中的数值。
可以使用 INSERT INTO 语句来添加一个单一记录至一个表中,如以上所示使用单一记录追加查询语法。在这个例子中,代码指定了该记录每一字段的名称和值。必须指定追加数值的记录的每一个字段和那个字段的值。如果没有指定每一个字段时,缺省值或 Null 值将被插入至没有数据的字段之中。这些记录将被添加至表的尾部。
通过使用 SELECT ...FROM 子句如以上所示的多重记录追加查询语法,也可以从另一表或查询使用 INSERT INTO 追加一组记录。在这个示例中, SELECT 子句将指定追加字段至指定的 target 表。
source 或 target 表可以指定一个表或查询。如果查询被指定, Microsoft Jet 数据库引擎会把记录追加到由该查询指定的所有表中。
INSERT INTO 是可选的,但当使用时,请置於 SELECT 语句之前。
如果目标表包含一个主键,一定要把唯一的非 Null 值追加到主键字段中,否则 Microsoft Jet 数据库引擎不会追加记录。
如果要把把记录追加到带有 AutoNumber 字段的表中,还想重编追加的记录,请不要在查询中包含 AutoNumber 字段。如果要保持字段中的原始值,请将自动编号加在的查询之中。
使用 IN 子句,可追加记录至另一个数据库中的表。
要创建新表请用 SELECT...INTO 语句代替制表查询的创建。
若要在运行追加查询之前找出哪些记录是被追加的,首先执行和查阅一个使用相同的选择条件之选定查询所获得的结果。
追加查询为从一个或多个表中复制记录至另一个表。您追加的表包含记录将不会被追加查询所影响。
除了从另一表中来追加现存的记录,可以指定在单一追加记录之中使用 VALUES 子句来指定对每一字段的值。如果省略字段列表, VALUES 子句在表之中必须包含每一字段的值;否则, INSERT 运算将会失败。使用额外的 INSERT INTO 语句与一个 VALUES 子句来创建要的每一个额外的记录。
【例 30 】在客户数据表格中,从新的表格插入数据。
INSERT INTO 客户数据表格
SELECT 新客户数据表格 .*
FROM 新客户数据表格;
【例 31 】在职员表格中插入数据。
INSERT INTO 职员表格 ( 姓名,生日,职称 )
VALUES(" 王荣 ","57/12/11"," 经理 ");
【例 32 】从训练人员表格中,将职员雇用时间超过 30 天者,加入到正式职员表格中。
INSERT INTO 职员表格
SELECT 训练人员表格 .*
FROM 训练人员表格
WHERE 雇用天数 >30 ;
UPDATE 语句
建立一个 UPDATE 的查询,通过条件的限制来修改特定的数据。
UPDATE table
SET newvalue
WHERE criteria;
table :欲修改数据的表格名称。
newvalue :欲修改成的数值 ( 将该项数值插入到特定的字段当中 ) 。
criteria :查询条件,用来决定要修改哪些记录。
【例 33 】若是要把订单表格中的订单数量修改成 1.1 倍,运费为 1.03 倍,可利用下列之 SQL 语句来完成。
UPDATE 订单表格
SET 订单数量 = 订单数量 * 1.1 ,运费 = 运费 * 1.03 倍
WHERE 运达地点 =' 美国 ' ;
当完成修改后,可以利用 SELECT 语句,配合同样的 WHERE 条件子句,来察看修改的数据是否正确。
事实上,要利用 SQL 完成某些看似复杂的操作,并不需要繁琐的 SQL 命令组合,或是许许多多的步骤才能完成,其实最重要的还是要活用 SQL 命令,才会在最精简的 SQL 语句里获得最高的效率。