SQL语言
索引:
1.规范化准则
使用规范化准则通常是要将表分为含有多列的两个表或多个表,将主键码/外键码关系设计为新的更小的表以便能通过连接操作将它们重新连接起来。
如果要完全拘泥于理论,则设计的数据库很少能令人满意。在开发真正的产品前,按交互式反复推敲设计是非常重要的。
第一范式
第一范式需要在行和列的每一个交点有且只有一个值,并且该值必须是原子性的。在第一范式中不能有重复的组。
第二范式
该准则只适用于主键码由多列组成的表。它声明每一个非键码的列都必须取决于整个主键码。表不能包含有专属于复合主键码的部分的非键码列。
第三范式
第三范式要求非键码列不能取决于另一个非键码列,每一个非键码列都必须取决于主键码列。
第四范式
该准则禁止在主键码和非键码之间存在独立的一对多关系。
2.索引策略
使用索引的准则:
- 对列或存储表主键码的列的唯一索引可以避免重复并保证主键码列中的每一个值唯一的标示行;
- 通常按排序顺序获取的列可能应该被索引;
- 用于连接的列可以被索引,因为系统可以快速连接;
- 如果系统提供了群集索引,最好选择常常查找值范围的列作为索引。
不能使用索引的场合:
- 在查询中已经引用的列从性能方面来说不能从索引得到帮助;
- 只有两个或三个值的列不能从索引得到帮助;
- 有很少行的小型表不能通过索引得到帮助。
3.SELECT查询大全
(1).Select语法
SELECT [ALL|DISTINCT] select_list FROM table/view_list [WHERE search_conditions] [GROUP BY group_by_list] [HAVING search_conditions] [ORDER BY order_by_list]
(2).Select子句
组成
- 选择所有的列:SELECT *;
- 按任意顺序使用一个或多个列名,之间用逗号分隔;
- 可以使用一个或多个字符常量;
- 可以使用一个或多个SQL函数和算术运算符。
别名
可为列指定显示标记(别名)。如:
select pub_name Publisher, pub_id…; select pub_name as Publisher, pub_id…;
删除重复行
ALL返回所有限定的行,其用法是默认的;
DISTINCT只返回唯一的行。
格式要求:
- 在SELECT列表只能使用一次;
- 在SELECT列表中为首词;
- 不能再其后添加逗号。
虽然空值被定义为未知且相互不等,但在一个特殊的列中DISTINCT将每一个NULL作为该列中其他空值的复制来对待。
聚集函数
函数 | 说明 |
---|---|
SUM([DISTINCT] expression) | 数值表达式中(特殊值)的总和 |
AVG([DISTINCT] expression) | 数值表达式中(特殊值)的平均值 |
COUNT([DISTINCT] expression) | 表达式中非空值(特殊)的个数 |
COUNT(*) | 被选择行的个数 |
MAX(expression) | 表达式的最大者 |
MIN(expression) | 表达式的最小者 |
注意COUNT和COUNT(*)的区别:
- COUNT忽略空值;
- COUNT(*)计算所有的行,无论是否有一个特殊的列含有空值。
(3).From子句
可以为表指定别名。如:
select p.pub_id, p.pub_name from publisher p
(4).Where子句
比较运算符
= 等于 > 大于 < 小于 >= 大于等于 <= 小于等于 <> 不等于
组合或逻辑非条件
AND 与 OR 或 NOT 非
优先级:先NOT,然后AND,最后OR。
限制范围
BETWEEN… AND … NOT BETWEEN … AND …
列表(IN、NOT IN)
select au_lname, state from authors where state in ('CA', 'IN', 'MD');
未知值(IS NULL、IS NOT NULL)
select title_id, advance from titles where advance is null;
字符匹配(LIKE和NOT LIKE)
匹配模式必须封闭在引号中,通配符有如下两个:
- %:任一0个或多个字符的字符串;
- _(下划线):任一单个字符。
通配符转义:使用ESCAPE关键字指定转义字符。如:
Select titel_id, notes From titles Where notes like '%27@%' escape '@';
(5).Order by子句
Order by列表可以有一个或多个元素,元素之间用逗号分开,表达式能以升序(默认)或降序(DESC关键字)排列。
表达式可以是:
- 一个列名;
- 一个列名和算术运算或功能;
- 一个显示标签;
- 一个位置编码。
当有空值时,sql-92明确规定:当空值被排序时,它们应该大于所有非空值或小于所有非空值。
(6).Group by子句
如果成组的列包含多个NULL,那么它们就要被放到单一组中。
Group by与聚集函数一起使用时,Group by创建组,聚集函数运算每组的值。
当查询包含where、group by和聚集函数时的执行步骤是:where子句首先查找所需的行,group by子句将这些行成组,组形成后,sql计算组的值。
Group by与Order by配合使用时,Order by总是位于Group by之后。
HAVING子句是一个用于组的WHERE子句,HAVING限制组。
(7).连接
可连接的列
它们的值来自于相同的数据类,最好它们具有完全相同的数据类型。数据类型中的轻微差别(CHAR和VARCHAR,允许NULL和不允许NULL_都可能会引起性能问题。
获得良好的连接的原则
- 理想情况下,连接列是它的表的一个键码列:要么是主键码,要么是外键码。
- 连接列应被索引以得到大量的数据。
- 为了有最好的性能,连接列应该有相同的数据类型,包括它们是否允许NULL值。
连接语法
有两类:
- FROM/WHERE;
- JOIN关键字(SQL92)。
SQL-92为连接提供了一些关键字(JOIN、CROSS JOIN及NATURAL JOIN,它们能与INTER、RIGHT OUTER、LEFT OUTER和FULL OUTER组合以充分利用连接)。
自连接
在单一表内比较值。如:
select ed_id, ed_fname from editor e1, editor e2 where e1.ed_bosss = e2.ed_id;
左外连接
在结果中包含在连接规范中第一个表的所有的行,无论在别的表中是否有匹配的值。如:
select au_fname, au_lname, pub_name from authors left outer join publishers on authors.city = publishers.city;
右外部连接
与左外连接相反。如:
select au_fname, au_lname, pub_name from authors right outer join publishers on authors.city = publishers.city;
全外部连接
返回所有限定的行。如:
select au_fname, au_lname, pub_name from authors full outer join publishers on authors.city = publishers.city;
(8).UNION
对应关系运算中的并运算。
语法:
select_statement UNION select_statement;
每一条select语句都可以有自己的where子句,但整个查询只能使用一个order by子句,必须在最后的select语句中。它适用于所有的输出。
默认下,UNION从结果显示中删除重复的行。要显示所有的行,可以在UNION后增加ALL关键字。
(9).INTERSECT和MINUS
对应关系运算中的交和差运算。
(10).子查询
两种基本形式
子查询有两种基本形式:简单子查询和关联子查询。第一种子查询由内层到外层进行,外查询的进行取决于内查询的结果;第二种则相反,外层sql语句提供内层子查询在计算中要用的值,然后再将子查询的结果传送回外查询。
简单子查询示例:
select pub_name from publishers where publishers.pub_id in (select titels.pub_id from titles where type='business');
关联子查询示例:
select pub_name from publishers where exists (select * from titles where titles.pub_id=publishers.pub_id and type='business');
大部分子查询都可以用连接实现。两者各有优缺点。子查询可以计算一个变化的聚集值并将其返回到外查询进行比较,连接则做不到;子查询只能显示外层表中的信息,当在结果中要包含多个表的信息时,要使用连接。
(NOT)IN
返回0或更多值的子查询。
理解ALL和ANY
ALL表示所有,ANY表示一些。如:
Select title From titles Where advance > all (select advance from publishers, titles where titles.pub_id = publishers.pub_id and pub_name='1bc');
=ANY等价于IN。
但是<>ANY与NOT IN不同。
(NOT)EXISTS
存在性测试。