在使用多个联结时应该分别测试每个联结,这样使故障排除更简单。
联结
SELECT vend_name, prod_name, prod_price
FROM vendors, products
WHERE vendors.vend_id = products.vend_id
ORDER BY vend_name, prod_name;
WHERE子句指示mysql匹配两个表中的vend_id
也可以使用另外一种语法达到完全相同的目的:
SELECT vend_name, prod_name, prod_price
FROM vendors INNER JOIN products
ON vendors.vend_id = products.vend_id;
首选使用INNER JOIN语法。虽然使用WHERE子句定义联结比较简单,但使用明确的联结语法能够确保不会忘记联结条件,有时候这样做也会影响性能。
可以联结多个表:
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 = 2005;
联结的表越多,性能下降越厉害。
自联结
使用子查询查询生产物品DTNTR的供应商所生产的所有物品:
SELECT prod_id, prod_name
FROM products
WHERE vend_id = (SELECT vend_id FROM products WHERE prod_id = 'DTNTR')
使用自联结的相同查询:
SELECT p1.prod_id, p1.prod_name
FROM products AS p1, products AS p2
WHERE p1.vend_id = p2.vend_id
AND p2.prod_id = 'DTNTR';
products表在FROM子句中出现了两次,这是完全合法的。但是为了避免二义性,需要使用表别名。
自联结通常用来替代从相同表中检索数据时使用的子查询语句。
内联结,外联结
INNER JOIN只有两个表中都有匹配的数据时才返回对应的行;
LEFT OUTER JOIN永远返回左表数据,不论右表中是否有匹配行;
RIGHT OUTER JOIN反之;
FULL OUTER JOIN两表数据都会被返回;
CROSS JOIN返回笛卡尔积;
带聚集函数的联结
对每个客户的订单计数:
SELECT customers.cust_name
customers.cust_id
COUNT(orders.order_num) AS num_order
FROM customer LEFT OUTER JOIN orders
ON customers.cust_id = orders.cust_id
GROUP BY customers.cust_id;
组合查询
UNION可以将多个SELECT的结果组合成单个结果集。
以下两个查询是等价的:
SELECT vend_id, prod_id, prod_price
FROM products
WHERE prod_price <= 5
OR vend_id IN(1001, 1002);
SELECT vend_id, prod_id, prod_price
FROM products
WHERE prod_price <= 5
UNION
SELECT vend_id, prod_id, prod_price
FROM products
WHERE vend_id IN (1001, 1002);
UNION中的每个查询必须包含相同的列、表达式或聚集函数(次序可以不同);
列数据类型必须兼容:类型不必完全相同,但必须是DBMS可以隐式转换的类型;
UNION默认取消重复的行,如果需要返回所有重复的行可以使用UNION ALL;
使用UNION时ORDER BY必须位于最后一条SELECT之后,只能使用一条ORDER BY子句,它将被用来排序所有SELECT返回的所有结果;
UNION组合查询可以用于不同的表。
插入、更新、删除数据
使用明确给出列的列表的INSERT语句,能使SQL代码在表结构发生变化时仍能继续发挥作用;
如果数据检索是最重要的,可以在有必要时使用LOW_PRIORITY指示Mysql降低INSERT语句的优先级;(同样适用于UPDATE与DELETE语句)
可以使用一条INSERT语句插入多个行,比使用多条INSERT语句快:
INSERT INFO table(col1, col2) VALUES(v11, v12), (v21, v22);
INSERT SELECT(不要求列名匹配,事实上对应的是列的位置):
INSERT customers(cust_id, cust_contact, ...)
SELECT cust_id, cust_contact, ... FROM custnew;
使用UPDATE与DELETE时一定要注意WHERE子句,因为稍不注意就会更新表中的所有行;
UPDATE更新多个列的语法:
UPDATE customers
SET col1 = v1,
col2 = v2
WHERE cust_id = 10005;
如果用UPDATE更新多行时,如果其中的一行出现了错误,则整个UPDATE操作会被取消。如果即使发生错误也要继续更新,可以使用UPDATE IGNORE tablename ......
如果需要从表中删除所有行,可以使用TRUNCATE TABLE语句(实际上是删除原来的表并重新创建一个表);
除非确实打算更新或删除每一行,否则绝对不要使用不带WHERE子句的UPDATE与DELETE语句;
在对UPDATE或DELETE使用WHERE子句之前,应该先用SELECT进行测试,以确保过滤的是正确的记录;