#登录mysql mysql -u root -p #root 替换成你自己的用户名 #指定ip mysql -h localhost -u root -p #适用远程登陆mysql
配置远程连接
1 2 3 4 5 6 7
use mysql; select host,user from user; #这时候发现root用户的host作用域为localhost #将host修改为%,允许所有连接 update user set host='%' where user='root'; #热更新(flush privileges 命令本质上的作用是将当前user和privilige表中的用户信息/权限设置从mysql库 (MySQL数据库的内置库)中提取到内存里。 MySQL用户数据和权限有修改后,希望在"不重启MySQL服务"的情况下直接生效,那么就需要执行这个命令) flush privileges;
常用命令
use
1
USE mysql; #选择数据库
show
1 2 3 4 5 6 7
SHOW DATABASES; #显示可用的数据库列表 SHOW TABLES; #显示一个数据库内可用的表的列表 SHOW COLUMNS FROM user; #显示表列,表名(user)为必须项 DESCRIBE user; #是SHOW COLUMNS FROM user;的一种快捷方式
SHOW ERRORS; #显示服务器错误信息 SHOW WARNINGS; #显示服务器警告信息
更多命令,可输入’HELP SHOW’查看。
SELECT
1. SELECT
从一个或多个表中检索信息。至少要给出两条信息:
想选择什么
从哪里检索
示例:检索mysql的user列
1 2 3 4 5 6 7 8
USE school; #基本查询 #检索单个列 SELECT prod_name FROM products; #检索单个列 SELECT prod_id, prod_name, prod_price FROM products; #检索所有列 SELECT * FROM products;
2. 限制查询结果
1 2 3 4 5 6 7 8 9 10 11 12 13
#返回不同的行 DISTINCT #'DISTINCT'只返回不同的vend_id的行 #'DISTINCT'应用于所有而不仅是前置他的列 SELECT DISTINCT vend_id FROM products; #限制结果 LIMIT #参数5:不多于5行 SELECT prod_name FROM products LIMIT 5; #参数5,5:从第5开始,不多于5行 SELECT prod_name FROM products LIMIT 5, 5; #由于容易弄混参数,所以从MySQL 5 开始支持另一种替代的语法,如:从行3开始取4行 SELECT prod_name FROM products LIMIT 4 OFFSET 3; #使用完全限定的表名 SELECT products.prod_name FROM products;
#单个列,降序排序 SELECT prod_name FROM products ORDER BY prod_name DESC; #多列降序排序,优先级从前往后 SELECT prod_id, prod_price, prod_name FROM products ORDER BY prod_price DESC, prod_name DESC; #price降序, name升序 SELECT prod_id, prod_price, prod_name FROM products ORDER BY prod_price DESC, prod_name; #最贵的prod_name SELECT prod_name FROM products ORDER BY prod_price DESC LIMIT 1;
#price = 2.50 SELECT prod_name, prod_price FROM products WHERE prod_price = 2.50; #name = 'fuses', MYSQL在执行匹配时默认不区分大小写 SELECT prod_name, prod_price FROM products WHERE prod_name = 'fuses'; #price <= 10,小于等于 SELECT prod_name, prod_price FROM products WHERE prod_price <= 10; #vend_id <> 1003,不匹配检查 SELECT vend_id, prod_name FROM products WHERE vend_id <> 1003; #vend_id != 1003,不匹配检查 SELECT vend_id, prod_name FROM products WHERE vend_id != 1003; #prod_price BETWEEN 5 AND 10 SELECT prod_name, prod_price FROM products WHERE prod_price BETWEEN 5 AND 10; #cust_email is NULL SELECT cust_email, cust_id FROM customers WHERE cust_email is NULL;
在同时使用将ORDER BY和WHERE字句时,ORDER BY需位于WHERE后。
MYSQL在执行匹配时默认不区分大小写
值与串类型的列进行比较,值需要限定引号
BETWEEN字句需指定两个值,一个开始,一个结束值
组合WHERE字句:
1 2 3 4 5 6 7 8 9 10 11 12
#AND关键字:逻辑与 SELECT prod_id, prod_name, prod_price FROM products WHERE vend_id = 1003 AND prod_price <= 10;
#OR关键字:逻辑或 SELECT vend_id, prod_name FROM products WHERE vend_id = 1002 OR vend_id =1003;
#IN关键字:在这些值里 SELECT prod_name, vend_id FROM products WHERE vend_id IN (1002, 1003);
#NOT关键字:否定紧跟在后面的条件 SELECT prod_name, vend_id FROM products WHERE vend_id NOT IN (1002, 1003);
IN和OR操作符功能等价,但IN操作符具有如下优点:
语法更清楚更直观
计算的次序更容易管理(使用的操作符更少)
效率一般更快
IN最大的优点是可以包含其他SELECT语句
1 2
#price >= 10 且由1002或1003造的产品 SELECT prod_id, prod_name, prod_price FROM products WHERE (vend_id = 1002 OR vend_id = 1003) AND prod_price >= 10;
#%:百分号通配符,表示任意字符出现任意次。 #例:查找所有jet开头的产品 SELECT prod_id, prod_name FROM products WHERE prod_name LIKE 'jet%'; #例:匹配任何文本含anvil的值 SELECT prod_id, prod_name FROM products WHERE prod_name LIKE '%anvil%'; #例:%在中间 SELECT prod_id, prod_name FROM products WHERE prod_name LIKE 's%e';
7. 正则表达式
7.1 REGEXP关键字
1 2 3 4 5 6 7 8 9 10 11
#基本字符匹配:匹配id含有ANV的所有行 SELECT prod_id, prod_name FROM products WHERE prod_id REGEXP 'ANV'; #'.000' SELECT prod_name FROM products WHERE prod_name REGEXP '.000'; #OR匹配 SELECT prod_name FROM products WHERE prod_name REGEXP '1000|2000'; #匹配几个字符之一:1 Ton|2 Ton|3 Ton SELECT prod_name FROM products WHERE prod_name REGEXP '[123] Ton'; #同上 SELECT prod_name FROM products WHERE prod_name REGEXP '[1|2|3] Ton';
.是正则表达式的一个特殊字符,表示匹配任意一个字符
自3.23.4后,正则匹配默认不区分大小写。可用BINARY关键字区分大小写
1 2 3 4 5
#例: #匹配行:0 SELECT prod_id, prod_name FROM products WHERE prod_id REGEXP BINARY 'aNV'; #匹配行:3 SELECT prod_id, prod_name FROM products WHERE prod_id REGEXP BINARY 'aNV';
^表否定
1 2
#匹配除1、2、3外的所有 SELECT prod_name FROM products WHERE prod_name REGEXP '[^123] Ton';
7.2 匹配范围
1 2
#-可用来定义范围你:0-9 SELECT prod_name FROM products WHERE prod_name REGEXP '[0-9] Ton';
7.3 转译(匹配特殊字符)
使用\\转义特殊字符
1 2
#匹配. SELECT prod_name FROM products WHERE prod_name REGEXP '\\.';
\\也用来引用元字符
\\f 换页
\\n 换行
\\r 回车
\\t 制表
\\v 纵向制表
匹配\使用\\\。
7.4 匹配字符类
-[:alnum:] :任意数字和字符(同[a-zA-Z0-9])
-[:alpha:] :任意字符(同[a-zA-Z])
-[:blank:] :空格和制表(同[\\t])
-[:cntrl:] :ASCII控制字符(ASCII0到31和127)
-[:digit:] :任意数字(同[0-9])
-[:graph:] :与[:print:]相同,但不包括空格
-[:lower:] :任意小写字母(同[a-z])
-[:print:] :任意可打印字符
-[:punct:] :既不在[:alnum:]也不在[:cntrl:]中的任意字符
-[:space:] :包括空格在内的任意空白字符(同[\\f\\n\\r\\t\\v])
-[:upper:] :任意大写字母(同[A-Z])
-[:xdigit:] :任意十六进制数字(同[a-fA-F0-9])
7.5 匹配多个实例(重复元字符)
* :0个或多个匹配
+ :1个或多个匹配(同{1,})
? :0个或1个匹配(同{0,1})
{n} :指定数目的匹配
{n,} :不少于指定数目的匹配
{n,m} :匹配数目的范围(m不超过255)
1 2 3 4 5 6
#例1 SELECT prod_name FROM products WHERE prod_name REGEXP '\\([0-9] sticks?\\)'; #例2:连在一起的4位数字 SELECT prod_name FROM products WHERE prod_name REGEXP '[[:digit:]]{4}'; #同上 SELECT prod_name FROM products WHERE prod_name REGEXP '[:digit:]{4}';
7.6 定位元字符
^:文本的开始
$:文本的结束
[]:
[]:
1 2
#匹配以数字或.开始的串 SELECT prod_name FROM products WHERE prod_name REGEXP '^[0-9\\.]';
SELECT cust_id, order_num FROM orders WHERE Date(order_date) in ('2005-09-01', '2005-09-30'); #上面的缺点是,当不知道某天有没有订单时,要不要写在in里, 不写肯定匹配不出来
1 2
#更好的方法: SELECT cust_id, order_num FROM orders WHERE Year(order_date) = 2005 AND Month(order_date) = 9;
9.4 数值处理函数
数值处理函数主要用于代数、三角或几何运算
值有讽刺意味的是,在主要的DBMS的函数中,数值处理函数,是最一致最统一的函数。
函数名
Abs
Cos
Exp
Mod
Pi
Rand
Sin
Sqrt
Tan
10. 汇总数据 (聚集函数)
常常需要汇总数据,而不是把它们实际检索出来
10.1 聚集函数
MySQL给出了5个SQL聚集函数:
AVG:返回某列的平均值
COUNT:返回某列的行数
MAX:返回某列的最大值
MIN:返回某列的最小值
SUM:返回某列值之和
MySQL还涉及一系列标准偏差聚集函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
#AVG SELECT AVG(prod_price) AS avg_price FROM products; SELECT AVG(prod_price) AS avg_price FROM products WHERE vend_id = 1003; #COUNT SELECT COUNT(*) AS num_cust FROM customers; #具有电子邮件地址的客户计数 SELECT COUNT(cust_email) AS num_cust FROM customers; #MAX SELECT MAX(prod_price) AS max_price FROM products; #MIN SELECT MIN(prod_price) AS min_price FROM products; #SUM SELECT SUM(quantity) AS items_ordered FROM orderitems WHERE order_num = 20005; #SUM也可以用来计算值 SELECT SUM(item_price * quantity) AS items_ordered FROM orderitems WHERE order_num = 20005;
AVG()函数将自动忽略值为NULL的行
如果指定列名,COUNT()将忽略值为NULL的行。若列名是*号,则不忽略
MAX()将自动忽略值为NULL的行
MIN()将自动忽略值为NULL的行
SUM()将自动忽略值为NULL的行
10.2 聚集不同值(DISTINCT
聚集函数的DISTINCT被添加到MySQL 5.0.3,更低版本不可用
1 2 3
#AVG DISTINCT SELECT AVG(DISTINCT prod_price) AS avg_price FROM products WHERE vend_id = 1003; #上面的代码没有很好的体现应用场景,只是做一个示例。(2021/12/2)
使用DISTINCT后,平均值提高了,因为有多个物品具有相同的较低价格。
10.3 组合聚集函数
1 2
#包含多个聚合函数 SELECT COUNT(*) AS num_items, MIN(prod_price) AS min_price, MAX(prod_price) AS max_price, AVG(prod_price) AS price_avg FROM products;
10.4 小结
11. 分组数据
11.2 创建分组**GROUP BY**
分组是在SELECT的GROUP BY字句中建立的。
1 2
#统计每个vend_id的行数 SELECT vend_id, COUNT(*) FROM products GROUP BY vend_id;
#最后COUNT(*) >= 2:过滤两个以上的订单。 SELECT cust_id, COUNT(*) AS orders FROM orders GROUP BY cust_id HAVING COUNT(*) >= 2;
#具有两个以上价格>=10的产品的供应商 SELECT vend_id, COUNT(*) AS num_prods FROM products WHERE prod_price >= 10 GROUP BY vend_id HAVING COUNT(*) >= 2;
SELECT vend_id, COUNT(*) AS num_prods FROM products WHERE prod_price >= 10 GROUP BY vend_id HAVING COUNT(*) >= 2;
11.4 分组和排序
ORDER BY:排序产生的输出
GROUP BY:分组行,但输出可能不是分组的顺序(虽然经常是以分组的顺序给出,但情况并不总是这样,这不是mysql规范所要求的)
当要求分组数据时,并不表示需要以相同的方式排序输出.所以应该提供明确的ORDER BY语句.
1 2 3 4
#总价按照order_num汇总 SELECT order_num, SUM(quantity * item_price) AS ordertotal FROM orderitems GROUP BY order_num HAVING SUM(quantity * item_price) >= 50; #根据总价排序 SELECT order_num, SUM(quantity * item_price) AS ordertotal FROM orderitems GROUP BY order_num HAVING SUM(quantity * item_price) >= 50 ORDER BY ordertotal;
#子查询 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 = 'TNT2'));
#联结查询 SELECt cust_name, cust_contact FROM customers, orders, orderitems WHERE customers.cust_id = orders.cust_id AND orders.order_num = orderitems.order_num AND orderitems.prod_id = 'TNT2';
SELECt cust_name, cust_contact FROM customers AS c, orders AS o, orderitems AS oi WHERE c.cust_id = o.cust_id AND o.order_num = oi.order_num AND oi. prod_id = 'TNT2';
使用别名主要理由
缩短SQL语句
允许在单挑SELECT语句中多次使用相同的表。
2. 自联结
一个表中,查询某件物品DTNTR的供应商的其他物品有哪些,可以使用子查询:
1 2
SELECT vend_id FROM products WHERE prod_name = 'DTNTR'; SELECT prod_name FROM products WHERE vend_id = (SELECT vend_id FROM products WHERE prod_id = 'DTNTR');
使用联结查询:
1
SELECT p1.prod_name FROM products AS p1, products AS p2 WHERE p1.vend_id = p2.vend_id AND p2.prod_id = 'DTNTR';
SELECT c.cust_id, o.order_num FROM customers AS c INNER JOIN orders AS o ON c.cust_id = o.cust_id;
使用外部联结,为了检索所有用户,保护那些没有下订单的客户:
1
SELECT c.cust_id, o.order_num FROM customers AS c LEFT JOIN orders AS o ON c.cust_id = o.cust_id;
5. 带聚集函数的联结
之前的聚集函数只在单个表使用,现在对多个表使用聚集函数。
检索所有客户以及客户所下订单数:
1 2
SELECT c.cust_name, c.cust_id, COUNT(o.order_num) AS num_ord FROM customers AS c INNER JOIN orders AS o ON c.cust_id = o.cust_id GROUP BY c.cust_id; # 此SELECT语句使用INNER JOIN将customers和orders表互相关联。GROUP BY子句按客户分组数据,因此函数调用 COUNT(orders.order_num)对每个客户的订单计数,将它作为num_ord返回。
聚集函数也可以方便地与其他联结一起使用:
1 2
# 使用LEFT JOIN 左外联结查询。对没有订单的客户也检索出来 SELECT c.cust_name, c.cust_id, COUNT(o.order_num) AS num_ord FROM customers AS c LEFT JOIN orders AS o ON c.cust_id = o.cust_id GROUP BY c.cust_id;
# 1. SELECT vend_id, prod_id, prod_price FROM products WHERE prod_price <= 5; # 2. SELECT vend_id, prod_id, prod_price FROM products WHERE vend_id in (1002, 1001);
#3. 使用UNION组合1和2 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 (1002, 1001);
#4. 使用多条WHERE子句实现3 SELECT vend_id, prod_id, prod_price FROM products WHERE prod_price <= 5 OR vend_id in (1001, 1002);
SELECT vend_id, prod_name, prod_price FROM products WHERE prod_price <= 5 UNION ALL SELECT vend_id, prod_name, prod_price FROM products WHERE vend_id in (1001, 1002);
SELECT vend_id, prod_name, prod_price FROM products WHERE prod_price <= 5 UNION SELECT vend_id, prod_name, prod_price FROM products WHERE vend_id in (1001, 1002) ORDER BY vend_id, prod_price;
CREATE TABLE productnotes ( note_id int NOT NULL AUTO_INCREMENT, prod_id char(10) NOT NULL, note_date datetime NOT NULL, note_text text NULL, PRIMARY KEY(note_id), FULLTEXT(note_text) )ENGINE=MyISAM;
MySQL根据FULLTEXT(note_text)对note_text进行索引。
使用全文检索
1 2 3 4 5 6 7
#1. 全文检索 SELECT note_text FROM productnotes WHERE Match(note_text) Against('rabbit'); #Match()指定被搜索的列,Against()指定要使用的搜索表达式 #传递给 Match()的值必须与FULLTEXT()定义中的相同
#2. LIKE SELECT note_text FROM productnotes WHERE note_text LIKE '%rabbit%';
SELECT note_text FROM productnotes WHERE Match(note_text) Against('anvils' WITH QUERY EXPANSION);
4. 布尔文本搜索
即使没有FULLTEXT索引也可以使用(意味着性能低,随着数据量越多越低)
1 2 3 4
#检索包含词heavy的所有行 SELECT note_text FROM productnotes WHERE Match(note_text) Against('heavy' IN BOOLEAN MODE); #匹配包含heavy但不包含任意以rope开始的词的行 SELECT note_text FROM productnotes WHERE Match(note_text) Against('heavy -rope*' IN BOOLEAN MODE);
5. 全文搜索使用说明
INSERT
INSERT用来插入(或添加)行到数据库。
1. 插入完整的行
指定表名和插入到新行中的值。例子:
1 2
INSERT INTO Customers VALUES(NULL, 'Pep E. LaPew','100 Main Street', 'Los Angeles', 'CA', '90046', 'USA', NULL, NULL);
CREATE TABLE IF NOT EXISTS orderitems( order_num int NOT NULL, order_item int NOT NULL, prod_id char(10) NOT NULL, quantity int NOT NULL DEFAULT 1, #指定默认值,在未给出数量的 item_price decimal(8, 2) NOT NULL, PRIMARY KEY(order_num, order_item) )ENGINE=InnoDB;
#重命名多个表 RENAME TABLE customers2 TO customers3, orders2 TO orders3, products2 TO products3;
使用视图
MySQL 5添加了对视图的支持。
视图是虚拟的表。与包含数据的表不一样,视图只包含使用时动态检索数据的查询。
1. 何为视图
检索订购了某个产品的客户:
1
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 = 'TNT2';
ORDER BY可以用在视图中。但从该视图检索数据的SELECT中的ORDER BY将覆盖视图中的ORDER BY
视图不能索引,也不能有关联的触发器或默认值
视图可以和表一起使用(例如编写一条联结表和视图的SELECT语句。
4. 使用视图
视图用CREATE VIEW语句创建
使用SHOW CREATE VIEW viewname来查看视图的语句。
用DROP删除视图(DROP VIEW viewname
更新视图时,可以先用DROP再CREATE,也可以直接CREATE OR REPLACE VIEW。
4.1 利用视图简化复杂的联结
1
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;
该语句创建一个名为productcustomers的视图,联结三个表,返回已订购任意产品的客户列表。SELECT * FROM productcustomers将列出任意订购了产品的客户。
为检索订购了产品‘TNT2’的客户:
1
SELECT cust_name, cust_contact FROM productcustomers WHERE prod_id = 'TNT2';
4.2 用视图重新格式化检索数据
在单个组合计算列种返回供应商名和位置:
1 2
SELECT Concat(RTrim(vend_name), '(', RTrim(vend_country), ')') AS vend_title FROM vendors ORDER BY vend_name;
如果经常需要这个格式化的结果,可以创建一个视图,每次需要时使用它即可。
1
CREATE VIEW vendorlocations AS SELECT Concat(RTrim(vend_name), '(', RTrim(vend_country), ')') AS vend_title FROM vendors ORDER BY vend_name;
使用:
1
SELECT * FROM vendorlocations;
4.3 用视图过滤不想要的数据
过滤没有电子邮件的客户:
1
CREATE VIEW customeremaillist AS SELECT cust_id, cust_name, cust_email FROM customers WHERE cust_email IS NOT NULL;
发送电子邮件前,需要排除没有电子邮件地址的用户。
1
SELECT * FROM customeremaillist;
4.4 使用视图与计算字段
检索某个订单种的商品,计算每种五排的总价格
1
SELECT prod_id, quantity, item_price, quantity*item_price AS expanded_price FROM orderitems WHERE order_num = 20005;
转化为视图:
1
CREATE VIEW orderitemsexpanded AS SELECT order_num, prod_id, quantity, item_price, quantity*item_price AS expanded_price FROM orderitems;
检索订单20005的详细内容:
1
SELECT * FROM orderitemsexpanded WHERE order_num = '20005';
DELIMITER // CREATE PROCEDURE productpricting() BEGIN SELECT AVG(prod_price) AS priceaverage FROM products; END; DELIMITER ; //
#记得之后把分割符修改回分号 DELIMITER ;
使用该存储过程:
1
CALL productpricting();
5. 删除存储过程
1
DROP PROCEDURE productpricing;
6. 使用参数
一般,存储过程并不显示结果,而是把结果返回给指定的变量:
1 2 3 4 5 6 7 8 9 10
CREATE PROCEDURE productpricing( OUT p1 DECIMAL(8, 2), OUT ph DECIMAL(8, 2), OUT pa DECIMAL(8, 2) ) BEGIN SELECT Min(prod_price) INTO p1 FROM products; SELECT Max(prod_price) INTO ph FROM products; SELECT Avg(prod_price) INTO pa FROM products; END;
#创建 CREATE PROCEDURE ordertotal( IN onumber INT, OUT total DECIMAL(8, 2) ) BEGIN SELECT SUM(item_price * quantity) FROM orderitems WHERE order_num = onumber INTO total; END;
CREATE PROCEDURE ordertotal( IN onumber INT, IN taxable BOOLEAN, OUT ototal DECIMAL(8, 2) )COMMENT 'Obtain order total, optionally adding tax' #COMMET非必须 BEGIN #声明变量total DECLARE total DECIMAL(8, 2); #tax,默认6 DECLARE taxrate INT DEFAULT 6; #检索和 SELECT SUM(item_price * quantity) FROM orderitems WHERE order_num = onumber INTO total; #是否加税 IF taxable THEN SELECT total + (total/100 * taxrate) INTO total; END IF;
CREATE PROCEDURE processorders() BEGIN #定义变量 DECLARE done BOOLEAN DEFAULT 0; DECLARE o INT;
#定义游标 DECLARE ordernumbers CURSOR FOR SELECT order_num FROM orders; #定义continue handle DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done = 1; #打开游标 OPEN ordernumbers; #获取order number #循环处理所有行 REPEAT FETCH ordernumbers INTO o; #结束循环 UNTIL done END REPEAT; #关闭游标 CLOSE ordernumbers; END;
但与前一个例子不一样的是,这个例子中的FETCH是在REPEAT内,因此它反复执行直到done为真(由UNTILdone END REPEAT;规定)
CREATE PROCEDURE processorders() BEGIN #定义变量 DECLARE done BOOLEAN DEFAULT 0; DECLARE o INT; DECLARE t DECIMAL(8, 2);
#定义游标 DECLARE ordernumbers CURSOR FOR SELECT order_num FROM orders; #定义continue handle DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done = 1; #创建一个表如果不存在的话 CREATE TABLE IF NOT EXISTS ordertotals(order_num INT, total DECIMAL(8,2)); #打开游标 OPEN ordernumbers; #获取order number #循环处理所有行 REPEAT #获取订单的order_num FETCH ordernumbers INTO o; #调用另一存储过程获取该order_num的合计 CALL ordertotal(o, 1, t); #将数据插入表中 INSERT INTO ordertotals(order_num, total) VALUES(o, t); #结束循环 UNTIL done END REPEAT; #关闭游标 CLOSE ordernumbers; COMMIT; END;
CREATE TRIGGER neworder AFTER INSERT ON orders FOR EACH ROW SELECT NEW.order_num; #MySQL5后不允许触发器返回任何结果,修改为: CREATE TRIGGER neworder AFTER INSERT ON orders FOR EACH ROW SELECT NEW.order_num INTO @ordernum;
为测试这个触发器,试着插入一行:
1
INSERT INTO orders (order_date, cust_id) VALUES(Now(), 10001);
3.2 DELETE触发器
在DELETE触发器代码内,可引用一个名为OLD的虚拟表,访问被删除的行
OLD中的值全部只读,不能更新
1 2 3 4 5
CREATE TRIGGER deleteorder BEFORE INSERT ON orders FOR EACH ROW BEGIN INSERT INTO archive_orders(order_num, order_date, cust_id) VALUES(OLD.order_num, OLD.order_date, OLD.cust_id); END;
使用BEFORE DELETE优点:如果由于某种原因,订单不能存档,DELETE本身将被放弃。
3.3 UPDATE触发器
可以引用OLD虚拟表访问以前的值,NEW虚拟表访问新值
BEFORE UPDATE触发器中,NEW值也可能被更新
OLD中的值全部都是只读的,不能更新
1 2
CREATE TRIGGER updatevendor BEFORE UPDATE ON vendos FOR EACH ROW SET NEW.vend_state = Upper(NEW.vend_state);
管理事务处理
1. 事务处理
事务处理可以用来维护数据库的完整性,保证成批的MySQL操作要么完全执行,要么完全不执行。
事务:指一组SQL语句。
回退:指撤销指定的SQL语句的过程。
提交:指将为存储的SQL语句结果写入数据库表。
保留点:事务处理中设置的临时占位符。
2. 控制事务处理
使用下面的语句来表示事务的开始:
1
START TRANSACTION;
2.1 回退(ROLLBACK
MySQL使用ROLLBACK命令来回退MySQL语句:
1 2 3 4 5 6
SELECT * FROM ordertotals; START TRANSACTION; DELETE FROM ordertotals; SELECT * FROM ordertotals; ROLLBACK; SELECT * FROM ordertotals;