在1中我们主要讲了在单个表上的查询,而在2中我们将会扩展到多个表中,以适应更广泛的作业
11.使用子查询
11.1子查询(subquery)
即嵌套在其他查询中是查询
11.2利用子查询进行过滤
SELECT order_num
FROM orderitems
WHERE prod_id='RGAN=01'
SELECT cust_id
FROM orders
WHERE order_num IN (SELECT order_num
FROM orderitems
WHERE prod_id='RGAN=01');
在SELECT中,子查询由内向外处理
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='RGAN=01'));
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
作为子查询的SELECT语句只能查询单个列。企图查询多个列将返回错误
11.3作为计算字段使用子查询
从customers表中检索每个顾客的订单数
SELECT cust_name,
cust_state,
(SELECT COUNT(*)
FROM orders
WHERE orders.cust_id=customers.cust_id) AS orders
--完全限制列名,告诉SQL比较orders表中的cust_id与customers表中的
cust_id相比较
FROM customers
ORDER BY cust_name;
1
2
3
4
5
6
7
8
9
对于这种问题有不止一种解决方案,JION也可以。
12.联结表
12.1联结
12.1.1关系表
举个例子,我们会将供应商信息与其供应的商品分开存放,因为每个供应商可能会有多种商品
1.统一供应商生存的每种商品,其供应信息是相同的,不必对这些信息重复录入
2.供应商信息发生变化,只需改动一次即可
我们的原则就是相同的数据出现多次并不是一件好事,关系型数据库正是基于此建立。
关系表的设计就是把数据分成多个表,一类数据一个表,不同 的表之间通过某些共同的值连接。
12.1.2为什么使用联结表
联结:用一条SELECT语句检索存储在多个表中的数据
12.2常见联结-指定联结的表及联结的方式
SELECT vend_id,prod_name,prod_price
FROM vendors,products
WHERE vendors.vend_id=products.vend_id;
1
2
3
12.2.1WHERE子句的重要性
WHERE子句作为过滤条件,只包含那些匹配给定条件(这里是联结条件)的行
若在联结中没有过滤条件,就会令两个表中的每一行都和另一个表中的每一行匹配,即为笛卡尔积,这是我们应该避免的。
12.2.2内联结
SELECT vend_id,prod_name,prod_price
FROM vendors INNER JOIN products
ON vendors.vend_id=products.vend_id;
1
2
3
12.2.3联结多个表
SELECT prod_name,vend_id,prod_name,prod_price,quantity
FROM orderitems,vendors ,products
WHERE vendors.vend_id=products.vend_id
AND orderitems.vend_id=products.prod_id
AND order_num=2007;
这个例子显示订单2007中的物品。
1
2
3
4
5
6
联结的表越多,性能下降的越厉害,不要联结不必要的表。一般DBMS对联结的表个数有限制。
返回11章中的例子
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='RGAN=01'));
用JOIN 改写
SELECT cust_name,cust_contact
FROM customers,orders,orderitems
WHERE customers.cust_id=orders.cust_id
AND orderitems.order_num=orders.order_num
AND prod_id='RGAN01';
1
2
3
4
5
6
7
8
9
10
11
12
13
14
13.创建高级联结
13.1对表使用别名
缩短语句;允许在一条SELECT语句总多次使用相同的表
对上个例子进行改写
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='RGAN=01';
1
2
3
4
5
6
13.2使用不同类型的联结
自联结self jion 自然联结natural join 外联结outer join
13.2.1自联结??
多次引用同一个表的子查询
SELECT C.*,O.order_num,O.order_date,OI.prod_id,OI.quantity,OI.item_price
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='RGAN=01';
1
2
3
4
5
13.2.2外联结
SELECT customers.cust_id,orders.order_num
FROM customers LEFT OUTER JOIN orders
ON customers.cust_id=orders.cust_id;
--左外联结,以左边的表为基准,右边的表多的舍去,少的为NULL
SELECT customers.cust_id,orders.order_num
FROM customers RIGHT OUTER JOIN orders
ON customers.cust_id=orders.cust_id;
--右外联结,以右边的表为基准
SELECT customers.cust_id,orders.order_num
FROM customers OUTER JOIN orders
ON customers.cust_id=orders.cust_id;
--全外联结
1
2
3
4
5
6
7
8
9
10
11
12
13
14
13.3使用带聚集函数的联结
聚集函数与联结一起使用
检索所有顾客及每个顾客所下的订单个数
SELECT customers.cust_id
COUNT(orders.order_num) AS num_ord
FROM custmers INNER JOIN orders
ON customers.cust_id=orders.cust_id
GROUP BY customers.cust_id;
1
2
3
4
5
14.组合查询
用UNION将多条SELECT语句组合成一个SELECT语句
14.1组合查询
适用情况
1.在一个查询中从不同的表返回结构
2.对一个表执行多个查询,按一个查询返回数据
任何具有多个WHERE子句的SELECT语句都可以作为一个组合查询
14.2创建组合查询
14.2.1使用UNION
SELECT cust_name,cust_contct,cust_email
FROM customers
WHERE cust_state IN('IL','IN','MI')
SELECT cust_name,cust_contct,cust_email
FROM customers
WHERE cust_name='Fun4ALL';
上面的例子用UNION联结
SELECT cust_name,cust_contct,cust_email
FROM customers
WHERE cust_state IN('IL','IN','MI')
UNION
SELECT cust_name,cust_contct,cust_email
FROM customers
WHERE cust_name='Fun4ALL';
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
14.2.2UNION的使用规则
1.UNION中的每个查询包含相同的列,表达式或者聚集函数,但是各个列不要求以相同的顺序写出
2.列数据类型必须兼容,类型不必完全相同,但必须是DBMS可以隐含转换的类型(例如,不同的数值类型和日期类型)
14.2.3包含或取消重复的行
SELECT cust_name,cust_contct,cust_email
FROM customers
WHERE cust_state IN('IL','IN','MI')
UNION
SELECT cust_name,cust_contct,cust_email
FROM customers
WHERE cust_name='Fun4ALL';
--去掉结果集中重复的行
SELECT cust_name,cust_contct,cust_email
FROM customers
WHERE cust_state IN('IL','IN','MI')
UNION ALL
SELECT cust_name,cust_contct,cust_email
FROM customers
WHERE cust_name='Fun4ALL';
--直接将两个结果集进行组合
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
14.2.4对组合查询结果排序
SELECT cust_name,cust_contct,cust_email
FROM customers
WHERE cust_state IN('IL','IN','MI')
UNION
SELECT cust_name,cust_contct,cust_email
FROM customers
WHERE cust_name='Fun4ALL';
ORDER BY cust_name,cust_contct,
--必须位于最后一条SELECT语句之后
1
2
3
4
5
6
7
8
9
15.插入数据INSERT
15.1数据插入
1.插入完整的行
2.插入一部分数据
3.插入某些查询结果
15.1.1插入完整/部分行
INSERT INTO customers(cust_id,
cust_name,
cust_adress,
cust_name,
cust_city,
cust_zip)
VALUES('',
'',
'',
'',
'',
'NULL')
1
2
3
4
5
6
7
8
9
10
11
12
–列名与插入的相应数据要对应,写入的列名可以不用对应原表中的列名顺序,如果对应的列名里没有要插入数据,写入NULL,
–也可以不用对一行的所有列都插入,插入哪些列,就写哪些列。
15.1.3插入检索的数据
INSERT INTO customers(cust_id,
cust_name,
cust_adress,
cust_name,
cust_city,
cust_zip)
SELECT cust_id,
cust_name,
cust_adress,
cust_name,
cust_city,
cust_zip
FROM custnew;
--从custnew表中读出数据并插入customers表中
1
2
3
4
5
6
7
8
9
10
11
12
13
14
##15.2从一个表复制到另一个表
SELECT *
INTO custcopy
FROM customers;
1
2
3
16.更新和删除表
16.1更新数据UPDATE
1.更新特定行
2.更新所有行
不要省略WHERE子句
更新客户1000005的电子邮件
UPDATE customers
SET cust_email='[email protected]'
WHERE cust_id='10000005';
1
2
3
更新多列
UPDATE customers
SET cust_email='[email protected]'
cust_contact='sam robert'
WHERE cust_id='10000005';
1
2
3
4
删除指定的列
UPDATE customers
SET cust_email=NULL
WHERE cust_id='10000005'
1
2
3
16.2删除数据DELETE
DELETE FROM customers
WHERE cust_id='10000005';
1
2
删除的是内容,而非表
16.3更新和删除的原则
1.一定要注意WHERE子句
2.保证每个表都有主键
3.在UPDATE和DELETE使用WHERE之前,一定要先用SELECT进行测试,保证过滤的是正确的记录,以防编写的WHERE的子句不正确
4.使用强制实施引用完整性的数据库,这样DBMS将不允许删除其数据与表相关联的行。
5.有的DBMS允许数据管理员施加约束,防止执行不带WHERE子句的UPDATE和DELETE.
17.创建和操作表
17.1
1.交互式界面创建
2.SQL语句创建
17.1.1表创建基础CREATE TABLE
1.新表的名字,在关键字CREATE TABLE 之后
2.表列的名字和定义,用逗号分隔
CREATE TABLE products
(
prod_id CHAR(10) NOT NULL,
prod_name CHAR(254) NOT NULL,
prod_price DECIMAL(8,2) NOT NULL,
prod_desc VARCAR(1000) NULL
);
1
2
3
4
5
6
7
指定表名时,若该表名已经存在,则需要先删除该表,而不是简单的覆盖
17.1.2使用NULL值
对于列的属性定义,NOT NULL即不允许该列出现空值,否则将会报错,列默认允许为NULL值。
17.1.3指定默认值
CREATE TABLE products
(
prod_id CHAR(10) NOT NULL,
prod_name CHAR(254) NOT NULL,
prod_price DECIMAL(8,2) NOT NULL DEFAULT 1,
prod_desc VARCAR(1000) NULL
);
--在插入的行如果不给出值,自动赋予默认值。
1
2
3
4
5
6
7
8
17.2更新表ALTER
ALTER对表的列及表名进行操作,UPDATE对表的行进行操作
ALTER TABLE vendors
ADD vend_phone CHAR(20);
ALTER TABLE vendors
DROP COLUMN vend_phone;
1
2
3
4
5
17.3删除表
DROP TABLE custcopy;
17.4重命名表
RENAME TABL cusucpoy TO custnew;
18.使用视图
18.1视图
视图是虚拟的表,与包含数据的表不一样,视图只包含使用时动态检索数据的查询。
这是12章的一个例子,查询订购了某种商品的顾客
SELECT cust_name,cust_contact
FROM customers,orders,orderitems
WHERE customers.cust_id=orders.cust_id
AND orderitems.order_num=orders.order_num
AND prod_id='RGAN01';
1
2
3
4
5
现在,假如我们可以把整个查询包装成一个名为productcustomers的虚拟表,就可以对上述查询进行简化
SELECT cust_name,cust_contact
FROM productcustomers
WHERE prod_id='RGAN01';
1
2
3
18.1.1为什么使用视图
1.重用SQL语句
2.简化复杂的SQL操作
3.使用表的一部分而不是整个表
4.保护数据,授予用户访问表的特定部分的权限,而非整个数据。
5.更改数据格式额表示。视图可返回与底层表的表示和格式不同的数据
视图是一种查看储存在别处的数据的一种设施,视图本身不含任何数据,只是从别处查询数据,在添加和更改这些表中的数据时,将会返回更改过的 数据
18.1.2视图的规则和限制
1.视图必须唯一命名
2.创建视图的数据没有限制
3.必须有足够的访问权限
4.视图可以嵌套,即可以利用从其他视图检索出的数据来构建视图
5.在视图查询中禁止使用ORDER BY 子句
6.有些DBMS要求对返回的列进行命名,如果列是计算字段,需要使用别名
7.视图不能索引,也不能有关联的触发器或默认值
8.有些DBMS把视图作为只读的查询,这表示可以从视图检索数据,但不能将数据写回底层表
18.2创建视图
CREATE VIEW 同样必须先删除相同的视图,再进行覆盖
18.2.1利用视图简化复杂的联结
对于上述例子,productcustomers怎么创建
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';
1
2
3
4
5
6
7
8
9
10
18.2.2用视图重新格式化检索出的数据
第7章例子
SELECT RIRIM(vend_name) + ‘(‘+RIRIM(vend_country)+’)’
AS vend_title
FROM vendors
ORDER BY vend_name;
1
2
3
4
现在,假设我们经常需要这个格式化的结果,不必每次在需要的时候都进行这种拼接,而是创建一个视图,使用它即可。把此语句转化为视图。
CREATE VIEW vendorlocations AS
SELECT RIRIM(vend_name) + ‘(‘+RIRIM(vend_country)+’)’
AS vend_title
FROM vendors;
SELECT * FROM vendorlocations;
--结果与第七章相同
1
2
3
4
5
6
7
18.2.3用视图过滤不想要的数据
CREATE VIEW customersemaillist AS
SELECT cust_id,cust_name,cust_email
FROM customers
WHERE cust_email IS NOT NULL;
SELECT *
FROM customersemaillist;
1
2
3
4
5
6
7
18.2.4使用视图与计算字段
第7章例子
SELECT prod_id,
quality,
item_price,
quantity*item_price AS expanded_price
FROM orderitems
WHERE order_num=20008;
利用视图重构
CREATE VIEW orderitemexpanded AS
SELECT order_num,
prod_id,
quality,
item_price,
quantity*item_price AS expanded_price
FROM orderitems;
SELECT *
FROM orderitemexpanded
WHERE order_num=20008;
---------------------
作者:xjh163
来源:CSDN
原文:https://blog.csdn.net/xjh163/article/details/79406578
版权声明:本文为博主原创文章,转载请附上博文链接!