基于Mysql5.6 学习此书
Lesson11 子查询
1. 利用子查询进行过滤
例如:查找购买物品数量>=10的客户
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 quantity >= 10) ); ----------- mysql> 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 quantity >= 10)); +----------------+--------------+ | cust_name | cust_contact | +----------------+--------------+ | Coyote Inc. | Y Lee | | Yosemite Place | Y Sam | | E Fudd | E Fudd | +----------------+--------------+ 3 rows in set (0.04 sec)
使用子查询并不总是执行复杂 SELECT 操作的最有效方法,
下面是使用联结的相同查询:
SELECT c.cust_name, c.cust_contact FROM customers c, orders o, orderitems oi WHERE c.cust_id=o.cust_id and oi.order_num=o.order_num and oi.quantity >= 10; +----------------+--------------+ | cust_name | cust_contact | +----------------+--------------+ | Coyote Inc. | Y Lee | | Yosemite Place | Y Sam | | E Fudd | E Fudd | +----------------+--------------+ 3 rows in set (0.02 sec)
或
SELECT c.cust_name, c.cust_contact FROM customers c INNER JOIN orders o INNER JOIN orderitems oi ON c.cust_id=o.cust_id and oi.order_num=o.order_num and oi.quantity >= 10; +----------------+--------------+ | cust_name | cust_contact | +----------------+--------------+ | Coyote Inc. | Y Lee | | Yosemite Place | Y Sam | | E Fudd | E Fudd | +----------------+--------------+ 3 rows in set (0.00 sec)
2. 作为计算字段使用子查询
假如需要显示 Customers 表中
每个顾客的订单总数。订单与相应的顾客 ID存储在 Orders 表中。
执行这个操作,要遵循下面的步骤:
(1) 从 Customers 表中检索顾客列表;
(2) 对于检索出的每个顾客,统计其在 Orders 表中的订单数目。
使用子查询:
select cust_name, cust_state, (select count(*) from orders where orders.cust_id=customers.cust_id) as orders from customers order by cust_name; +----------------+------------+--------+ | cust_name | cust_state | orders | +----------------+------------+--------+ | Coyote Inc. | MI | 2 | | E Fudd | IL | 1 | | Mouse House | OH | 0 | | Wascals | IN | 1 | | Yosemite Place | AZ | 1 | +----------------+------------+--------+ 5 rows in set (0.27 sec)
提示:不止一种解决方案
正如这一课前面所述,虽然这里给出的样例代码运行良好,但它并不
是解决这种数据检索的最有效方法。在后面两课学习 JOIN 时,我们
还会遇到这个例子。
使用联结JOIN:
select c.cust_name, c.cust_state, count(o.order_num) orders from customers c left join orders o on c.cust_id=o.cust_id group by c.cust_id order by c.cust_name; +----------------+------------+--------+ | cust_name | cust_state | orders | +----------------+------------+--------+ | Coyote Inc. | MI | 2 | | E Fudd | IL | 1 | | Mouse House | OH | 0 | | Wascals | IN | 1 | | Yosemite Place | AZ | 1 | +----------------+------------+--------+ 5 rows in set (0.00 sec)
总结
子查询常用于 WHERE 子句的 IN 操作符中, 以及用来填充计算列。
Lesson12 联接表
SQL最强大的功能之一就是能在数据查询的执行中联结(join)表。
为什么使用联结?
如前所述,将数据分解为多个表能更有效地存储,更方便地处理,并且可伸缩性更好。但这些好处是有代价的。
如果数据存储在多个表中,怎样用一条 SELECT 语句就检索出数据呢?
答案是使用联结。简单说,联结是一种机制,用来在一条 SELECT 语句中关联表,因此称为联结。使用特殊的语法,可以联结多个表返回一组输出,联结在运行时关联表中正确的行。
联结
笛卡儿积(cartesian product)
由没有联结条件的表关系返回的结果为笛卡儿积。检索出的行的数目将是第一个表中的行数乘以第二个表中的行数。
没有 WHERE 子句,第一个表中的每一行将与第二个表中的每一行配对,而不管它们逻辑上是否能配在一起。
有时,返回笛卡儿积的联结,也称叉联结(cross join)
联结就是从两个表的笛卡尔积运算结果中选取某些行和列。换句话说,连接就是有条件的笛卡尔积。
SELECT vend_name, prod_name, prod_price FROM Vendors, Products ; +----------------+----------------+------------+ | vend_name | prod_name | prod_price | +----------------+----------------+------------+ | Anvils R Us | .5 ton anvil | 5.99 | | LT Supplies | .5 ton anvil | 5.99 | | ACME | .5 ton anvil | 5.99 | | Furball Inc. | .5 ton anvil | 5.99 | | Jet Set | .5 ton anvil | 5.99 | | Jouets Et Ours | .5 ton anvil | 5.99 | | Anvils R Us | 1 ton anvil | 9.99 | | LT Supplies | 1 ton anvil | 9.99 | | ACME | 1 ton anvil | 9.99 | | Furball Inc. | 1 ton anvil | 9.99 | | Jet Set | 1 ton anvil | 9.99 | | Jouets Et Ours | 1 ton anvil | 9.99 | | Anvils R Us | 2 ton anvil | 14.99 | | LT Supplies | 2 ton anvil | 14.99 | | ACME | 2 ton anvil | 14.99 | | Furball Inc. | 2 ton anvil | 14.99 | | Jet Set | 2 ton anvil | 14.99 | | Jouets Et Ours | 2 ton anvil | 14.99 | | Anvils R Us | Detonator | 13.00 | | LT Supplies | Detonator | 13.00 | ......
相应的笛卡儿积不是我们想要的。这里返回的数据用每个供应商匹配了每个产品,包括了供应商不正确的产品(即使
供应商根本就没有产品) 。所以,不要忘了 WHERE 子句。
SELECT vend_name, prod_name, prod_price FROM Vendors, Products WHERE Vendors.vend_id = Products.vend_id; +-------------+----------------+------------+ | vend_name | prod_name | prod_price | +-------------+----------------+------------+ | Anvils R Us | .5 ton anvil | 5.99 | | Anvils R Us | 1 ton anvil | 9.99 | | Anvils R Us | 2 ton anvil | 14.99 | | LT Supplies | Fuses | 3.42 | | LT Supplies | Oil can | 8.99 | | ACME | Detonator | 13.00 | | ACME | Bird seed | 10.00 | | ACME | Carrots | 2.50 | | ACME | Safe | 50.00 | | ACME | Sling | 4.49 | | ACME | TNT (1 stick) | 2.50 | | ACME | TNT (5 sticks) | 10.00 | | Jet Set | JetPack 1000 | 35.00 | | Jet Set | JetPack 2000 | 55.00 | +-------------+----------------+------------+ 14 rows in set (0.00 sec)
多张表联结
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; +----------------+-----------+------------+----------+ | prod_name | vend_name | prod_price | quantity | +----------------+-----------+------------+----------+ | TNT (5 sticks) | ACME | 10.00 | 100 | +----------------+-----------+------------+----------+ 1 row in set (0.18 sec)
应该注意,不要联结不必要的表。联结的表越多,性能下降越厉害。
内联结(INNER JOIN)
SELECT vend_name, prod_name, prod_price FROM Vendors, Products WHERE Vendors.vend_id = Products.vend_id;
之前使用的这种是简单的等值语法。上面的又可以写成 inner join,ANSI SQL 规范首选 INNER JOIN 语法,这是标准格式。但简单语法简单也很常用。
SELECT vend_name, prod_name, prod_price FROM Vendors INNER JOIN Products ON Vendors.vend_id = Products.vend_id;
也可以用WHERE : SELECT vend_name, prod_name, prod_price FROM Vendors INNER JOIN Products WHERE Vendors.vend_id = Products.vend_id;
区别:where后面增加的条件是对临时表生成后,进行过滤的。而on条件是在生成临时表时使用的条件。
这句不加ON条件,也是笛卡尔积。
注意:left / right join 后不能不加on条件,否则报错。可以这么写 select * from stu1 left join stu2 on 1=1;这样也是笛卡尔积。
迄今为止,我们使用的只是内联结或等值联结的简单联结。现在来看三种
其他联结: 自联结 (self-join) 、 自然联结 (natural join) 和外联结 (outer join) 。
自联结 (self-join)
即自己与自己联结
假如要给与 Jim Jones同一公司的所有顾客发送一封信件。这个查询要求,首先找出 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 语句做了一个简单检索,返回 Jim Jones工作公司的 cust_name 。该名字用于外部查询的 WHERE 子句中,以检索出为该公司工作的所有雇员。
SELECT c1.cust_id, c1.cust_name, c1.cust_contact FROM Customers c1, Customers c2 WHERE c1.cust_name = c2.cust_name AND c2.cust_contact = 'Jim Jones';
此查询中需要的两个表实际上是相同的表,因此 Customers 表在 FROM 子句中出现了两次。这就是自联结。
提示:用自联结而不用子查询,一般自联结比子查询速度快。
自然联结 (natural join)
无论何时对表进行联结,应该至少有一列不止出现在一个表中(被联结的列) 。标准的联结(前一课中介绍的内联结)返回所有数据,相同的列甚至多次出现。自然联结排除多次出现,使每一列只返回一次。
怎样完成这项工作呢?答案是,系统不完成这项工作,由你自己完成它。
自然联结要求你只能选择那些唯一的列,一般通过对一个表使用通配符
( SELECT * ) ,而对其他表的列使用明确的子集来完成。下面举一个例子:
SELECT C.*, O.order_num, O.order_date, OI.prod_id, OI.quantity, OI.item_price FROM Customers C, Orders O, OrderItems OI WHERE C.cust_id = O.cust_id AND OI.order_num = O.order_num AND prod_id = 'RGAN01';
外联结 (outer join)
许多联结将一个表中的行与另一个表中的行相关联,但有时候需要包含没有关联行的那些行。例如,可能需要使用联结完成以下工作:
- 对每个顾客下的订单进行计数,包括那些至今尚未下订单的顾客;
- 列出所有产品以及订购数量,包括没有人订购的产品;
- 计算平均销售规模,包括那些至今尚未下订单的顾客。
在上述例子中,联结包含了那些在相关表中没有关联行的行。这种联结称为外联结。
包括:左联结(LEFT OUTER JOIN 或 LEFT JOIN),右联结(RIGHT OUTER JOIN 或 RIGHT JOIN)
例如:
SELECT Customers.cust_id, Orders.order_num FROM Customers LEFT OUTER JOIN Orders ON Customers.cust_id = Orders.cust_id; +---------+-----------+ | cust_id | order_num | +---------+-----------+ | 10001 | 20005 | | 10001 | 20009 | | 10002 | NULL | | 10003 | 20006 | | 10004 | 20007 | | 10005 | 20008 | +---------+-----------+ 6 rows in set (0.00 sec)
- INNER JOIN(内连接,或等值连接):获取两个表中字段匹配关系的记录。
- LEFT JOIN(左连接):获取左表所有记录,即使右表没有对应匹配的记录。
- RIGHT JOIN(右连接): 与 LEFT JOIN 相反,用于获取右表所有记录,即使左表没有对应匹配的记录
右联结
SELECT Customers.cust_id, Orders.order_num FROM Customers RIGHT OUTER JOIN Orders ON Customers.cust_id = Orders.cust_id; +---------+-----------+ | cust_id | order_num | +---------+-----------+ | 10001 | 20005 | | 10001 | 20009 | | 10003 | 20006 | | 10004 | 20007 | | 10005 | 20008 | +---------+-----------+ 5 rows in set (0.00 sec)
还存在另一种外联结,就是全外联结(full outer join) ,它检索两个表中的所有行并关联那些可以关联的行。与左外联结或右外联结包含一个表不关联的行不同,全外联结包含两个表的不关联的行。全外联结的语法如下:
SELECT Customers.cust_id, Orders.order_num FROM Orders FULL OUTER JOIN Customers ON Orders.cust_id = Customers.cust_id; -- 但是 mysql 报错了 mysql> SELECT Customers.cust_id, Orders.order_num FROM Orders FULL OUTER JOIN Customers ON Orders.cust_id = Customers.cust_id; ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'OUTER JOIN Customers ON Orders.cust_id = Customers.cust_id' at line 1 mysql>
注意: FULL OUTER JOIN 的支持
Access、MariaDB、MySQL、Open Office Base和 SQLite不支持 FULL OUTER JOIN 语法。
使用带聚集函数的联结
看个例子,要检索所有顾客及每个顾客所下的订单数,下面的代码使用 COUNT() 函数完成此工作:
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; +---------+---------+ | cust_id | num_ord | +---------+---------+ | 10001 | 2 | | 10003 | 1 | | 10004 | 1 | | 10005 | 1 | +---------+---------+ 4 rows in set (0.04 sec)
SELECT Customers.cust_id, COUNT(Orders.order_num) AS num_ord FROM Customers LEFT OUTER JOIN Orders ON Customers.cust_id = Orders.cust_id GROUP BY Customers.cust_id; +---------+---------+ | cust_id | num_ord | +---------+---------+ | 10001 | 2 | | 10002 | 0 | | 10003 | 1 | | 10004 | 1 | | 10005 | 1 | +---------+---------+ 5 rows in set (0.00 sec)
有必要汇总一下联结及其使用的要点。
- 注意所使用的联结类型。 一般我们使用内联结, 但使用外联结也有效。
- 关于确切的联结语法,应该查看具体的文档,看相应的 DBMS支持何种语法(大多数 DBMS使用这两课中描述的某种语法) 。
- 保证使用正确的联结条件(不管采用哪种语法) ,否则会返回不正确的数据。
- 应该总是提供联结条件,否则会得出笛卡儿积。
- 在一个联结中可以包含多个表,甚至可以对每个联结采用不同的联结类型。虽然这样做是合法的,一般也很有用,但应该在一起测试它们前分别测试每个联结。这会使故障排除更为简单。
Lesson14 组合查询
本课讲述如何利用 UNION 操作符将多条 SELECT 语句组合成一个结果集。
多数 SQL查询只包含从一个或多个表中返回数据的单条 SELECT 语句。但是,SQL也允许执行多个查询(多条 SELECT 语句) ,并将结果作为一个查询结果集返回。这些组合查询通常称为并(union)或复合查询(compound query) 。
主要有两种情况需要使用组合查询:
- 在一个查询中从不同的表返回结构数据;
- 对一个表执行多个查询,按一个查询返回数据。
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 从查询结果集中自动去除了重复的行;换句话说,它的行为与一条 SELECT 语句中使用多个 WHERE 子句条件一样。
这是 UNION 的默认行为,如果愿意也可以改变它。事实上,如果想返回所有的匹配行,可使用 UNION ALL 而不是 UNION 。
SELECT 语句的输出用 ORDER BY 子句排序。在用 UNION 组合查询时,只能使用一条 ORDER BY 子句,它必须位于最后一条 SELECT 语句之后。用它来排序所有 SELECT 语句返回的所有结果。
Lesson18 使用视图
视图是虚拟的表。与包含数据的表不一样,视图只包含使用时动态检索数据的查询。
为什么使用视图
下面是视图的一些常见应用。
- 重用 SQL语句
- 简化复杂的 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;
删除视图: DROP VIEW viewname; 。覆盖(或更新)视图,必须先删除它,然后再重新创建。
这条语句创建一个名为 ProductCustomers 的视图,它联结三个表,返回已订购了任意产品的所有顾客的列表。如果执行 SELECT * FROM ProductCustomers ,将列出订购了任意产品的顾客。
检索订购了产品 TNT2 的顾客,可如下进行:
SELECT cust_name, cust_contact FROM ProductCustomers WHERE prod_id = 'TNT2';
简化了sql,重用了sql。
又例如,有一个sql
SELECT RTRIM(vend_name) + ' (' + RTRIM(vend_country) + ')' AS vend_title FROM Vendors ORDER BY vend_name; # 或者 SELECT RTRIM(vend_name) || ' (' || RTRIM(vend_country) || ')' AS vend_title FROM Vendors ORDER BY vend_name; #Mysql 使用 CONCAT 连接字符串 SELECT CONCAT(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 VendorLocations AS SELECT RTRIM(vend_name) || ' (' || RTRIM(vend_country) || ')' AS vend_title FROM Vendors; #Mysql 使用 CONCAT 连接字符串 CREATE VIEW VendorLocations AS SELECT CONCAT(RTRIM(vend_name) ,' (', RTRIM(vend_country),')') AS vend_title FROM Vendors;
用视图过滤不想要的数据
视图对于应用普通的 WHERE 子句也很有用。例如,可以定义CustomerEMailList 视图,过滤没有电子邮件地址的顾客。为此,可使用下面的语句:
CREATE VIEW CustomerEMailList AS SELECT cust_id, cust_name, cust_email FROM Customers WHERE cust_email IS NOT NULL;
使用视图与计算字段
在简化计算字段的使用上,视图也特别有用。下面是第 7 课中介绍的一条 SELECT 语句,它检索某个订单中的物品,计算每种物品的总价格:
SELECT prod_id, quantity, item_price, quantity*item_price AS expanded_price FROM OrderItems WHERE order_num = 20008;
要将其转换为一个视图,如下进行:
CREATE VIEW OrderItemsExpanded AS SELECT order_num, prod_id, quantity, item_price, quantity*item_price AS expanded_price FROM OrderItems
检索订单 20008 的详细内容(上面的输出) ,如下进行
SELECT * FROM OrderItemsExpanded WHERE order_num = 20008;
小结
视图为虚拟的表。它们包含的不是数据而是根据需要检索数据的查询。
视图提供了一种封装 SELECT 语句的层次,可用来简化数据处理,重新格式化或保护基础数据。
Lesson19 使用存储过程
迄今为止,我们使用的大多数 SQL语句都是针对一个或多个表的单条语句。并非所有操作都这么简单,经常会有一些复杂的操作需要多条语句才能完成,这就需要存储过程了。
存储过程
简单来说,存储过程就是为以后使用而保存的一条或多条 SQL语句。 可将其视为批处理文件, 虽然它们的作用不仅限于批处理。
使用存储过程有三个主要的好处,即简单、安全、高性能。显然,它们都很重要。不过,不同 DBMS中的存储过程语法有所不同。事实上,编写真正的可移植存储过程几乎是不可能的。不过,存储过程的自我调用(名字以及数据如何传递) 可以相对保持可移植。 因此, 如果需要移植到别的DBMS,至少客户端应用代码不需要变动。
创建存储过程
我们来看一个简单的存储过程例子,它对邮件发送清单中具有邮件地址的顾客进行计数。
下面是该过程的 Oracle版本:
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;
这个存储过程有一个名为 ListCount 的参数。 此参数从存储过程返回一个值而不是传递一个值给存储过程。关键字 OUT 用来指示这种行为。
Oracle支持 IN (传递值给存储过程) 、 OUT (从存储过程返回值, 如这里) 、INOUT (既传递值给存储过程也从存储过程传回值)类型的参数。存储过程的代码括在 BEGIN 和 END 语句中,这里执行一条简单的 SELECT 语句,它检索具有邮件地址的顾客。然后用检索出的行数设置 ListCount(要传递的输出参数) 。
调用 Oracle例子可以像下面这样:
var ReturnValue NUMBER EXEC MailingListCount(:ReturnValue); SELECT ReturnValue;
下面是该过程的 SQL Server 版本。
CREATE PROCEDURE MailingListCount AS DECLARE @cnt INTEGER SELECT @cnt = COUNT(*) FROM Customers WHERE NOT cust_email IS NULL; RETURN @cnt;
此存储过程没有参数。调用程序检索 SQL Server的返回代码提供的值。其中用 DECLARE 语句声明了一个名为 @cnt 的局部变量 (SQL Server中所有局部变量名都以 @ 起头) ;然后在 SELECT 语句中使用这个变量,让它包含 COUNT() 函数返回的值;最后,用 RETURN @cnt 语句将计数返回给调用程序。
调用 SQL Server例子可以像下面这样:
DECLARE @ReturnValue INT EXECUTE @ReturnValue=MailingListCount; SELECT @ReturnValue;
Lesson20 事务
Mysql中查看自动提交状态:
select @@autocommit;
默认是1. 可以设置 set autocommit = 0; set autocommit = 1;
若是1,表示自动提交。每一个操作,都是一个事务,自动提交。若要开启事务,显示的写 start transaction; 然后写操作语句,最后写 commit 或 rollback。
若是0,表示不自动提交。每个操作,都有写个 commit; 才能提交,若没写,系统默认rollback。
Mysql查看隔离级别:有四种,serializable(序列化)、repeatable read (可重复读)、read committed(提交后读)、read uncommitted(未提交读)
select @@tx_isolation;
事务:一组业务操作ABCD,要么全部成功,要么全部不成功。
特性:ACID
- 原子性:整体
- 一致性:完成
- 隔离性:并发
- 持久性:结果
隔离问题:
- 脏读:一个事务读到另一个事务没有提交的数据
- 不可重复读:一个事务读到另一个事务已提交的数据(update)
- 虚读(幻读):一个事务读到另一个事务已提交的数据(insert)
隔离级别:
- read uncommitted:读未提交。存在3个问题
- read committed:读已提交。解决脏读,存在2个问题
- repeatable read:可重复读。解决:脏读、不可重复读,存在1个问题。
- serializable :串行化。都解决,单事务。(速度慢)
附录:
语法
ALTER TABLE 用来更新已存在表的结构。 ALTER TABLE tablename ( ADD|DROP column datatype [NULL|NOT NULL] [CONSTRAINTS], ADD|DROP column datatype [NULL|NOT NULL] [CONSTRAINTS], ... ); CREATE INDEX 用于在一个或多个列上创建索引 CREATE INDEX indexname ON tablename (column, ...); CREATE PROCEDURE 用于创建存储过程。 CREATE PROCEDURE procedurename [parameters] [options] AS SQL statement; CREATE TABLE 用于创建新数据库表。 CREATE TABLE tablename ( column datatype [NULL|NOT NULL] [CONSTRAINTS], column datatype [NULL|NOT NULL] [CONSTRAINTS], ... ); CREATE VIEW 用来创建一个或多个表上的新视图。 CREATE VIEW viewname AS SELECT columns, ... FROM tables, ... [WHERE ...] [GROUP BY ...] [HAVING ...]; DELETE 从表中删除一行或多行。 DELETE FROM tablename [WHERE ...]; DROP 永久地删除数据库对象 (表、 视图、 索引等) 。 DROP INDEX|PROCEDURE|TABLE|VIEW indexname|procedurename|tablename|viewname; INSERT 为表添加一行。 INSERT INTO tablename [(columns, ...)] VALUES(values, ...); INSERT SELECT 将 SELECT 的结果插入到一个表 INSERT INTO tablename [(columns, ...)] SELECT columns, ... FROM tablename, ... [WHERE ...]; SELECT 用于从一个或多个表(视图)中检索数据。 SELECT columnname, ... FROM tablename, ... [WHERE ...] [UNION ...] [GROUP BY ...] [HAVING ...] [ORDER BY ...]; UPDATE 更新表中的一行或多行。 UPDATE tablename SET columname = value, ... [WHERE ...];
----------