检索数据
SELECT 语句
检索单个列:
SELECT prod_name
FROM Products;
检索多个列:
SELECT prod_id, prod_name, prod_price
FROM Products;
检索所有列:
SELECT *
FROM Products;
(* 是通配符)
排序检索数据
排序数据:
SELECT prod_name
FROM Products
ORDER BY prod_name;
按多个列排序:
SELECT prod_id, prod_price, prod_name
FROM Products
ORDER BY prod_price, prod_name;
按列位置排序:
SELECT prod_id, prod_price, prod_name
FROM Products
ORDER BY 2, 3;
指定排序方向:
SELECT prod_id, prod_price, prod_name
FROM Products
ORDER BY prod_price DESC;
(DESC 是降序,默认 ASC 升序)
SELECT prod_id, prod_price, prod_name
FROM Products
ORDER BY prod_price DESC, prod_name;
过滤数据
使用 WHERE 子句
SELECT prod_name, prod_price
FROM Products
WHERE prod_price = 3.49
WHERE 子句操作符
=,<>,!=,<,<=,!<,>,>=,!>,BETWEEN,IS NULL
检查单个值:
SELECT prod_name, prod_price
FROM Products
WHERE prod_price < 10;
不匹配检查:
SELECT vend_id, prod_name
FROM Products
WHERE vend_id <> ‘DLL01’;
范围值检查:
SELECT prod_name, prod_price
FROM Products
WHERE prod_price BETWEEN 5 AND 10;
空值检查:
SELECT prod_name
FROM Products
WHERE prod_price IS NULL;
高级数据过滤
组合 WHERE 子句
AND 操作符:
SELECT prod_id, prod_price, prod_name
FROM Products
WHERE vend_id = ‘DLL01’ AND prod_price <= 4;
OR 操作符:
SELECT prod_name, prod_price
FROM Products
WHERE vend_id = ‘DLL01’ OR vend_id = ‘BRS01’;
操作优先顺序:AND>OR
IN 操作符:
SELECT prod_name, prod_price
FROM Products
WHERE vend_id IN (‘DLL01’, ‘BRS01’)
ORDER BY prod_name;
NOT 操作符:
SELECT prod_name
FROM Products
WHERE NOT vend_id = ‘DLL01’
ORDER BY prod_name;
用通配符进行过滤
LIKE 操作符:
LIKE 指示 DBMS,后跟的搜索模式利用通配符匹配而不是直接相等匹配进行比较。
百分号%通配符:
%表示任何字符出现任意次数。
SELECT prod_id, prod_name
FROM Products
WHERE prod_name LIKE ‘Fish%’;
将检索任意以Fish起头的词。
SELECT prod_id, prod_name
FROM Products
WHERE prod_name LIKE ‘%bean bag%’;
表示匹配任何位置包含文本 bean bag 的值。
下划线_通配符:
用途与%一样,但一个_只匹配单个字符。
SELECT prod_id, prod_name
FROM Products
WHERE prod_name LIKE ‘__ inch teddy bear’;
方括号[]通配符:
指定一个字符集,必须匹配指定通配符位置包含的一个字符。
SELECT cust_contact
FROM Customers
WHERE cust_contact LIKE ‘[JM]%’
ORDER BY cust_contact;
加前缀字符^可否定,即返回不匹配[]中的字符的值。
SELECT cust_contact
FROM Customers
WHERE cust_contact LIKE ‘[^JM]%’
ORDER BY cust_contact;
创建计算字段
拼接:将值联结到一起构成单个值,用+或||表示。
SELECT vend_name + ‘(’ + ven_country + ‘)’
FROM Vendors
ORDER BY vend_name;
以下作用相同
SELECT vend_name || ‘(’ || ven_country || ‘)’
FROM Vendors
ORDER BY vend_name;
去掉拼接后自动填充的多余空格可用 TRIM() 去掉左右两边空格,RTRIM() 去掉右边空格,LTRIM() 去掉左边空格。
SELECT vend_name + ‘(’ + RTRIM(ven_country) + ‘)’
FROM Vendors
ORDER BY vend_name;
使用别名:
别名是一个字段或值的替换名,相当于给字段一个新的名字。用关键字 AS 赋予别名。
SELECT vend_name + ‘(’ + ven_country + ‘)’ AS vend_title
FROM Vendors
ORDER BY vend_name;
执行算术计算:
SELECT prod_id,
quantity,
item_price,
quantity*item_price AS expanded_price
FROM OrderItems
WHERE order_num = 20008;
SQL 算术操作符:±*/
使用数据处理函数
DBMS 函数的差异
函数
语法
提取串的组成部分
Access 使用 MID();DB2、Oracle 和 PostgreSQL 使用 SUBSTR();MySQL、SQL Server 和 Sybase 使用 SUBSTRING()
数据类型转换
Access 和 Oracle 使用多个函数,每种类型的转换有一个函数;DB2 和 PostgreSQL 使用 CAST();MySQL、SQL Server 和 Sybase 使用 CONVERT()
提取当前日期
Access 使用 NOW();DB2 和 PostgreSQL 使用 CURRENT_DATE;MySQL 使用 CURDATE();Oracle 使用 SYSDATE;SQL Server 和 Sybase 使用 GETDATE()
使用函数
文本处理函数:
SELECT vend_name, UPPER(vend_name) AS vend_name_upcase
FROM Vendors
ORDER BY vend_name;
常用文本处理函数
LEFT()(或使用子字符串函数):返回串左边的字符
RIGHT()(或使用子字符串函数):返回串右边的字符
LENGTH()(也使用DATALENGTH() 或 LEN()):返回串的长度
LTRIM():去掉左边的空格
RTRIM():去掉串右边的空格
SOUNDEX():返回串的SOUNDEX值,将任何文本串转换为描述其语音表示的字母数字模式。
UPPER()(Access使用UCASE()):将串转换为大写
LOWER()(Access使用LCASE()):将串转换为小写
用 SOUNDEX() 函数搜索能匹配发音类似的内容
SELECT cust_name, cust_contact
FROM Customers
WHERE SOUNDEX(cust_contact) = SOUNDEX(‘Michael Green’)
日期和时间处理函数
DATEPART() 函数,返回日期的某一部分
SELECT order_num
FROM Orders
WHERE DATEPART(yy, order_date) = 2004;
数值处理函数
ABS():返回一个数的绝对值
EXP():返回一个数的指数值
SQRT():返回一个数的平方根
PI():返回圆周率
SIN():返回一个角度的正弦
COS():返回一个角度的余弦
TAN():返回一个角度的正切
汇总数据
聚集函数
AVG():返回某列的平均值
COUNT():返回某列的行数
MAX():返回某列的最大值
MIN():返回某列的最小值
SUM():返回某列值之和
AVG() 函数:
所有列的平均值
SELECT AVG(prod_price) AS avg_price
FROM Products;
特定列或行的平均值
SELECT AVG(prod_price) AS avg_price
FROM Products;
WHERE vend_id = ‘DLL01’
COUNT() 函数:
COUNT()对表中行的数目进行计数,不管包含空值还是非空值
SELECT COUNT() AS num_cust
FROM Customers;
COUNT(column)对特定列中具有值的行进行计数,忽略NULL值
SELECT COUNT(cust_email) AS num_cust
FROM Customers;
MAX() 函数
SELECT MAX(prod_price) AS max_price
FROM Products
MIN() 函数
SELECT MIN(prod_price) AS min_price
FROM Products
SUM() 函数
计算总数
SELECT SUM(quantity) AS items_ordered
FROM OrderItems
WHERE order_num = 20005;
合计计算值
SELECT SUM(item_price*quantity) AS total_price
FROM OrderItems
WHERE order_num = 20005;
聚集不同值
对所有行执行计算,指定 ALL 参数或不给参数(ALL 是默认行为)
只包含不同的值,指定 DISTINCT 参数
SELECT AVG(DISTINCT prod_price) AS avg_price
FROM Products
WHERE vend_id = ‘DLL01’;
组合聚集函数
SELECT COUNT(*) AS num_items,
MIN(prod_price) AS price_min,
MAX(prod_price) AS price_max,
AVG(prod_price) AS price_avg
FROM Products;
分组数据
创建分组:
SELECT vend_id, COUNT(*) AS num_prods
FROM Products
GROUP BY vend_id;
GROUP BY 子句可以包含任意数目的列。
如果在GROUP BY 子句中嵌套了分组,数据将在最后规定的分组上进行汇总。
GROUP BY 子句中列出的每个列都必须是检索列或有效的表达式(但不能时聚集函数)。
大多数 SQL 实现不允许 GROUP BY 列带有长度可变的数据类型(如文本或备注型字段)。
除聚集计算语句外,SELECT 语句中的每个列都必须在 GROUP BY 子句中给出。
如果分组列中具有 NULL 值,则 NULL 将作为一个分组返回。如果列中有多行 NULL 值,它们将分为一组。
GROUP BY 子句必须出现在 WHERE 子句之后,ORDER BY 子句之前。
过滤分组:
HAVING 非常类似于 WHERE。唯一的差别是 WHERE 过滤行,而 HAVING 过滤分组。
SELECT cust_id, COUNT() AS orders
FROM Orders
GROUP BY cust_id
HAVING COUNT() >= 2;
WHERE 和 HAVING 子句可同时使用
SELECT vend_id, COUNT() AS num_prods
FROM Products
WHERE prod_price >= 4
GROUP BY vend_id
HAVING COUNT() >= 2
分组和排序
ORDER BY 与 GROUP BY 差别
ORDER BY:排序产生的输出;任意列都可以使用(甚至非选择的列也可以使用);不一定需要。
GROUP BY:分组行,但输出可能不是分组的顺序;只可能使用选择列或表达式列,而且必须使用每个选择列表达式;如果与聚集函数一起使用列(或表达式),则必须使用。
一般在使用 GROUP BY 子句时,应该也给出 ORDER BY 子句。这是保证数据正确排序的唯一方法。
SELECT order_num, COUNT() AS items
FROM OrderItems
GROUP BY order_num
HAVING COUNT() >= 3
ORDER BY items, order_num;
SELECT 子句顺序:
子句说明
是否必须使用
SELECT
要返回的列或表达式
是
FROM
从中检索数据的表
仅在从表选择数据时使用
WHERE
行级过滤
否
GROUP BY
分组说明
仅在按组计算聚集时使用
HAVING
组级过滤
否
ORDER BY
输出排序顺序
否
使用子查询
SELECT 语句是SQL的查询。SQL还允许创建子查询,即嵌套在其他查询中的查询。
SELECT cust_id
FROM Orders
WHERE order_num IN (SELECT order_num
FROM OrderItems
WHERE prod_id = ‘RGAN01’);
作为计算字段使用子查询
SELECT cust_name,
cust_state,
(SELECT COUNT(*)
FROM Orders
WHERE Orders.cust_id = Customers.cust_id) AS
orders
FROM Customers
ORDER BY cust_name;
联结表
为什么要使用联结
联结是一种机制,用来在一条 SELECT 语句中关联表。
创建联结:
SELECT vend_name, prod_name, prod_price
FROM Vendors, Products
WHERE Vendors.vend_id = Products.vend_id;
WHERE 子句的重要性
在一条 SELECT 语句中联结几个表时,相应的关系是在运行中构造的。在联结两个表时,实际上是将第一个表中的每一行与第二个表中的每一行配对。WHERE 子句作为过滤条件,它只包含那些匹配给定条件的行。
内部联结:
SELECT vend_name, prod_name, prod_price
FROM Vendors INNER JOIN Products
ON Vendors.vend_id = Products.vend_id
使用这种语法时,联结条件用特定的 ON 子句而不是 WHERE 子句给出。
联结多个表:
SQL 对一条 SELECT 语句中可以联结的表的数目没有限制。创建联结的基本规则也相同。
SELECT prod_name, vend_name, prod_price, quantity
FROM OrderItems, Products, Vendors
WHERE Products.vend_id = Vendors.vend_id
AND OrderItems.prod_id = Products.prod_id
AND order_num = 20007;
创建高级联结
使用表别名
SQL 允许给列名,计算字段和表名起别名。理由是:
1.
缩短SQL语句
2.
允许在单条 SELECT 语句中多次使用相同的表
SELECT cust_name, cust_contact
FROM Customers AS C, Order AS O, OrderItems AS OI
WHERE C.cust_id = O.cust_id
AND OI.order_num = O.order_num
AND prod_id = ‘RGAN01’;
使用不同类型的联结
自联结:
SELECT c1.cust_id, c1.cust_name, c1.cust_contact
FROM Customers AS c1, Customers AS c2
WHERE c1.cust_name = c2.cust_name
AND c2.cust_contact = ‘Jim Jones’;
自然联结:
SELECT C.*, O.order_num, O.order_date, OI.prod_id, OI.quantity, OI.item_price
FROM Customers AS c, Order AS O, OrderItems AS OI
WHERE C.cust_id = O.cust_id
AND OI.order_num = O.order_num
AND prod_id = ‘RGAN01’;
外部联结:
SELECT Customers.cust_id, Orders.order_num
FROM Customers LEFT OUTER JOIN Orders
ON Customers.cust_id = Orders.cust_id;
用关键字 OUTER JOIN 指定联结的类型。外部联结还包括没有关联行的行。在使用 OUTER JOIN 语法时,必须使用 RIGHT 或 LEFT 关键字指定包括其所有行的表(RIGHT 指出的是 OUTER JOIN 右边的表,而 LEFT 指出的是 OUTER JOIN 左边的表)。
SQL 额外支持一种简化的外部联结语法。
SELECT Customers.cust_id, Orders.order_num
FROM Customers, Orders
WHERE Customers.cust_id = Orders.cust_id;
这里的联结条件是在 WHERE 子句中规定的。与使用 = 号的相等测试不一样,= 操作符用来指定应该包括 Customers 表中的每一行。= 为左边外部联结操作符。它从左边表中检索所有行。
与左外部联结相对的是由外部联结,由 = 指定。
使用带聚集函数的联结
COUNT() 函数
SELECT Customers.cust_id, COUNT(Orders.order_num) AS num_ord
FROM Customers INNER JOIN Orders
ON Customers.cust_id = Orders.cust_id
GROUP BY Customers.cust_id;
聚集函数也可以方便地与其他联结一起使用。
SELECT Customers.cust_id, COUNT(Orders.order_num) AS num_ord
FROM Customers LEFT OUTER JOIN Orders
ON Customers.cust_id = Orders.cust_id
GROUP BY Customers.cust_id;
组合查询
创建组合查询
使用 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’;
UNION 规则:
UNION 必须由两条或两条以上的 SELECT 语句组成,语句之间用关键字 UNION 分隔。
UNION 中的每个查询必须包含相同的列、表达式或聚集函数。
列数据类型必须兼容:类型不必完全相同,但必须是 DBMS 可以隐含地转换的类型。
UNION 从查询结果中自动去除了重复的行,如果想返回所有匹配行,可以使用 UNION ALL。
在用 UNION 组合查询时,只能使用一条 ORDER BY 子句,它必须出现在最后一条 SELECT 语句之后。
插入数据
插入完整的行:
INSERT INTO Customers
VALUES(‘10000006’,
‘Toy Land’,
‘123 Any Street’,
‘New York’,
‘NY’,
‘11111’,
‘USA’,
NULL,
NULL);
或者
INSERT INTO Customers(cust_id,
cust_name,
cust_address,
cust_city,
cust_state,
cust_zip,
cust_country,
cust_contact,
cust_email)
VALUES(‘10000006’,
‘Toy Land’,
‘123 Any Street’,
‘New York’,
‘NY’,
‘11111’,
‘USA’,
NULL,
NULL);
插入部分行:
INSERT INTO Customers(cust_id,
cust_name,
cust_address,
cust_city,
cust_state,
cust_zip,
cust_country)
VALUES(‘10000006’,
‘Toy Land’,
‘123 Any Street’,
‘New York’,
‘NY’,
‘11111’,
‘USA’);
插入检索出的数据:
INSERT INTO Customers(cust_id,
cust_name,
cust_address,
cust_city,
cust_state,
cust_zip,
cust_country)
SELECT cust_id,
cust_name,
cust_address,
cust_city,
cust_state,
cust_zip,
cust_country
FROM CustNew;
从一个表复制到另一个表
SELECT *
INTO CustCopy
FROM Customers;
更新和删除数据
更新数据:
UPDATE Customers
SET cust_email = ‘kim@thetoystore.com’
WHERE cust_id = ‘10000005’;
更新多个列
UPDATE Customers
SET cust_contact = ‘Sam Roberts’,
cust_email = ‘kim@thetoystore.com’
WHERE cust_id = ‘10000005’;
删除数据:
DELETE FROM Customers
WHERE cust_id = ‘10000006’;
更新和删除的指导原则:
除非确实打算更新和删除每一行,否则绝对不要使用不带 WHERE 子句 的 UPDATE 或 DELETE 语句。
保证每个表都有主键。
在对 UPDATE 或 DELETE 语句使用 WHERE 子句前,应该先用 SELECT 进行测试,保证它过滤的时正确的记录。
使用强制实施引用完整性的数据库。
创建和操纵表
创建表:
利用 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
);
NULL 值就是没有值或缺值。允许 NULL 的列允许在插入行时不给出该列的值。
默认值在 CREATE TABLE 语句的列定义中用关键字 DEFAULT 指定。
CREATE TABLE Products
(
prod_id CHAR(10) NOT NULL,
vend_id CHAR(10) NOT NULL,
prod_name CHAR(254) NOT NULL,
quantity INTEGER NOT NULL DEFAULT 1,
prod_price DECIMAL(8,2) NOT NULL
);
更新表:
增加列
ALTER TABLE Vendors
ADD vend_phone CHAR(20);
删除列
ALTER TABLE Vendors
DROP COLUMN vend_phone;
删除表:
DROP TABLE CustCopy;
重命名表:
RENAME
使用视图
将查询包装成一个名为 ProductCustomer 虚拟表,即视图,不包含任何列或数据,包含的是一个查询。
SELECT cust_name, cust_contact
FROM ProductCustomers
WHERE prod_id = ‘RGAN01’;
为什么使用视图:
重用 SQL 语句。
简化复杂的 SQL 操作。在编写查询后,可以方便地重用它而不必知道它的基本查询细节。
使用表的组成部分而不是整个表。
保护数据。可以给用户授予表的特定部分的访问权限而不是整个表的访问权限。
更改数据格式和表示。视图可返回与底层表的表示和格式不同的数据。
视图的规则和限制:
视图必须唯一命名。
对于可以创建的视图数目没有限制。
创建视图必须具有足够的访问权限。
视图可以嵌套。
许多 DBMS 禁止在视图查询中使用 ORDER BY 子句。
有的 DBMS 要求命名返回的所有列,如果列是计算字段,则需要使用别名。
视图不能索引,也不能有关联的触发器或默认值。
有的 DBMS 把视图作为只读的查询,这表示可以从视图检索数据,但不能将数据写回底层表。
有的 DBMS 允许创建视图,它不允许进行导致行不再属于视图的插入或更新。
创建视图
CREATE VIEW viewname;
删除视图
DROP VIEW viewname;
利用视图简化复杂的联结
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 * FROM ProductCustomers 引用视图
SELECT cust_name, cust_contact
FROM ProductCustomers
WHERE prod_id = ‘RGAN01’;
用视图重新格式化检索除的数据
CREATE VIEW VendorLocations AS
SELECT RTRIM(vend_name) + ‘(’ + RTRIM(vend_country) + ‘)’ AS vend_title
FROM Vendors;
用视图过滤不想要的数据
CREATE VIEW CustomerEMailList AS
SELECT cust_id, cust_name, cust_email
FROM Customers
WHERE cust_email IS NOT NULL;
使用视图与计算字段
CREATE VIEW OrderItemsExpanded AS
SELECT order_num,
prod_id,
quantity,
item_price,
quantity*item_price AS expanded_price
FROM OrderItems;
使用存储过程
为什么要使用存储过程:
通过把处理封装在容易使用的单元里,简化复杂的操作。
由于不要求反复建立一系列处理步骤,保证了数据的一致性。
简化对变动的管理。通过存储过程限制对基础数据的访问减少了数据讹误的机会。
存储过程通常以编译过的形式存储,所以DBMS 为处理命令所做的工作较少,提高了性能。
存在一些只能用在单个请求中的 SQL 元素和特性,存储过程可以使用它们来编写功能更强更灵活的代码。
执行存储过程:
EXECUTE 接受存储过程名和需要传递给它的任何参数。
EXECUTE AddNewProduct(‘JTS01’,
‘Stuffed Eiffel Tower’,
6.49,
‘Plush stuffed toy with the text La Tour Eiffel in red white and blue’)
创建存储过程:
CREATE PROCEDURE MailingListCount
AS
DECLARE @cnt INTEGER
SELECT @cnt = COUNT(*)
FROM Customers
WHERE NOT cust_email IS NULL;
RETURN @cnt;
管理事务处理
事务处理:
事务(transaction)指一组 SQL 语句;
回退(rollback)指撤销指定 SQL 语句的过程;
提交(commit)指将未存储的 SQL 语句结果写入数据库表;
保留点(savepoint)指事务处理中设置的临时占位符(placeholder),可以对它发布回退(与回退整个事务处理不同)。
控制事务处理:
有的 DBMS 要求明确标识事务处理块的开始和结束。
BEGIN TRANSACTION
…
COMMIT TRANSACTION
ROLLBACK 命令用来撤销 SQL 语句:
DELETE FROM Orders;
ROLLBACK;
使用 COMMIT 语句进行明确的提交:
BEGIN TRANSACTION
DELETE OrderItems WHERE order_num = 12345
DELETE Orders WHERE order_num = 12345
COMMIT TRANSACTION
使用保留点:
保留点是可以回退到的某个占位符。
SAVE TRANSACTION delete1;
每个保留点都取标识它唯一的名字,以便回退时 DBMS 知道要退回何处。
ROLLBACK TRANSACTION delete1;
保留点越多越好。
使用游标
有时需要在检索出来的行中前进或后退一行或多行,这是使用游标的原因。游标时一个存储在 DBMS 服务器上的数据库查询,它不是一条 SELECT 语句,而是被该语句检索出来的结果集。在存储了游标之后,应用程序可以根据需要滚动或浏览其中的数据。
常见的选项和特性:
能够标记游标为只读,使数据能读取,但不能更新和删除。
能控制可以执行的定向操作(向前、向后、第一、最后、绝对位置、相对位置等)。
能标记某些列为可编辑的,某些列为不可编辑的。
规定范围,使游标对创建它的特定请求或对所有请求可访问。
指示 DBMS 对检索出的数据做复制,使在游标打开和访问期间数据不变化。
使用游标
创建游标:
DECLARE 命名游标,并定义相应的 SELECT 语句,根据需要带 WHERE 和其他子句。
DECLARE CustCursor CURSOR
FOR SELECT * FROM Customers
WHERE cust_email IS NULL
使用游标:
游标用 OPEN CURSOR 语句打开
OPEN CURSOR CustCursor
然后可以用 FETCH 语句访问游标数据。FETCH 指出要检索的行,从何处检索它们以及将它们放于何处。
DECALRE TYPE CustCursor IS REF CURSOR RETURN Customers%ROWTYPE;
BEGIN
OPEN CustCursor;
FETCH CustCursor INTO CustRecord;
CLOSE CustCursor;
END;
关闭游标:
CLOSE CustCursor
DEALLOCATE CURSOR CustCursor
了解高级 SQL 特性
约束
主键:
主键是一种特殊的约束,它用来保证一个列(或一组列)中的值是唯一的,并且永不改动。
表中任意列只要满足以下条件,都可以用于主键:
任意两行的主键值都不相同。
每行都具有一个主键值。
包含主键值的列不修改或更新。
主键值不能重用。如果表中删除某一行,其主键值不分配给新行。
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)
);
唯一约束:
唯一约束用来保证一个列(或一组列)中的数据唯一。
唯一约束既可以用 UNIQUE 关键字在表定义中定义,也可以用单独的 CONSTRAINT 定义。
它们类似于主键,但存在几个重要的区别:
表可包含多个唯一约束,但么个表只允许一个主键。
唯一约束可包含 NULL 值。
唯一约束列可修改或更新。
唯一约束列的值可重复使用。
与主键不一样,唯一约束不能用来定义外键。
检查约束:
检查约束用来保证一个列(或一组列)中的数据满足一组指定的条件。
检查约束的常见用途为:
检查最小或最大值。
指定范围。
只允许特定的值。
ADD CONSTRAINT CHECK (gender LIKE ‘[MF]’)
索引
索引改善检索操作的性能,但降低数据插入、修改和删除的性能。
索引数据可能要占用大量的存储空间。
并非所有数据都适合于索引。
索引用于数据过滤和数据排序。
可以在索引中定义多个列。
索引用 CREATE INDEX 语句创建。
CREATE INDEX prod_name_ind
ON PRODUCTS (prod_name);
索引必须唯一命名。
触发器
触发器内的代码具有以下数据的访问权:
INSERT 操作中的所有新数据;
UPDATE 操作中的所有新数据和旧数据;
DELETE 操作中删除的数据。
以下是触发器的一些常见用途:
保证数据一致。
基于某个表的变动在其他表上执行活动。
进行额外的验证并根据需要回退数据。
计算计算列的值或更新时间戳。
CREATE TRIGGER customer_state
ON Customers
FOR INSERT, UPDATE
AS
UPDATE Customers
SET cust_state = Upper(cust_state)
WHERE Customers.cust_id = inserted.cust_id;
数据库安全
需要保护的某些操作:
对数据库管理功能的访问。
对特定数据库或表的访问。
访问的类型。
仅通过视图或存储过程对表进行访问。
创建多层次的安全措施,从而允许多种基于登陆的访问和控制;
限制管理用户账号的能力。