sql基础
第2课 SQL 的 SELECT 语句:
单条 SQL 语句必须以分号(;)分隔。
SQL 语句不区分大小写。
在处理 SQL 语句时,其中所有空格都被忽略。SQL 语句可以写成长长 的一行,也可以分写在多行。
SQL 语句一般返回原始的、无格式的数据。数 据的格式化是表示问题,而不是检索问题。
使用 DISTINCT 关键字,顾名思义,它指示数据库只返回不同的值。
TOP 关键字来限制SELECT最多查找多少行。
LIMIT关键字指定返回的行数。LIMIT 带的 OFFSET 指定从哪儿开始
LIMIT 5 OFFSET 5 指示返回从第 5 行起的 5 行数据。 第一个数字是检索的行数,第二个数字是指从哪儿开始。
第一个被检索的行是第 0 行,而不是第 1 行。因此,LIMIT 1 OFFSET 1 会检索第 2 行,而不是第 1 行。
0行开始,limit限定行数,offset偏移几行。offset不是偏移几行 是第几行的下面一行 offset 3 是第三行的下面一行: 第四行。
不存在第0行啊。SQL必知必会第18页,
第3课排序检索数据 使用 SELECT 语句的 ORDER BY 子句排序检索数据:
SELECT prod_id, prod_price, prod_name
FROM Products
ORDER BY 2, 3;
ORDER BY 2, 3 表示先按 prod_price,再按 prod_name 进行排序。不明确给出列名有可能造成错用列名排序。
指定 DESC 、DESCENDING关键字进行降序排序。
第4课过滤数据 使用 SELECT 语句的 WHERE 子句指定搜索条件:
不匹配检查,WHERE vend_id <> 'DLL01'; WHERE vend_id != 'DLL01';!=和<>通常可以互换。但是,并非所有 DBMS 都支持这两种不等于操 作符。例如,Microsoft Access 支持<>而不支持!=。
范围值检查,BETWEEN 操作符。
空值检查,NULL 无值(no value),它与字段包含 0、空字符串或仅仅包含空格不同。
第5课高级数据过滤 组合WHERE 子句 WHERE 子句:
SELECT prod_id, prod_price, prod_name
FROM Products
WHERE vend_id = 'DLL01' AND prod_price <= 4;
OR 操作符,检索匹配任一条件的 行。但许多 DBMS 在 OR WHERE 子句的第一个条件得到满足的情 况下,就不再计算第二个条件。
SELECT prod_name, prod_price
FROM Products
WHERE vend_id = 'DLL01' OR vend_id = ‘BRS01’;
SQL在处理 OR 操作符前,优先处理 AND 操作符。用圆括号括起来。
IN 操作符用来指定条件范围,和OR类似。
SELECT prod_name, prod_price
FROM Products
WHERE vend_id IN ( 'DLL01', 'BRS01' )
ORDER BY prod_name;
NOT操作符,否定其后所跟的 任何条件。NOT 关键字可以用在要过滤的列前, 而不仅是在其后。
第6课 用通配符进行过滤 LIKE 操作符:
百分号(%)通配符。在搜索串中,%表示任何字符出现任意次数。% 代表搜索模式中给定位置的 0 个、1 个或多个字符。但有个例外,这就是 NULL。
SELECT prod_id, prod_name
FROM Products
WHERE prod_name LIKE 'Fish%';
下划线()通配符。下划线的用途与%一样,但它只匹配单个字符,而不是多个字符。不能多也不能少。
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;
即J% or M%
不要过度使用通配符。如果其他操作符能达到相同的目的,应该使用 其他操作符。
在确实需要使用通配符时,也尽量不要把它们用在搜索模式的开始 处。把通配符置于开始处,搜索起来是最慢的。
第7课 创建计算字段
拼接(concatenate) 将值联结到一起(将一个值附加到另一个值)构成单个值。、
多数 DBMS :
SELECT vend_name + ' (' + vend_country + ')'
FROM Vendors
ORDER BY vend_name;
SELECT vend_name || ' (' || vend_country || ')'
FROM Vendors
ORDER BY vend_name;
使用 MySQL 或 MariaDB:
SELECT Concat(vend_name, ' (', vend_country, ')')
FROM Vendors
ORDER BY vend_name;
结果去掉空格:TRIM 函数, RTRIM()(去掉字符串右边的 空格)、LTRIM()(去掉字符串左边的空格)以及 TRIM()(去掉字符 串左右两边的空格)。
SELECT RTRIM(vend_name) + ' (' + RTRIM(vend_country) + ')'
FROM Vendors
ORDER BY vend_name;
使用别名alias,用 AS 关键字赋予。
SELECT RTRIM(vend_name) + ' (' + RTRIM(vend_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;
第8课 使用函数处理数据
屏幕快照 2018-05-15 下午4.04.54.png
常用函数:
用于处理文本字符串(如删除或填充值,转换值为大写或小写)的文 本函数。
用于在数值数据上进行算术操作(如返回绝对值,进行代数运算)的 数值函数。
用于处理日期和时间值并从这些值中提取特定成分(如返回两个日期 之差,检查日期有效性)的日期和时间函数。
返回 DBMS 正使用的特殊信息(如返回用户登录信息)的系统函数。
文本处理函数:TRIM()、UPPER()
LEFT()(或使用子字符串函数) 返回字符串左边的字符
LENGTH()(也使用DATALENGTH()或LEN()) 返回字符串的长度
LOWER()(Access使用LCASE()) 将字符串转换为小写
LTRIM() 去掉字符串左边的空格
RIGHT()(或使用子字符串函数) 返回字符串右边的字符
RTRIM() 去掉字符串右边的空格
SOUNDEX() 返回字符串的SOUNDEX值
UPPER()(Access使用UCASE()) 将字符串转换为大写
日期和时间处理函数,不用数据库使用的时间格式不同
SELECT order_num
FROM Orders
WHERE to_number(to_char(order_date, 'YYYY')) = 2012;
数值处理函数,主要用于代数、三角或几何运算。
ABS() 返回一个数的绝对值
COS() 返回一个角度的余弦
EXP() 返回一个数的指数值
PI() 返回圆周率
SIN() 返回一个角度的正弦
SQRT() 返回一个数的平方根
TAN() 返回一个角度的正切
第9课 汇总数据,使用这些函数,SQL 查询可用于检索数据,以便分析和报表 生成。
AVG() 返回某列的平均值
COUNT() 返回某列的行数
MAX() 返回某列的最大值
MIN() 返回某列的最小值
SUM() 返回某列值之和
SELECT AVG(prod_price) AS avg_price
FROM Products WHERE vend_id = 'DLL01';
SELECT SUM(item_price*quantity) AS total_price
FROM OrderItems
WHERE order_num = 20005;
聚集不同值, 只包含不同的值,指定 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;
第10课 分组数据 两个新SELECT 语句子句:GROUP BY 子句和 HAVING 子句。
SELECT vend_id, COUNT(*) AS num_prods
FROM Products
GROUP BY vend_id;
GROUP BY 子句可以包含任意数目的列,因而可以对分组进行嵌套, 更细致地进行数据分组。
如果在 GROUP BY 子句中嵌套了分组,数据将在最后指定的分组上进 行汇总。换句话说,在建立分组时,指定的所有列都一起计算(所以 不能从个别的列取回数据)。
GROUP BY 子句中列出的每一列都必须是检索列或有效的表达式(但 不能是聚集函数)。如果在 SELECT 中使用表达式,则必须在 GROUP BY 子句中指定相同的表达式。不能使用别名。
大多数 SQL 实现不允许 GROUP BY 列带有长度可变的数据类型(如文 本或备注型字段)。
除聚集计算语句外,SELECT 语句中的每一列都必须在 GROUP BY 子句 中给出。
如果分组列中包含具有 NULL 值的行,则 NULL 将作为一个分组返回。 如果列中有多行 NULL 值,它们将分为一组。
GROUP BY 子句必须出现在 WHERE 子句之后,ORDER BY 子句之前。
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:对行分组;但输出可能不是分组的顺序,只可能使用选择列或表达式列,而且必须使用每个选择列表达式;如果与聚集函数一起使用列(或表达式),则必须使用。
SELECT子句顺序
屏幕快照 2018-05-15 下午5.33.55.png
第11课 使用子查询
SELECT 语句是 SQL 的查询。子查询(subquery),即嵌套在其他查询中的查询。
利用子查询进行过滤,
SELECT cust_id
FROM Orders
WHERE order_num IN (SELECT order_num FROM OrderItems WHERE prod_id = 'RGAN01');
SELECT cust_name, cust_contact FROM Customers WHERE cust_id IN (SELECT cust_id FROM Orders
WHERE order_num IN (SELECT order_num FROM OrderItems WHERE prod_id = 'RGAN01'));
第12课 联结表
将数据分解为多个表,使用联结用一条 SELECT 语句就检索出数据。
内联结\等值联结(equijoin)
SELECT vend_name, prod_name, prod_price
FROM Vendors, Products
WHERE Vendors.vend_id = Products.vend_id;
SELECT vend_name, prod_name, prod_price
FROM Vendors INNER JOIN Products
ON Vendors.vend_id = Products.vend_id;
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;
第13课 创建高级联结 使用表别名,对被联结的表使用聚集函数。
SELECT cust_name, cust_contact
FROM Customers AS C, Orders AS O, OrderItems AS OI
WHERE C.cust_id = O.cust_id
AND OI.order_num = O.order_num
AND prod_id = 'RGAN01';
SELECT cust_id, cust_name, cust_contact
FROM Customers
WHERE cust_name = (SELECT cust_name
FROM Customers
WHERE cust_contact = 'Jim Jones');
同
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 Customers.cust_id, Orders.order_num
FROM Customers INNER JOIN Orders
ON Customers.cust_id = Orders.cust_id;
同
SELECT Customers.cust_id, Orders.order_num
FROM Customers LEFT OUTER JOIN Orders
ON Customers.cust_id = Orders.cust_id;
在使用 OUTER JOIN 语法时,必须使用 RIGHT 或 LEFT 关键字指定包括其所有行的表
(RIGHT 指出的是 OUTER JOIN 右边的表,而 LEFT 指出的是 OUTER JOIN 左边的表)。
外联结形式:左外联结和右外联结。调整 FROM 或 WHERE 子句中表的顺序,左外联结可以转换为右外联结。因此,这两种外联 结可以互换使用,哪个方便就用哪个。
使用带聚集函数的联结
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;
内联与外联的区别??
第14课 组合查询 利用 UNION 操作符将多条 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';
同
SELECT cust_name, cust_contact, cust_email
FROM Customers
WHERE cust_state IN ('IL','IN','MI')
OR cust_name = 'Fun4All';
使用UNION可能比使用WHERE子句更为复杂。但 对于较复杂的过滤条件,或者从多个表(而不是一个表)中检索数据的 情形,使用 UNION 可能会使处理更简单。使用 UNION 组合 SELECT 语句的数目,SQL 没有标准限制。
UNION 必须由两条或两条以上的 SELECT 语句组成,语句之间用关键 字 UNION 分隔(因此,如果组合四条 SELECT 语句,将要使用三个 UNION 关键字)。
UNION 中的每个查询必须包含相同的列、表达式或聚集函数(不过, 各个列不需要以相同的次序列出)。
列数据类型必须兼容:类型不必完全相同,但必须是 DBMS 可以隐含 转换的类型(例如,不同的数值类型或不同的日期类型)。
在用 UNION 组合查询时,只 能使用一条 ORDER BY 子句,它必须位于最后一条 SELECT 语句之后。
第15课 插入数据 利用 SQL 的 INSERT 语句将数据插入表中。
插入完整的行;
插入行的一部分;
插入某些查询的结果。
必须给每一列提供一个值。如果某列没有值, 如上面的 cust_contact 和 cust_email 列,则应该使用 NULL 值(假定 表允许对该列指定空值)。各列必须以它们在表定义中出现的次序填充。
如果表的定义允许,则可以在 INSERT 操作中省略某些列。省略的列 必须满足以下某个条件。
该列定义为允许 NULL 值(无值或空值)。
在表定义中给出默认值。这表示如果不给出值,将使用默认值。
如果表中不允许有 NULL 值或者默认值,这时却省略了表中的值, DBMS 就会产生错误消息,相应的行不能成功插入。
INSERT INTO Customers
VALUES('1000000006',
'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('1000000006',
'Toy Land',
'123 Any Street',
'New York',
'NY',
'11111',
'USA');
使用INSERT SELECT 从 CustNew 中将所有数据导入 Customers。
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;
SELECT *
INTO CustCopy
FROM Customers;
SELECT 语句创建一个名为 CustCopy 的新表
CREATE TABLE CustCopy AS
SELECT * FROM Customers;
第16课 更新和删除数据 利用 UPDATE 和 DELETE 语句进一步操作表数据。
UPDATE Customers
SET cust_contact = 'Sam Roberts',
cust_email = 'sam@toyland.com'
WHERE cust_id = '1000000006';
DELETE FROM Customers
WHERE cust_id = '1000000006';
// 如果省略 WHERE 子句,它将删除表中每个顾客。
提示:友好的外键
第 12 课介绍了联结,简单联结两个表只需要这两个表中的公用字段。 也可以让 DBMS 通过使用外键来严格实施关系(这些定义在附录 A 中)。存在外键时,DBMS 使用它们实施引用完整性。例如要向 Products 表中插入一个新产品,DBMS 不允许通过未知的供应商 id插入它,因为 vend_id 列是作为外键连接到 Vendors 表的。那么, 这与 DELETE 有什么关系呢?使用外键确保引用完整性的一个好处是, DBMS 通常可以防止删除某个关系需要用到的行。例如,要从 Products 表中删除一个产品,而这个产品用在 OrderItems 的已有订 单中,那么 DELETE 语句将抛出错误并中止。这是总要定义外键的另 一个理由。
提示:FROM 关键字
在某些 SQL 实现中,跟在 DELETE 后的关键字 FROM 是可选的。但是 即使不需要,也最好提供这个关键字。这样做将保证 SQL 代码在 DBMS 之间可移植。
DELETE 不需要列名或通配符。DELETE 删除整行而不是删除列。要删除 指定的列,请使用 UPDATE 语句。
使用 UPDATE 或 DELETE 时所遵循的重要原则。
除非确实打算更新和删除每一行,否则绝对不要使用不带 WHERE 子句 的 UPDATE 或 DELETE 语句。
保证每个表都有主键(如果忘记这个内容,请参阅第 12 课),尽可能 像 WHERE 子句那样使用它(可以指定各主键、多个值或值的范围)。
在 UPDATE 或 DELETE 语句使用 WHERE 子句前,应该先用 SELECT 进 行测试,保证它过滤的是正确的记录,以防编写的 WHERE 子句不正确。
使用强制实施引用完整性的数据库(关于这个内容,请参阅第 12 课),
这样 DBMS 将不允许删除其数据与其他表相关联的行。
有的 DBMS 允许数据库管理员施加约束,防止执行不带 WHERE 子句 的 UPDATE 或 DELETE 语句。如果所采用的 DBMS 支持这个特性,应
该使用它。
若是 SQL 没有撤销(undo)按钮,应该非常小心地使用 UPDATE 和 DELETE, 否则你会发现自己更新或删除了错误的数据。
第17课 创建和操纵表 创建、更改和删除表的基本知识。
屏幕快照 2018-05-16 下午5.21.39.png 屏幕快照 2018-05-16 下午5.22.25.png 屏幕快照 2018-05-16 下午5.24.10.png
更新表 ALTER TABLE
理想情况下,不要在表中包含数据时对其进行更新。应该在表的设 计过程中充分考虑未来可能的需求,避免今后对表的结构做大 改动。
所有的 DBMS 都允许给现有的表增加列,不过对所增加列的数据类型 (以及 NULL 和 DEFAULT 的使用)有所限制。
许多 DBMS 不允许删除或更改表中的列。
多数 DBMS 允许重新命名表中的列。
许多 DBMS 限制对已经填有数据的列进行更改,对未填有数据的列几
乎没有限制。
ALTER TABLE Vendors
ADD vend_phone CHAR(20);
删除表
DROP TABLE CustCopy;
重命名表 DB2、MariaDB、MySQL、Oracle 和 PostgreSQL 用户使用 RENAME 语句,SQL Server 用户使用 sp_rename 存储过程,SQLite 用户使用 ALTER TABLE 语句。
第18课 使用视图
一个最常见的视图应用是隐藏复杂的 SQL,这通常涉及联结。
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 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;
用视图过滤不想要的数据
CREATE VIEW CustomerEMailList AS
SELECT cust_id, cust_name, cust_email
FROM Customers
WHERE cust_email IS NOT NULL;
使用视图与计算字段
SELECT prod_id,
quantity,
item_price,
quantityitem_price AS expanded_price
FROM OrderItems
WHERE order_num = 20008;
同
CREATE VIEW OrderItemsExpanded AS
SELECT order_num,
prod_id,
quantity,
item_price,
quantityitem_price AS expanded_price
FROM OrderItems;
第19课 使用存储过程 创建和使用存储过程的基本语法。
存储过程就是为以后使用而保存的一条 或多条 SQL 语句。可将其视为批文件,虽然它们的作用不仅限于批处理。使用存储过程有三个主要的好处,即简单、安全、高性能。
通过把处理封装在一个易用的单元中,可以简化复杂的操作(如前面 例子所述)。
由于不要求反复建立一系列处理步骤,因而保证了数据的一致性。如 果所有开发人员和应用程序都使用同一存储过程,则所使用的代码都 是相同的。
168 | 第 19 课 使用存储过程
这一点的延伸就是防止错误。需要执行的步骤越多,出错的可能性就
越大。防止错误保证了数据的一致性。
简化对变动的管理。如果表名、列名或业务逻辑(或别的内容)有变
化,那么只需要更改存储过程的代码。使用它的人员甚至不需要知道
这些变化。
这一点的延伸就是安全性。通过存储过程限制对基础数据的访问,减
少了数据讹误(无意识的或别的原因所导致的数据讹误)的机会。
因为存储过程通常以编译过的形式存储,所以 DBMS 处理命令所需的 工作量少,提高了性能。
存在一些只能用在单个请求中的 SQL 元素和特性,存储过程可以使用 它们来编写功能更强更灵活的代码。
EXECUTE 接受存储过程 名和需要传递给它的任何参数。
EXECUTE AddNewProduct( 'JTS01',
'Stuffed Eiffel Tower',
6.49,
'Plush and blue' );
存储过程所
完成的工作:
验证传递的数据,保证所有 4 个参数都有值;
生成用作主键的唯一 ID;
将新产品插入 Products 表,在合适的列中存储生成的主键和传递的
数据。
创建存储过程:对邮件发送清单中具有邮件地址的顾客进行计数。
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;
略.....
第20课 管理事务处理 利用 COMMIT 和 ROLLBACK 语句管理事务处理。
通过确保成批的 SQL 操作要么完全执行,要么完全不执行,来维护数据库的完整性。
事务(transaction)指一组 SQL 语句;
回退(rollback)指撤销指定 SQL 语句的过程;
提交(commit)指将未存储的 SQL 语句结果写入数据库表;
保留点(savepoint)指事务处理中设置的临时占位符(placeholder),
可以对它发布回退(与回退整个事务处理不同)。
BEGIN TRANSACTION
DELETE OrderItems WHERE order_num = 12345
DELETE Orders WHERE order_num = 12345
COMMIT TRANSACTION
第21课 使用游标
游标(cursor)是一个存储在 DBMS 服务器上的数据库查询, 它不是一条 SELECT 语句,而是被该语句检索出来的结果集。在存储了 游标之后,应用程序可以根据需要滚动或浏览其中的数据。
DECLARE CustCursor CURSOR
FOR
SELECT * FROM Customers
WHERE cust_email IS NULL
DECLARE @cust_id CHAR(10),
@cust_name CHAR(50),
@cust_address CHAR(50),
@cust_city CHAR(50),
@cust_state CHAR(5),
@cust_zip CHAR(10),
@cust_country CHAR(50),
@cust_contact CHAR(50),
@cust_email CHAR(255)
OPEN CustCursor
FETCH NEXT FROM CustCursor
INTO @cust_id, @cust_name, @cust_address,
@cust_city, @cust_state, @cust_zip,
@cust_country, @cust_contact, @cust_email
WHILE @@FETCH_STATUS = 0
BEGIN
FETCH NEXT FROM CustCursor
INTO @cust_id, @cust_name, @cust_address,
@cust_city, @cust_state, @cust_zip,
@cust_country, @cust_contact, @cust_email
...
END
CLOSE CustCursor
第22课 高级SQL特性 个高级数据处理特性:约束、索引和触发器。
关系数据库存储 分解为多个表的数据,每个表存储相应的数据。利用键来建立从一个表到 另一个表的引用(由此产生了术语引用完整性(referential integrity)。
主键是一种特殊的约束,用来保证一列(或 一组列)中的值是唯一的,而且永不改动。
任意两行的主键值都不相同。
每行都具有一个主键值(即列中不允许 NULL 值)。
包含主键值的列从不修改或更新。
主键值不能重用。如果从表中删除某一行,其主键值不分配给新行。
外键是表中的一列,其值必须列在另一表的主键中。
唯一约束 唯一约束用来保证一列(或一组列)中的数据是唯一的。它们类似于主
键,但存在以下重要区别。
表可包含多个唯一约束,但每个表只允许一个主键。 唯一约束列可包含 NULL 值。
唯一约束列可修改或更新。
唯一约束列的值可重复使用。
与主键不一样,唯一约束不能用来定义外键。
检查约束 检查约束用来保证一列(或一组列)中的数据满足一组指定的条件。检
查约束的常见用途有以下几点。
检查最小或最大值。例如,防止 0 个物品的订单(即使 0 是合法的数)。 指定范围。例如,保证发货日期大于等于今天的日期,但不超过今天
起一年后的日期。
只允许特定的值。例如,在性别字段中只允许 M 或 F。
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
);
索引 索引用来排序数据以加快搜索和排序操作的速度。
使索引有用的因素是什么?很简单,就是恰当的排序。
索引改善检索操作的性能,但降低了数据插入、修改和删除的性能。 在执行这些操作时,DBMS 必须动态地更新索引。
索引数据可能要占用大量的存储空间。
并非所有数据都适合做索引。取值不多的数据(如州)不如具有更多
可能值的数据(如姓或名),能通过索引得到那么多的好处。
索引用于数据过滤和数据排序。如果你经常以某种特定的顺序排序数
据,则该数据可能适合做索引。
可以在索引中定义多个列(例如,州加上城市)。这样的索引仅在以州
加城市的顺序排序时有用。如果想按城市排序,则这种索引没有用处
CREATE INDEX prod_name_ind
ON Products (prod_name);
触发器 触发器是特殊的存储过程,它在特定的数据库活动发生时自动执行。触发
器可以与特定表上的 INSERT、UPDATE 和 DELETE 操作(或组合)相关联。
与存储过程不一样(存储过程只是简单的存储 SQL 语句),触发器与单 个的表相关联。与 Orders 表上的 INSERT 操作相关联的触发器只在 Orders 表中插入行时执行。类似地,Customers 表上的 INSERT 和 UPDATE 操作的触发器只在表上出现这些操作时执行。
触发器内的代码具有以下数据的访问权:
INSERT 操作中的所有新数据;
UPDATE 操作中的所有新数据和旧数据;
DELETE 操作中删除的数据。
创建一个触发器,它对所有 INSERT 和 UPDATE 操作,将Customers 表中的 cust_state 列转换为大写。
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;
数据库安全
需要保护的操作有:
对数据库管理功能(创建表、更改或删除已存在的表等)的访问;
对特定数据库或表的访问;
访问的类型(只读、对特定列的访问等);
仅通过视图或存储过程对表进行访问;
创建多层次的安全措施,从而允许多种基于登录的访问和控制;
限制管理用户账号的能力。