多数SQL查询只包含从一个或多个表中返回数据的单条 SELECT 语句。可是,SQL 也容许执行多个查询(多条 SELECT 语句),并将结果做为一个查询结果集返回。这些组合查询一般称为并(union)或复合查询(compound query)。程序员
主要有两种状况须要使用组合查询:sql
能够用 UNION 操做符来组合数条 SQL 查询。数据库
使用 UNION 很简单,所要作的只是给出每条 SELECT 语句,在各条语句之间放上关键字 UNION。安全
SELECT cust_name, cust_contact, cust_email
FROM Customers
WHERE cust_state IN ('IL', 'IN', 'MI')
UNION
SELECT cust_name, cust_contact, cust_email
FROM Customers
WHERE cust_name = 'Fun4All';
复制代码
使用多条WHERE子句而不是UNION的相同查询:服务器
SELECT cust_name, cust_contact, cust_email
FROM Customers
WHERE cust_state IN ('IL', 'IN', 'MI')
OR cust_name = 'Fun4All';
复制代码
对于较复杂的过滤条件,或者从多个表(而不是一个表)中检索数据的情形,使用 UNION 可能会使处理更简单。数据库设计
UNION 从查询结果集中自动去除了重复的行;换句话说,它的行为与一条 SELECT 语句中使用多个 WHERE 子句条件同样。函数
若是想返回全部的匹配行,可以使用 UNION ALL 而不是 UNION。工具
SELECT cust_name, cust_contact, cust_email
FROM Customers
WHERE cust_state IN ('IL', 'IN', 'MI')
UNION ALL
SELECT cust_name, cust_contact, cust_email
FROM Customers
WHERE cust_name = 'Fun4All';
复制代码
UNION ALL 为 UNION 的一种形式,它完成 WHERE 子句完成不了的工做。布局
在用 UNION 组合查询时,只能使用一条 ORDER BY 子句,它必须位于最后一条 SELECT 语句以后。性能
SELECT cust_name, cust_contact, cust_email
FROM Customers
WHERE cust_state IN ('IL', 'IN', 'MI')
UNION
SELECT cust_name, cust_contact, cust_email
FROM Customers
WHERE cust_name = 'Fun4All'
ORDER BY cust_name, cust_contact;
复制代码
INSERT 用来将行插入(或添加)到数据库表。插入有几种方式:
插入及系统安全:使用 INSERT 语句可能须要客户端/服务器 DBMS 中的特定安全权限。在你试图使用 INSERT 前,应该保证本身有足够的安全权限。
把数据插入表中的最简单方法是使用基本的 INSERT 语法,它要求指定表名和插入到新行中的值。
INSERT INTO Customers
VALUES('1000000006', 'Toy Land', '123 Any Street', 'New York', 'NY', '11111', 'USA', NULL, NULL);
复制代码
存储到表中每一列的数据在 VALUES 子句中给出,必须给每一列提供一个值。若是某列没有值,则应该使用 NULL 值(假定表容许对该列指定空值)。各列必须以它们在表定义中出现的次序填充。
虽然这种语法很简单,但并不安全,应该尽可能避免使用。上面的 SQL 语句高度依赖于表中列的定义次序,还依赖于其容易得到的次序信息。即便能够获得这种次序信息,也不能保证各列在下一次表结构变更后保持彻底相同的次序。所以,编写依赖于特定列次序的 SQL 语句是很不安全的,这样作早晚会出问题。
编写 INSERT 语句的更安全(不过更繁琐)的方法以下:
INSERT INTO Customers(cust_id, cust_name, cust_address, cust_city, cust_state, cust_zip, cust_country, cust_contact, cust_email)
VALUES('1000000006', 'Toy Land', '123 Any Street', 'New York', 'NY', '11111', 'USA', NULL, NULL);
复制代码
由于提供了列名,VALUES 必须以其指定的次序匹配指定的列名,不必定按各列出如今表中的实际次序。其优势是,即便表的结构改变,这条 INSERT 语句仍然能正确工做。
给出列名的状况下,以不一样的次序填充仍然正确:
INSERT INTO Customers(cust_id, cust_contact, cust_email, cust_name, cust_address, cust_city, cust_state, cust_zip)
VALUES('1000000006', NULL, NULL, 'Toy Land', '123 Any Street', 'New York', 'NY', '11111');
复制代码
当心使用 VALUES:无论使用哪一种 INSERT 语法,VALUES 的数目都必须正确。若是不提供列名,则必须给每一个表列提供一个值;若是提供列名,则必须给列出的每一个列一个值。不然,就会产生一条错误消息,相应的行不能成功插入。
使用 INSERT 的推荐方法是明确给出表的列名。使用这种语法,还能够省略列,这表示能够只给某些列提供值,给其余列不提供值。
INSERT INTO Customers(cust_id, cust_name, cust_address, cust_city, cust_state, cust_zip, cust_country)
VALUES('1000000006', 'Toy Land', '123 Any Street', 'New York', 'NY', '11111', 'USA');
复制代码
省略的列必须知足如下条件:
INSERT 还存在另外一种形式,能够利用它将 SELECT 语句的结果插入表中,这就是所谓的INSERT SELECT。顾名思义,它是由一条 INSERT语句和一条 SELECT语句组成的。
INSERT INTO Customers(cust_id, cust_contact, cust_email, cust_name, cust_address, cust_city, cust_state, cust_zip, cust_country)
SELECT cust_id, cust_contact, cust_email, cust_name, cust_address, cust_city, cust_state, cust_zip, cust_country
FROM CustNew;
复制代码
若是 CustNew 这个表确实有数据,则全部的数据将被插入到 Customers 表。
有一种数据插入不使用 INSERT 语句。要将一个表的内容复制到一个全新的表(运行中建立的表),可使用 SELECT INTO 语句。
SELECT *
INTO CustCopy
FROM Customers;
复制代码
要想只复制部分的列,能够明确给出列名,而不是使用 * 通配符。
在使用SELECT INTO时,须要知道一些事情:
更新(修改)表中的数据,可使用 UPDATE 语句。有两种使用 UPDATE 的方式:
基本的 UPDATE 语句由三部分组成,分别是:
UPDATE Customers
SET cust_email = 'kim@thetoystore.com WHERE cust_id = '1000000005'; 复制代码
不要省略 WHERE 子句:在使用 UPDATE 时必定要细心。由于稍不注意,就会更新表中的全部行。
更新更多列的语法稍有不一样:
UPDATE Customers
SET cust_contact = 'Sam Roberts',
cust_email = 'sam@toyland.com'
WHERE cust_id = '1000000006';
复制代码
要删除某个列的值,可设置它为 NULL(假如表定义容许 NULL 值)。
UPDATE Customers
SET cust_email = NULL
WHERE cust_id = '1000000005'
复制代码
其中 NULL 用来去除 cust_email 列中的值。这与保存空字符串很不一样(空字符串用''表示,是一个值),而 NULL 表示没有值。
从一个表中删除(去掉)数据,使用 DELETE 语句。有两种使用 DELETE 的方式:
DELETE FROM Customers
WHERE cust_id = '1000000006';
复制代码
不要省略 WHERE 子句:在使用 DELETE 时必定要细心。由于稍不注意,就会错误地删除表中全部行。
友好的外键:使用外键确保引用完整性的一个好处是,DBMS 一般能够防止删除某个关系须要用到的行。例如,要从 Products 表中删除一个产品,而这个产品用在 OrderItems 的已有订单中,那么 DELETE 语句将抛出错误并停止。这是总要定义外键的另外一个理由。
若是省略了 WHERE 子句,则 UPDATE 或 DELETE 将被应用到表中全部的行。所以许多 SQL 程序员使用 UPDATE 或 DELETE 时须要遵循如下原则:
通常有两种建立表的方法:
利用 CREATE TABLE 建立表,必须给出下列信息:
CREATE TABLE Products
(
prod_id CHAR(10) NOT NULL,
vend_id CHAR(10) NOT NULL,
prod_name CHAR(254) NOT NULL,
prod_price DECIMAL(8, 2) NOT NULL,
prod_desc VARCHAR(1000) NULL
);
复制代码
替换现有的表:在建立新的表时,指定的表名必须不存在,不然会出错。防止意外覆盖已有的表,SQL 要求首先手工删除该表(请参阅后面的内容),而后再重建它,而不是简单地用建立表语句覆盖它。
在插入或更新行时,该列必须有值。每一个表列要么是 NULL列,要么是 NOT NULL 列,这种状态在建立时由表的定义规定。
CREATE TABLE Orders
(
order_num INTEGER NOT NULL,
order_date DATETIME NOT NULL,
cust_id CHAR(10) NOT NULL
);
复制代码
这三列都须要,所以每一列的定义都含有关键字 NOT NULL。这就会阻止插入没有值的列。若是插入没有值的列,将返回错误,且插入失败。
CREATE TABLE Vendors
(
vend_id CHAR(10) NOT NULL,
vend_name CHAR(50) NOT NULL,
vend_address CHAR(50) ,
vend_city CHAR(50) ,
vend_state CHAR(5) ,
vend_zip CHAR(10) ,
vend_country CHAR(50)
);
复制代码
NULL 为默认设置,若是不指定 NOT NULL,就认为指定的是 NULL。
主键和 NULL 值:主键是其值惟一标识表中每一行的列。只有不容许 NULL 值的列可做为主键,容许 NULL 值的列不能做为惟一标识。
CREATE TABLE OrderItems
(
order_num INTEGER NOT NULL,
order_item INTEGER NOT NULL,
prod_id CHAR(10) NOT NULL,
quantity INTEGER NOT NULL DEFAULT 1,
item_price DECIMAL(8, 2) NOT NULL
);
复制代码
默认值常常用于日期或时间戳列。
更新表定义,可使用 ALTER TABLE 语句。如下是使用 ALTER TABLE 时须要考虑的事情。
使用 ALTER TABLE 更改表结构,必须给出下面的信息:
ALTER TABLE Vendors
ADD vend_phone CHAR(20);
复制代码
更改或删除列、增长约束或增长键,这些操做也使用相似的语法:
ALTER TABLE Vendors
DROP COLUMN vend_phone;
复制代码
复杂的表结构更改通常须要手动删除过程,它涉及如下步骤:
(1) 用新的列布局建立一个新表; (2) 使用 INSERT SELECT 语句(关于这条语句的详细介绍,请参阅第 15课)从旧表复制数据到新表。有必要的话,可使用转换函数和计算字段; (3) 检验包含所需数据的新表; (4) 重命名旧表(若是肯定,能够删除它); (5) 用旧表原来的名字重命名新表; (6) 根据须要,从新建立触发器、存储过程、索引和外键。
当心使用 ALTER TABLE:使用 ALTER TABLE 要极为当心,应该在进行改动前作完整的备份(表结构和数据的备份)。数据库表的更改不能撤销,若是增长了不须要的列,也许没法删除它们。相似地,若是删除了不该该删除的列,可能会丢失该列中的全部数据。
DROP TABLE CustCopy;
复制代码
删除表没有确认,也不能撤销,执行这条语句将永久删除该表。
使用关系规则防止意外删除:许多 DBMS 容许强制实施有关规则,防止删除与其余表相关联的表。在实施这些规则时,若是对某个表发布一条 DROP TABLE 语句,且该表是某个关系的组成部分,则DBMS将阻止这条语句执行,直到该关系被删除为止。若是容许,应该启用这些选项,它能防止意外删除有用的表。
全部重命名操做的基本语法都要求指定旧表名和新表名。不过,存在 DBMS 实现差别。关于具体的语法,请参阅相应的 DBMS 文档。
视图是虚拟的表。与包含数据的表不同,视图只包含使用时动态检索 数据的查询。
用下面的 SELECT 语句从三个表中检索数据:
SELECT cust_name, cust_contact
FROM Customers, Orders, OrderItems
WHERE Customer.cust_id = Orders.cust_id
AND OrderItems.order_num = Orders.order_num
AND prod_id = 'RGAN01';
复制代码
如今,假如能够把整个查询包装成一个名为 ProductCustomers 的虚拟表,则能够以下轻松地检索出相同的数据:
SELECT cust_name, cust_contact
FROM ProductCustomers
WHERE prod_id = 'RGAN01';
复制代码
这就是视图的做用。ProductCustomers 是一个视图,它不包含任何列或数据,包含的是一个查询(与上面用以正确联结表的查询相同)。
下面是视图的一些常见应用:
建立视图以后,能够用与表基本相同的方式使用它们。能够对视图执行 SELECT 操做,过滤和排序数据,将视图联结到其余视图或表,甚至添加和更新数据(添加和更新数据存在某些限制,关于这个内容稍后作介绍)。
重要的是,要知道视图仅仅是用来查看存储在别处数据的一种设施。视图自己不包含数据,所以返回的数据是从其余表中检索出来的。在添加或更改这些表中的数据时,视图将返回改变过的数据。
性能问题:由于视图不包含数据,因此每次使用视图时,都必须处理查询执行时须要的全部检索。若是你用多个联结和过滤建立了复杂的视图或者嵌套了视图,性能可能会降低得很厉害。所以,在部署使用了大量视图的应用前,应该进行测试。
关于视图建立和使用的一些最多见的规则和限制:
视图用 CREATE VIEW 语句来建立。删除视图能够用 DROP VIEW 。
CREATE VIEW ProductCustomers AS
SELECT cust_name, cust_contact, prod_id
FROM Customers, Orders, OrderItems
WHERE Customers.cust_id = Orders.cust_id
AND OrderItems.order_num = Orders.order_num;
复制代码
在以上视图中进行检索:
SELECT cust_name, cust_contact
FROM ProductCustomers
WHERE prod_id = 'RGAN01';
复制代码
SELECT RTRIM(vend_name) + ' (' + RTRIM(vend_country) + ')' AS vend_title
FROM Vendors
ORDER BY vend_name;
复制代码
把此语句转换为视图:
CREATE VIEW VendorLocations AS
SELECT RTRIM(vend_name) + ' (' + RTRIM(vend_country) + ')' AS vend_title
FROM Vendors;
复制代码
再检索数据:
SELECT *
FROM VendorLocations;
复制代码
CREATE VIEW CustomerEmailList AS
SELECT cust_id, cust_name, cust_email
FROM Customers
WHERE cust_email IS NOT NULL;
复制代码
再检索数据:
SELECT *
FROM CustomerEMailList;
复制代码
SELECT prod_id, quantity, item_price, quantity*item_price AS expanded_price
FROM OrderItems
WHERE order_num = 20008;
复制代码
将以上查询转成视图:
CREATE VIEW OrderItemsExpanded AS
SELECT order_num, prod_id, quantity, item_price, quantity*item_price AS expanded_price
FROM OrderItems;
复制代码
再检索数据:
SELECT *
FROM OrderItemsExpanded
WHERE order_num = 20008;
复制代码
简单来讲,存储过程就是为之后使用而保存的一条或多条 SQL 语句。可将其视为批文件,虽然它们的做用不只限于批处理。
理由不少,下面给出一些主要的:
换句话说,使用存储过程有三个主要的好处,即简单、安全、高性能。
存储过程的执行远比编写要频繁得多,所以咱们先介绍存储过程的执行。执行存储过程的 SQL 语句很简单,即 EXECUTE。EXECUTE 接受存储过程名和须要传递给它的任何参数。
EXECUTE AddNewProduct('JTS01', 'Stuffed Eiffel Tower', 6.49, 'Plush stuffed toy with the text La Tour Eiffel in red white and blue'0;
复制代码
这里执行一个名为 AddNewProduct 的存储过程,将一个新产品添加到 Products 表中。AddNewProduct 有四个参数,分别是:供应商 ID(Vendors 表的主键)、产品名、价格和描述。这 4个参数匹配存储过程当中4个预期变量(定义为存储过程自身的组成部分)。此存储过程将新行添加到 Products 表,并将传入的属性赋给相应的列。
在 Products表中还有另外一个须要值的列 prod_id列,它是这个表的主键。为何这个值不做为属性传递给存储过程?要保证恰当地生成此 ID,最好是使生成此 ID 的过程自动化(而不是依赖于最终用户的输入)。
如下是存储过程所完成的工做:
Oracle 版本:
CREATE PROCEDURE MailingListCount (
ListCount OUT INTEGER
)
IS
v_rows INTEGER;
BEGIN
SELECT COUNT(*) INTO v_rows
FROM Customers
WHERE NOT cust_email IS NULL;
ListCount := v_rows;
END;
复制代码
这个存储过程有一个名为 ListCount 的参数。此参数从存储过程返回一个值而不是传递一个值给存储过程。关键字 OUT 用来指示这种行为。Oracle支持 IN(传递值给存储过程)、OUT(从存储过程返回值,如这里)、INOUT (既传递值给存储过程也从存储过程传回值)类型的参数。存储过程的代码括在 BEGIN 和 END 语句中,这里执行一条简单的 SELECT 语句,它检索具备邮件地址的顾客。而后用检索出的行数设置 ListCount(要传递的输出参数)。
使用事务处理(transaction processing),经过确保成批的 SQL 操做要么彻底执行,要么彻底不执行,来维护数据库的完整性。
关系数据库把数据存储在多个表中,使数据更容易操纵、维护和重用。不用深究如何以及为何进行关系数据库设计,在某种程度上说,设计良好的数据库模式都是关联的。
事务处理是一种机制,用来管理必须成批执行的 SQL 操做,保证数据库不包含不完整的操做结果。利用事务处理,能够保证一组操做不会中途中止,它们要么彻底执行,要么彻底不执行(除非明确指示)。若是没有错误发生,整组语句提交给(写到)数据库表;若是发生错误,则进行回退(撤销),将数据库恢复到某个已知且安全的状态。
下面是关于事务处理须要知道的几个术语:
能够回退哪些语句:事务处理用来管理 INSERT、UPDATE 和 DELETE 语句。不能回退 SELECT 语句(回退 SELECT 语句也没有必要),也不能回退 CREATE 或 DROP 操做。
管理事务的关键在于将 SQL 语句组分解为逻辑块,并明确规定数据什么时候应该回退,什么时候不该该回退。
MySQL 中的标识:
START TRANSACTION
...
复制代码
事务一直存在,直到被中断。一般,COMMIT 用于保存更改,ROLLBACK 用于撤销,详述以下。
DELETE FROM Orders;
ROLLBACK;
复制代码
在此例子中,执行 DELETE 操做,而后用 ROLLBACK 语句撤销。虽然这不是最有用的例子,但它的确可以说明,在事务处理块中,DELETE 操做(与 INSERT 和 UPDATE 操做同样)并非最终的结果。
通常的 SQL 语句都是针对数据库表直接执行和编写的。这就是所谓的隐式提交(implicit commit),即提交(写或保存)操做是自动进行的。
在事务处理块中,提交不会隐式进行。不过,不一样 DBMS 的作法有所不一样。有的 DBMS 按隐式提交处理事务端,有的则不这样。
进行明确的提交,使用COMMIT语句。
Oracle 示例:
SET TRANSACTION
DELETE OrderItems WHERE order_num = 12345;
DELETE OrderItems WHERE order_num = 12345;
COMMIT;
复制代码
使用简单的 ROLLBACK 和 COMMIT 语句,就能够写入或撤销整个事务。可是,只对简单的事务才能这样作,复杂的事务可能须要部分提交或回退。
要支持回退部分事务,必须在事务处理块中的合适位置放置占位符。这样,若是须要回退,能够回退到某个占位符。
MySQL 和 Oracle 示例:
ROLLBACK TO delete1;
复制代码
有时,须要在检索出来的行中前进或后退一行或多行,这就是游标的用途所在。游标(cursor)是一个存储在 DBMS 服务器上的数据库查询,它不是一条 SELECT 语句,而是被该语句检索出来的结果集。在存储了游标以后,应用程序能够根据须要滚动或浏览其中的数据。
不一样的 DBMS 支持不一样的游标选项和特性。常见的一些选项和特性以下:
使用游标有几个明确的步骤:
使用 DECLARE 语句建立游标,这条语句在不一样的 DBMS 中有所不一样。DECLARE 命名游标,并定义相应的 SELECT 语句,根据须要带 WHERE 和其余子句。
DECLARE CustCursor CURSOR
FOR
SELECT * FROM Customers
WHERE cust_email IS NULL;
复制代码
OPEN CURSOR CustCursor;
复制代码
如今能够用 FETCH 语句访问游标数据了。FETCH 指出要检索哪些行,从何处检索它们以及将它们放于何处(如变量名)。
使用 Oracle 语法从游标中检索一行:
DECLARE TYPE CustCursor IS REF CURSOR RETURN Customers%ROWTYPE
DECLARE CustRecord Customers%ROWTYPE;
BEGIN
OPEN CustCursor;
FETCH CustCursor INTO CustRecord;
CLOSE CustCursor;
END;
复制代码
CLOSE 语句用来关闭游标。一旦游标关闭,若是再也不次打开,将不能使 用。第二次使用它时不须要再声明,只需用 OPEN 打开它便可。
CLOSE CustCursor
复制代码
约束(constraint):管理如何插入或处理数据库数据的规则。
主键是一种特殊的约束,用来 一组列)中的值是惟一的,并且永不改动。换句话说,表中的一列(或 多个列)的值惟一标识表中的每一行。这方便了直接或交互地处理表中的行。没有主键,要安全地 UPDATE 或 DELETE 特定行而不影响其余行会 很是困难。
表中任意列只要知足如下条件,均可以用于主键。
一种定义主键的方法是建立它:
CREATE TABLE Vendors
(
vend_id CHAR(10) NOT NULL PRIMARY KEY,
vend_name CHAR(50) NOT NULL,
vend_address CHAR(50) NULL,
vend_city CHAR(50) NULL,
vend_state CHAR(5) NULL,
vend_zip CHAR(10) NULL,
vend_country CHAR(50) NULL
);
复制代码
另外一种方法:
ALTER TABLE Vendors
ADD CONSTRAINT PRIMARY KEY (vend_id);
复制代码
外键是表中的一列,其值必须列在另外一表的主键中。外键是保证引用完 整性的极其重要部分。
定义外键的方法:
CREATE TABLE Orders
(
order_num INTEGER NOT NULL PRIMARY KEY,
order_date DATETIME NOT NULL,
cust_id CHAR(10) NOT NULL REFERENCES Customers(cust_id)
);
复制代码
也能够用 CONSTRAINT 来完成:
ALTER TABLE Orders
ADD CONSTRAINT
FOREIGN KEY (cust_id) REFERENCES Customers (cust_id)
复制代码
外键有助防止意外删除:除帮助保证引用完整性外,外键还有另外一个重要做用。在定义外键后,DBMS 不容许删除在另外一个表中具备关联行的行。
惟一约束用来保证一列(或一组列)中的数据是惟一的。它们相似于主 键,但存在如下重要区别。
惟一约束的语法相似于其余约束的语法。惟一约束既能够用 UNIQUE 关 键字在表定义中定义,也能够用单独的 CONSTRAINT 定义。
检查约束用来保证一列(或一组列)中的数据知足一组指定的条件。检 查约束的常见用途有如下几点:
检查 约束在数据类型内又作了进一步的限制,这些限制极其重要,能够确保插 入数据库的数据正是你想要的数据。不须要依赖于客户端应用程序或用户 来保证正确获取它,DBMS 自己将会拒绝任何无效的数据。
施加检查约束:
CREATE TABLE OrderItems
(
order_num INTEGER NOT NULL,
order_item INTEGER NOT NULL,
prod_id CHAR(10) NOT NULL,
quantity INTEGER NOT NULL CHECK (quantity > 0),
item_price MONEY NOT NULL
);
复制代码
检查名为 gender 的列只包含 M 或 F,可编写以下的 ALTER TABLE 语句:
ADD CONSTRAINT CHECK (gender LIKE '[MF]')
复制代码
索引用来排序数据以加快搜索和排序操做的速度。想像一本书后的索引 (如本书后的索引),能够帮助你理解数据库的索引。
假如要找出本书中全部的“数据类型”这个词,简单的办法是从第 1 页 开始,浏览每一行。虽然这样作能够完成任务,但显然不是一种好的办法。浏览少数几页文字可能还行,但以这种方式浏览整部书就不可行了。 随着要搜索的页数不断增长,找出所需词汇的时间也会增长。
这就是书籍要有索引的缘由。索引按字母顺序列出词汇及其在书中的位 置。为了搜索“数据类型”一词,可在索引中找出该词,肯定它出如今 哪些页中。而后再翻到这些页,找出“数据类型”一词。
使索引有用的因素是什么?很简单,就是恰当的排序。找出书中词汇的 困难不在于必须进行多少搜索,而在于书的内容没有按词汇排序。若是 书的内容像字典同样排序,则索引没有必要(所以字典就没有索引)。
数据库索引的做用也同样。主键数据老是排序的,这是 DBMS 的工做。 所以,按主键检索特定行老是一种快速有效的操做。
可是,搜索其余列中的值一般效率不高。例如,若是想搜索住在某个州的客户,怎么办?由于表数据并未按州排序,DBMS 必须读出表中全部行(从第一行开始),看其是否匹配。这就像要从没有索引的书中找出词汇同样。
解决方法是使用索引。能够在一个或多个列上定义索引,使 DBMS 保存 其内容的一个排过序的列表。在定义了索引后,DBMS 以使用书的索引相似的方法使用它。DBMS 搜索排过序的索引,找出匹配的位置,而后检索这些行。
在开始建立索引前,应该记住如下内容:
没有严格的规则要求什么应该索引,什么时候索引。大多数 DBMS 提供了可 用来肯定索引效率的实用程序,应该常用这些实用程序。
索引用 CREATE INDEX 语句建立:
CREATE INDEX prod_name_ind
ON Products (prod_name);
复制代码
索引必须惟一命名。
触发器是特殊的存储过程,它在特定的数据库活动发生时自动执行。触发 器能够与特定表上的 INSERT、UPDATE 和 DELETE 操做(或组合)相关联。
与存储过程不同(存储过程只是简单的存储 SQL 语句),触发器与单个的表相关联。与 Orders 表上的 INSERT 操做相关联的触发器只在 Orders 表中插入行时执行。 相似地, Customers 表上的 INSERT 和 UPDATE 操做的触发器只在 Customers 表上出现这些操做时执行。
触发器内的代码具备如下数据的访问权:
下面是触发器的一些常见用途:
不一样 DBMS 的触发器建立语法差别很大,更详细的信息请参阅相应的文档。
Oracle 版本:
CREATE TRIGGER customer_state
AFTER INSERT OR UPDATE
FOR EACH ROW
BEGIN
UPDATE Customers
SET cust_state = Upper(cust_state)
WHERE Customers.cust_id = :OLD.cust_id
END;
复制代码
对于组织来讲,没有什么比它的数据更重要了,所以应该保护这些数据, 使其不被偷盗或任意浏览。固然,数据也必须容许须要访问它的用户访 问,所以大多数 DBMS 都给管理员提供了管理机制,利用管理机制授予 或限制对数据的访问。
任何安全系统的基础都是用户受权和身份确认。这是一种处理,经过这 种处理对用户进行确认,保证他是有权用户,容许执行他要执行的操做。 有的 DBMS 为此结合使用了操做系统的安全措施,而有的维护本身的用户及密码列表,还有一些结合使用外部目录服务服务器。
通常说来,须要保护的操做有: