SQL必知必会学习笔记3

SQL必知必会学习笔记3

十三、创建高级联结

1.使用表别名

SELECT cust_name,cust_contact
FROM Customer AS C, Orders AS 0, OrderItems AS OI
WHERE C.cust_id = 0.cust_id
AND OI.order_num = 0.order_num
AND prod_id = 'RGAN01'

警告: Oracle中没有AS,直接指定Customer C。

2.使用不同类型的联结

  迄今为止,我们使用的知识内联结或等值联结的简单联结。现在来看三种其他联结:自联结(self-join)自然联结(natural join)外联结(outer join)

自联结

  举例,加入要给JimJones同一公司的所有顾客发送一封信件。这个查询首要找出Jim Jones工作的公司,然后找出该公司工作的顾客,下面是解决此问题的一种方法:

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

  尽量使用自联结,虽然最终结果是相同的,但许多DBMS处理联结远比处理子查询快的多。

自然联结(存疑)

  使用标准的联结(内联结)返回所有数据,相同的列甚至多次出现。自然联结排除多次出现,使每一列只返回一次。怎么完成这个工作?答案是,系统不完成这项工作,有你自己完成它。自然联结要求你只能选择那些唯一的列,一般同步对一个表使用通配符(SELECT *), 而对其他表的列使用明确的子集来完成,下面举例:

SELECT C.*, O.order_num, O.order_date, OI.prod_id, OI.quantity, OI.item_price
FROM Customers AS C, Orders AS 0, OrderItems AS OI
WHERE C.cust_id = O.cust_id
AND OI.order_num = O.order_num
AND prod_id = 'RGAN01';

外联结

  许多联结讲一个表中的行与另一个表中的行相关联,但有时候需要包含没有关联行的那些行。例如,可能需要使用联结完成以下工作:

  • 对于每个顾客下的订单进行计数,包括那些至今尚未下订单的顾客;
  • 列出所有产品以及订购数量,包括没有人订购的产品;
  • 计算平均销售规模,包括那些至今尚未下订单的顾客。

  上述例子中,联结包含了那些在相关表中没有关联的行。这种联结称为外联结。下面的SELECT语句给出了一个简单的内联结。它检索所有顾客及其订单:

SELECT Customers.cust_id,Order.order_num
FROM Customers INNER JOIN Orders
ON Customer.cust_id = Order.cust_id;

  外联结语法类似。要检索包括没有订单顾客在内的所有顾客,可如下进行:

SELECT Customers.cust_id,Order.order_num
FROM Customers LEFT OUTER JOIN Orders
ON Customer.cust_id = Order.cust_id;

  外联结还包含没有关联的行,使用OUTER JOIN语法时,必须使用RIGHT或LEFT关键字指定包含其所有行的表(RIGHT支出的是OUTER JOIN右边的表,而LEFT支出的是OUTER JOIN左边的表)。还有一种全外联结,左右两边都会包含所有行。

SELECT Customers.cust_id,Order.order_num
FROM  Orders FULL OUTER JOIN Customers
ON Customer.cust_id = Order.cust_id;

3.使用带聚集函数的联结

SELECT Customers.cust_id, COUNT(Order.order_num) AS num_ord
FROM Customers INNER JOIN Orders
ON Customer.cust_id = Order.cust_id; 
GROUP BY Customer.cust_id;

4.使用联结和联结条件

  联结及使用的要点:

  • 注意所有的联结类型。一般我们使用内联结,但使用外联结也有效。
  • 关于确切的联结语法,应该查看具体的文档,看相应的DBMS支持何种语法
  • 保证使用正确的联结条件,否则会返回不正确的数据。
  • 应该总是提供联结条件,否则 会得出笛卡尔积。
  • 在一个联结中可以包含多个表,甚至可以对每个联结采用不同联结类型。虽然这样做是合法的,一般也很有用,但应该在一起测试它们前分别测试每个联结。这会故障排除更为简单。

十四、组合查询

1.组合查询

  SQL也允许执行多个查询,并将结果作为一个查询结果集返回。这些组合查询通常称为并(union) 或复合查询(compound query)。主要有两种情况需要使用组合查询:

  • 在一个查询中从不同的表返回结构数据;
  • 对一个执行多个查询,按一个查询返回结果。
  • 组合查询和多个WHERE条件具有相同的功能。

2.创建组合查询

  使用UNION很简单,只需要给每条SELECT语句之间放上UNION。

  进行组合时要注意几条规则

  • UNION必须由两条或两条以上的SELECT语句组成,语句之间用关键字UNION分隔。
  • UNION中的每个查询必须包含相应的列、表达式或聚集函数。
  • 列数据类型必须兼容:类型不必完全相同,必须是DBMS可以隐含切换的类型。
  • UNION语句从查询结果中自动去除了重复的行。如果想返回所有的行,可以使用UNION ALL 而不是UNION。

对组合查询结果排序

  在用UNION组合查询时,只能使用一条ORDER BY子句,必须位于一条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'
ORDER BY cust_name, cust_contact;

十五、插入数据

1.数据插入

  INSERT用来进行将行插入到数据库。插入有集中方式:

  • 插入完整的行;
  • 插入行的一部分;
  • 插入某些查询的结果

插入完整的行

  使用基本的INSERT语法,他要求指定表明和插入到新行中的值。

INSERT INTO Customers
VALUES('1000000006',
       'Toy Land',
       '123 Any Street',
       'New York',
       'NY',
       '11111',
       'USA',
       NULL,
       NULL);

INTO关键字 跟在INSERT之后的INTO关键字是可选的。

  这种方式很简单,但是并不安全,应该尽量避免使用过。编写INSERT语句的更安全的方法入下:

INSERT INTO Customers(cust_id, cust_name, cust_address,
cust_state, cust_zip, cust_country, cust_contact, cust_email)
VALUES('1000000006',
       'Toy Land',
       '123 Any Street',
       'New York',
       'NY',
       '11111',
       'USA',
       NULL,
       NULL);

  可以只给部分列提供值,给其他列不提供值。其他列的值将被省略。省略的列必须满足以下。

  • 该列定义为允许NULL值(无值或空值)。
  • 在表定义中给出默认值。这表示如果不给出值,将使用默认值。

  插入检索出的数据,即INSERT SELECT。由一条INSERT语句和一条SELECT语句组成的。

INSERT INTO Customer(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选出来的行都会被INSERT插入。

2.从一个表复制到另一个表

  使用SELECT INTO将一个表的内容复制到一个全新的表。INSERT SELECT与SELECT INTO。他们之间的一个重要差别是前者导出数据,而后者导入数据。

SELECT *
INTO CustCopy
FROM Customers;
  • 任何SELECT选项和字句都可以使用,包括WHERE和GROUP BY;
  • 可以利用联结从多个表插入数据;
  • 不管从多少个表中检索数据,数据都只能插入一个表中。

十六、更新和删除数据

  介绍UPDATE和DELETE语句。

1.更新数据

  使用UPDATE的方式:

  • 更新表中的特定行
  • 更新表中的所有行
  • 不要省略WHERE语句,避免更新表中的所有行。

  基本的UPDATE语句由三部分组成:

  • 要更新的表
  • 列名和他们的新值;
  • 要确定更新哪些行的过滤条件。
UPDATE Customers
SET cust_email = ‘kim@thetoystore.com’
WHERE cust_id = '10000000005'

  要删除某个列的值,可以设置它为NULL。

UPDATE Customers
SET cust_email = NULL
WHERE cust_id = '10000000005';

2.删除数据

  两种DELETE的使用方式:

  • 从表中删除特定的行;
  • 从表中删除所有的行。
DELETE FROM Customer 
WHERE cust_id = '1000000006'

  如果从表中国删除所有的行,不要使用DELETE,可使用TRUNCATE TABLE语句,它完成相同的工作,而且速度更快。

3.更新和删除的指导原则

  • 除非确实打算更新和删除每一行,否则绝对不要使用不带WHERE子句的UPDATE或DELETE语句。
  • 保证每个表都有主键,尽可能像WHERE字句那样使用它。
  • UPDATE或DELETE语句使用WHRER字句前,应该先用SELECT 进行测试,保证过滤是正确的。
  • 使用强制实施引用完整性的数据,这样DBMS将不允许删除其数据与其他表相关联的行。
  • 有的DBMS允许数据库管理员施加约束,防止不带WHERE的UPDATE个DELETE语句。

十七、创建和操纵表

1.创建表

  创建表的两种方式:

  • 多数DBMS都具有交互式创建和管理数据库的工具;
  • 表可以直接用SQL语句操纵。
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值。

指定默认值

CREATE TABLE OrderItem 
(order_num INTEGER NOT NULL,
 order_item INTEGER NOT NULL,
 prod_id CHAR(10) NOT NULL,
 quantity INTEGER NOT NULL DEAFAULT 1,
 item_price DECIMAL(8,2) NOT NULL);

2.更新表

  使用ALTER TABLE时需要考虑的事

  • 理想情况下,不要在表中包含数据时对其进行更新。应该在表的设计过程中充分考虑未来可能的需求,便面今后对表的结构做大的改动
  • 所有DBMS都允许给现在的表增加列,不过对所新增的列的数据类型有所限制。
  • 许多DBMS不允许删除或更改表中的列。
  • 多数DBMS允许重命名表中的列。
  • 许多DBMS限制对已经填有数据的列进行更改,对未填有数据的列几乎没有限制。
# 增加一列
ALTER TABLE Vendors
ADD vend_phone CHAR(20);
# 删除一列
ALTER TABLE Vendors
DROP COLUMN vend_phone;

3.删除表

DROP TABLE CustCopy;

4.重命名表

  不同的DBMS使用的语句不相同,SQL Server用户使用sp_rename存储过程。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,772评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,458评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,610评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,640评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,657评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,590评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,962评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,631评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,870评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,611评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,704评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,386评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,969评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,944评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,179评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,742评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,440评论 2 342

推荐阅读更多精彩内容

  • 表 存储在表中的数据是同一种类型的数据或清单。 数据库中的表有为一个名字来标识自己。 表具有一些特性,这些特性定义...
    蛐蛐囍阅读 1,302评论 0 7
  • 数据库入门 数据库: 保存有组织的数据的容器(通常是一个文件或一组文件).数据库软件应该称为 DBMS(DataB...
    Mjericho阅读 491评论 0 0
  • 本书所用的表: 第一章:了解SQL 数据库:保存有组织的数据的容器(通常是一个文件或一组文件)。 数据库软件:DB...
    狼牙战士阅读 896评论 0 1
  • “爆竹声中一岁除,春风送暖入屠苏。千门万户瞳瞳日,总把新桃换旧符”。这首王安石的《元日》,是描写过年的最著名的诗句...
    小雨康桥阅读 220评论 0 1
  • “”咚、咚、咚"门响了,透过猫眼我看见了李阿姨,她又来找我帮忙了。说实话我挺害怕她来找我,因为她每次跟我说的都是家...
    雪山飞狐儿阅读 430评论 0 1