SQL必知必会2


在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'));

作为子查询的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;

对于这种问题有不止一种解决方案,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;

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;

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中的物品。

联结的表越多,性能下降的越厉害,不要联结不必要的表。一般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';

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';

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';

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;
--全外联结

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;

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';

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';
--直接将两个结果集进行组合

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语句之后

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')

–列名与插入的相应数据要对应,写入的列名可以不用对应原表中的列名顺序,如果对应的列名里没有要插入数据,写入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表中

15.2从一个表复制到另一个表

 SELECT *
 INTO custcopy
 FROM customers;

16.更新和删除表

16.1更新数据UPDATE

1.更新特定行
2.更新所有行
不要省略WHERE子句
更新客户1000005的电子邮件

UPDATE customers
SET cust_email='kim@thetoystore.com'
WHERE cust_id='10000005';

更新多列

UPDATE customers
SET cust_email='kim@thetoystore.com'
        cust_contact='sam robert'
WHERE cust_id='10000005';

删除指定的列

UPDATE customers
SET cust_email=NULL
WHERE cust_id='10000005'

16.2删除数据DELETE

DELETE FROM customers
WHERE cust_id='10000005';

删除的是内容,而非表

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
);

指定表名时,若该表名已经存在,则需要先删除该表,而不是简单的覆盖

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
);
--在插入的行如果不给出值,自动赋予默认值。

17.2更新表ALTER

ALTER对表的列及表名进行操作,UPDATE对表的行进行操作

ALTER TABLE vendors
ADD vend_phone CHAR(20);

ALTER TABLE vendors
DROP COLUMN  vend_phone;			

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';

现在,假如我们可以把整个查询包装成一个名为productcustomers的虚拟表,就可以对上述查询进行简化

SELECT cust_name,cust_contact
FROM productcustomers
WHERE prod_id='RGAN01';

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';

18.2.2用视图重新格式化检索出的数据

第7章例子

SELECT RIRIM(vend_name) + ‘(‘+RIRIM(vend_country)+’)’
               AS  vend_title
FROM vendors
ORDER BY vend_name;

现在,假设我们经常需要这个格式化的结果,不必每次在需要的时候都进行这种拼接,而是创建一个视图,使用它即可。把此语句转化为视图。

CREATE VIEW vendorlocations AS
SELECT RIRIM(vend_name) + ‘(‘+RIRIM(vend_country)+’)’
               AS  vend_title
FROM vendors;

SELECT * FROM vendorlocations;
--结果与第七章相同

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;

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;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值