mysql小结

334 阅读17分钟

MYSQL

and 优先级高于 or

select * from product where id='1' or id='2' and price>=10;-----------查出id为2和price大于等于10的,或者id为2的

select * from product where (id='1' or id='2') and price>=10;-----------查出id为1或2和price大于等于10的。====select * from product where id in ('1', '2') and price >=10;

like

%可以匹配0个、一个或多个字符

select * from product where name like 'jet%';-----------查出名称以jet开头的,不管jet之后有多少字符

select * from product where name like '%ack%';-----------查出包含ack的,不管ack前后有多少字符

select * from product where name like 's%e';-----------查出以s开头e结尾的,不管s和e中间有多少字符

_(下划线)可以匹配一个字符

正则表达式

REGEXP告诉mysql他后面所跟的东西是正则表达式

select * from product where name REGEXP '1000';

.可以用来匹配任意一个字符

select * from product where name REGEXP '.000';

MySQL中的正则表达式匹配(自版本 3.23.4后)不区分大小写(即,大写和小写都匹配)。为区分大 小写,可使用BINARY关键字,如WHERE prod_name REGEXP BINARY 'JetPack .000'。

使用|,为搜索两个串之一(或者为这个串,或者为另一个串)

select * from product where name REGEXP '1000|2000';

指定一组用[和]括起来的字符,想匹配特定的字符

select * from product where name REGEXP '[123] Tom';

可使用-来定义一个范围。下面的式子功能上等同于上述数字列表:[0-9] ,范围不限于完整的集合,[1-3]和[6-9]也是合法的范围。此外,范 围不一定只是数值的,[a-z]匹配任意字母字符

select * from product where name REGEXP '[1-5] Tom';

为了匹配特殊字符,必须用\(双反斜杠)为前导。\-表示查找-,\.表示查找.。

select * from product where name REGEXP '\.'; select * from product where name REGEXP '\([0-0] sticks?\)';

select * from product where name REGEXP '[[:digit:]]{4}';

定位符

select * from product where name REGEXP '^[0-9\.]';

^的双重用途 ^有两种用法。在集合中(用[和]定义),用它 来否定该集合,否则,用来指串的开始处。

创建计算字段

拼接字段(concat)

select Concat(name, '(', country, ')') from supplier;

Concat()需要一个或多个指定的串,各个串之间用逗号分隔。

通过删除数据右侧多余的空格来整理数据,这可以 使用MySQL的RTrim()函数来完成

select Concat(name, '(', RTrim(country), ')') from supplier;

Trim函数

MySQL除了支持RTrim()(正如刚才所见,它去掉 串右边的空格),还支持LTrim()(去掉串左边的空格)以及 Trim()(去掉串左右两边的空格)。

执行算术计算

select id, quality, price, quality*price as total from orders;

使用数据处理函数

函数

文本处理函数

select name, Upper(name) as nameUp from product;

SOUNDEX是一个将任何文 本串转换为描述其语音表示的字母数字模式的算法。

日期和时间处理函数

select id, num from orders where Date(order_date) = '2020-12-3';

数值处理函数

聚集函数

AVG()函数

select AVG(price) as avg_price from product;

select AVG(price) as avg_price from product where id = '1003';

COUNT()函数

COUNT()函数有两种使用方式。

使用COUNT(*)对表中行的数目进行计数,不管表列中包含的是空值(NULL)还是非空值。

使用COUNT(column)对特定列中具有值的行进行计数,忽略NULL值。

MAX()函数

select MAX(price) as max_price from product;

对非数值数据使用MAX()

虽然MAX()一般用来找出最大的数值或日期值,但MySQL允许将它用来返回任意列中的最大值,包括返回文本列中的最大值。在用于文本数据时,如果数据按相应的列排序,则MAX()返回最后一行。

NULL值 MAX()函数忽略列值为NULL的行。

MIN()函数

select MIN(price) as min_price from product;

对非数值数据使用MIN()

MIN()函数与MAX()函数类似,MySQL允许将它用来返回任意列中的最小值,包括返回文本列中的最小值。在用于文本数据时,如果数据按相应的列排序,则MIN()返回最前面的行。

NULL值 MIN()函数忽略列值为NULL的行。

SUM()函数

select SUM(quality) as sum_quality from product where order_num=20005;

函数SUM(item_price*quantity)返回订单中所有物品价钱之和,WHERE子句同样保证只统计某个物品订单中的物品

select AVG( DISTINCT price) as avg_price from product;--------使用了DISTINCT参数,因此平均值只 考虑各个不同的价格

如果指定列名,则DISTINCT只能用于COUNT()。DISTINCT不能用于COUNT(*),因此不允许使用COUNT(DISTINCT),否则会产生错误。类似地,DISTINCT必须使用列名,不能用于计算或表达式。

将DISTINCT用于MIN()和MAX() 虽然DISTINCT从技术上可用于MIN()和MAX(),但这样做实际上没有价值。一个列中的最小值和最大值不管是否包含不同值都是相同的。

组合聚集函数

select COUNT(*) AS num_items, MIN(price) AS min_price, MAX(price) AS max_price, AVG(price) AS avg_price from product;

分组数据

select id, COUNT(*) AS num_product from product GROUP BY product;

在具体使用GROUP BY子句前,需要知道一些重要的规定。

GROUP BY子句可以包含任意数目的列。这使得能对分组进行嵌套,为数据分组提供更细致的控制。

如果在GROUP BY子句中嵌套了分组,数据将在最后规定的分组上进行汇总。换句话说,在建立分组时,指定的所有列都一起计算(所以不能从个别的列取回数据)。

GROUP BY子句中列出的每个列都必须是检索列或有效的表达式(但不能是聚集函数)。如果在SELECT中使用表达式,则必须在GROUP BY子句中指定相同的表达式。不能使用别名。

除聚集计算语句外,SELECT语句中的每个列都必须在GROUP BY子句中给出。

如果分组列中具有NULL值,则NULL将作为一个分组返回。如果列中有多行NULL值,它们将分为一组。

GROUP BY子句必须出现在WHERE子句之后,ORDER BY子句之前。

使用WITH ROLLUP关键字,可以得到每个分组以及每个分组汇总级别(针对每个分组)的值,如下所示:

select id, COUNT(*) AS num_product from product GROUP BY product WITH ROLLUP;

过滤分组

select id, COUNT(*) AS num_product from product GROUP BY product having num_product >= 2;

HAVING和WHERE的差别

这里有另一种理解方法,WHERE在数据分组前进行过滤,HAVING在数据分组后进行过滤。这是一个重要的区别,WHERE排除的行不包括在分组中。这可能会改变计算值,从而影响HAVING子句中基于这些值过滤掉的分组。

分组和排序

select order_num, SUM(quality*order_num) AS total from orders GROUP BY order_num having total >= 50 ORDER BY total;

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 = 'TNT2'

​ )

);

select cust_name, cust_state, (select COUNT(*) from orders where orders.cust_id = customers.cust_id) as orders from customers order by cust_name;

联结表

select vend_name, prod_name, prod_price from vendors, products where vendors.vend_id = products.vend_id order by vend_name, prod_name;

等同于

select vend_name, prod_name, prod_price from vendors inner join products on vendors.vend_id = products.vend_id;

联结多个表

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 = 20005;

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 orderitems.order_num = orders.order_num and prod_id = 'TNT2';

创建高级联结

自联结

select prod_id, prod_name from products as p1, products as p2 where p1.vend_id = p2.vend_id and p2.prod_id = 'DTNTR';

自然连接

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

外部联结

下面的SELECT语句给出一个简单的内部联结。它检索所有客户及其订单:

select customers.cust_id, orders.order_num from customers inner join orders on customers.cust_id = orders.cust_id;

外部联结语法类似。为了检索所有客户,包括那些没有订单的客户,可如下进行:

select customers.cust_id, orders.order_num from customers left outer join orders on customers.cust_id = orders.cust_id;

与内部联结关联两个表中的行不同的是,外部联结还包括没有关联行的行。

在使用OUTER JOIN语法时,必须使用RIGHT或LEFT关键字指定包括其所有行的表(RIGHT指出的是OUTER JOIN右边的表,而LEFT指出的是OUTER JOIN左边的表)。

使用带聚集函数的联结

select customers.cust_name, 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;

select customers.cust_name, 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;

使用联结和联结条件

注意所使用的联结类型。一般我们使用内部联结,但使用外部联结也是有效的。

保证使用正确的联结条件,否则将返回不正确的数据。

应该总是提供联结条件,否则会得出笛卡儿积。

在一个联结中可以包含多个表,甚至对于每个联结可以采用不同的联结类型。虽然这样做是合法的,一般也很有用,但应该在一起测试它们前,分别测试每个联结。这将使故障排除更为简单。

组合查询

UNION

UNION必须要有两条或者两条以上select组成,中间由UNION关键字分隔,必须包含相同的列,列数据类型必须兼容

UNION自动去除了重复的行,如果要匹配所有的行,使用UNION ALL

在使用UNION组合查询时,只能使用一条ORDER BY 子句,必须出现在最后一条select子句后。

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)

ORDER BY vend_id, prod_price;

全文本搜索

mysql支持几种基本的数据库引擎。并非所有的引擎都支持全文本搜索。最常使用的引擎MyISAM和InnoDB,MyISAM支持全文本搜索,InnoDB不支持。

要进行全文本搜索,必须索引被搜索的列,且要随着数据的改变不断的索引。

索引之后,select可与Match()和Against()一起使用执行搜索.

Match()指定被搜索的列,Against()指定要使用的搜索表达式。

CREATE TABLE productnotes

(

​ note_id int NOT NULL 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;

不要在导入数据时使用FULLTEXT,先不启用FULLTEXT导入数据,导入完成之后启用FULLTEXT。

select note_text from productnotes where Match(note_text) Against('rabbit');

此语句还可以使用like完成,查出数据次序可能不同。

全文本搜索会对结果进行排序,具有较高等级的行先返回。

select note_text, Match(note_text) Against('rabbit') AS rank from productnotes;

上面语句会查出计算的等级。

查询扩展

找出所有提到ancils的注释,但是还想搜索有关的所有其他行,即使不含词anvils。

select note_text from productnotes where Match(note_text) Against('anvils' WITH QUERY EXPANSION);

布尔文本搜索

布尔方式不同于迄今为止使用的全文本搜索语法的地方在于,即使没有定义FULLTEXT索引,也可以使用它。

select note_text from productnotes where Match(note_text) Against('heavy' IN BOOLEAN MODE);

使用了关键字IN BOOLEAN MODE,但实际上没有指定布尔操作符,因此,其结果与没有指定布尔方式的结果相同。

为了匹配包含heavy但不包含任意以rope开始的词的行,可使用以下查询:

select note_text from productnotes where Match(note_text) Against('heavy -rope*' IN BOOLEAN MODE);

插入数据

单条

INSERT INTO customers(

​ cust_name,

​ cust_address,

​ cust_email

) VALUES(

​ 'zz',

​ 'jiangsu',

​ NULL

);

多条

INSERT INTO customers(

​ cust_name,

​ cust_address,

​ cust_email

) VALUES(

​ 'zz',

​ 'jiangsu',

​ NULL

),(

​ 'xm',

​ 'jiangsu',

​ NULL

);

插入检索出的数据

INSERT INTO customers(

​ cust_id,

​ cust_name,

​ cust_address,

​ cust_email

)

SELECT cust_id,

​ cust_name,

​ cust_address,

​ cust_email

FROM custnew;

更新和删除数据

UPTATE customers SET cust_name = 'zzw' WHERE cust_id = 1005;

UPTATE customers SET cust_name = 'zzw', cust_address = 'nt' WHERE cust_id = 1005;

DELETE FROM customers WHERE cust_id = 1006;

创建和操纵表

创建表

CREATE TABLE customers(

​ cust_id int NOT NULL AUTO_INCREMENT,

​ cust_name char(50) NOT NULL,

​ cust_address char(50) NULL,

​ cust_email char(255) NULL,

​ del_flag char(1) NOT NULL DEFAULT '0',

​ PRIMARY KEY (cust_id)

) ENGINE=InnoDB;

更新表

添加列ALTER TABLE vendors ADD vend_phone CHAR(20);

删除列ALTER TABLE vendors DROP vend_phone CHAR(20);

定义外键

ALTER TABLE orders ADD CONSTRAINT fk_orders_customers FOREIGN KEY (cust_id) REFERENCES customers (cust_id);

删除表

DROP TABLE customer;

重命名表

RENAME TABLE customer TO customers;

RENAME TABLE customer TO customers, order TO orders;

使用视图

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;

重新格式化数据

CREATE VIEW vendorlocations AS SELECT Concat(RTrim(vend_name), '(', RTrim(vend_country), ')') AS vend_title FROM vendors ORDER BY vend_name;

过滤数据

CREATE VIEW customeremail AS SELECT cust_id, cust_name, cust_email FROM customers WHERE cust_email IS NOT NULL;

计算字段

CREATE VIEW orderitemsexpanded AS SELECT order_num, prod_id, quantity, tiem_price, quantity*item_price AS total FROM orderitems;

使用存储过程

创建存储过程

CREATE PROCEDURE productpricing()

BEGIN

​ SELECT Avg(prod_price) AS priceaverage

​ FROM products;

END;

用CREATE PROCEDURE语句定义存储过程,如果存在参数,将他们在()中列举出来。

使用此存储过程,CALL productpricing();就可以得出平均价格

删除存储过程

DROP PROCEDURE productpricing;

使用此语句,存储过程不存在就会报错。使用DROP PROCEDURE IF EXISTS就可以避免。

使用参数

CREATE PROCEDURE productpricing(

​ OUT pl DECIMAL(8,2),

​ OUT ph DECIMAL(8,2),

​ OUT pa DECIMAL(8,2)

)

BEGIN

​ SELECT Min(prod_price)

​ INTO pl

​ FROM products;

​ SELECT Max(prod_price)

​ INTO ph

​ FROM products;

​ SELECT Avg(prod_price)

​ INTO pa

​ FROM products;

END;

pl存储产品最低价格,ph存储产品最高价格,pa存储产品平均价格。关键字OUT指出相应的参数用来从存储过程传出一个值(返回给调用者)。MySQL支持IN(传递给存储过程)、OUT(从存储过程传出,如这里所用)和INOUT(对存储过程传入和传出)类型的参数。

调用

CALL productpricing(

​ @pricelow,

​ @pricehigh,

​ @priceaverage

);

使用此语句并不显示任何数据,使用下面语句可显示

SELECT @priceaverage;

SELECT @pricehigh, @pricelow, @priceaverage;

CREATE PROCEDURE ordertotal(

​ IN onnumber INT,

​ OUT ototal DECIMAL(8,2)

)

BEGIN

​ SELECT Sum(item_price*quantity)

​ FROM orderitems

​ WHERE order_num = onumber

​ INTO ototal;

END;

onumber定义为IN,因为订单号被传入存储过程。ototal定义为OUT,因为要从存储过程返回合计。SELECT语句使用这两个参数,WHERE子句使用onumber选择正确的行,INTO使用ototal存储计算出来的合计。

调用

CALL ordertotal(20005, @total);

SELECT @total;

建立智能存储过程

CREATE PROCEDURE ordertotal(

​ IN onnumber INT,

​ IN taxable BOOLEAN,

​ OUT ototal DECIMAL(8,2)

) COMMENT 'Obtain order total, optionally adding tax'

BEGIN

​ -- Declare variable for total

​ DECLARE total DECIMAL(8,2);

​ -- Declare tax percentage

​ DECLARE taxrate INT DEFAULT 6;

​ -- Get the orde total

​ SELECT Sum(item_price*quantity)

​ FROM orderitems

​ WHERE order_num = onumber

​ INTO total;

​ -- Is this taxable

​ IF taxable THEN

​ -- Yes, so add taxrate to the total

​ SELECT total+(total/100*taxrate) INTO total;

​ END IF;

​ -- And finally, save to out variable

​ SELECT total INTO ototal;

END;

DECLARE语句定义了两个局部变量。DECLARE要求指定变量名和数据类型,它也支持可选的默认值。

SELECT语句已经改变,因此其结果存储到total(局部变量)而不是ototal。IF语句检查taxable是否为真,如果为真,则用另一SELECT语句增加营业税到局部变量total。最后,用另一SELECT语句将total(它增加或许不增加营业税)保存到ototal。

调用

CALL ordertotal(20005, 0, @total);

SELECT @total;

CALL ordertotal(20005, 1, @total);

SELECT @total;

BOOLEAN值指定为1表示真,指定为0表示假(实际上,非零值都考虑为真,只有0被视为假)

检查存储过程

显示创建存储过程的CREATE语句

SHOW CREATE PROCEDURE ordertotal;

获得包括何时、由谁创建等详细信息的存储过程列表,使用SHOW PROCEDURE STATUS

加限制SHOW PROCEDURE STATUS LIKE 'ordertotal';

使用游标

创建游标

CREATE PROCEDURE processorders()

BEGIN

​ DECLARE ordernumbers CURSOR

​ FOR

​ SELECT order_num FROM orders;

END;

DECLARE语句用来定义和命名游标,这里为ordernumbers。存储过程处理完成后,游标就消失(因为它局限于存储过程)。

打开和关闭游标

OPEN ordernumbers;

CLOSE ordernumbers;

使用游标数据

CREATE PROCEDURE processorders()

BEGIN

​ -- Declare local variables

​ DECLARE o INT;

​ -- Declare the cursor

​ DECLARE ordernumbers CURSOR

​ FOR

​ SELECT order_num FROM orders;

​ -- Open the cursor

​ OPEN ordernumbers;

​ -- Get order number

​ FETCH ordernumbers INTO o;

​ -- Close the cursor

​ CLOSE ordernumbers;

END;

其中FETCH用来检索当前行的order_num列(将自动从第一行开始)到一个名为o的局部声明的变量中。

CREATE PROCEDURE processorders()

BEGIN

​ -- Declare local variables

​ DECLARE done BOOLEAN DEFAULT 0;

​ DECLARE o INT;

​ -- Declare the cursor

​ DECLARE ordernumbers CURSOR

​ FOR

​ SELECT order_num FROM orders;

​ -- Declare continue handler

​ DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done=1;

​ -- Open the cursor

​ OPEN ordernumbers;

​ -- Loop through all rows

​ REPEAT

​ -- Get order number

​ FETCH ordernumbers INTO o;

​ -- End of loop

​ UNTIL done END REPEAT;

​ -- Close the cursor

​ CLOSE ordernumbers;

END;

FETCH是在REPEAT内,因此它反复执行直到done为真(由UNTIL done END REPEAT;规定)。为使它起作用,用一个DEFAULT 0(假,不结束)定义变量done。

CONTINUE HANDLER,它是在条件出现时被执行的代码。这里,它指出当SQLSTATE '02000'出现时,SET done=1。SQLSTATE '02000'是一个未找到条件,当REPEAT由于没有更多的行供循环而不能继续时,出现这个条件。

CREATE PROCEDURE processorders()

BEGIN

​ -- Declare local variables

​ DECLARE done BOOLEAN DEFAULT 0;

​ DECLARE o INT;

​ DECLARE t DECIMAL(8,2);

​ -- Declare the cursor

​ DECLARE ordernumbers CURSOR

​ FOR

​ SELECT order_num FROM orders;

​ -- Declare continue handler

​ DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done=1;

​ -- Create a table to store the results

​ CREATE TABLE IF NOT EXISTS ordertotals(

​ order_num INT,

​ total DECIMAL(8,2)

​ );

​ -- Open the cursor

​ OPEN ordernumbers;

​ -- Loop through all rows

​ REPEAT

​ -- Get order number

​ FETCH ordernumbers INTO o;

​ --Get the total for this order

​ CALL ordertotal(o, 1, t);

​ --Insert order and total into ordertotals

​ INSERT INTO ordertotals(order_num, total) VALUES(o, t);

​ -- End of loop

​ UNTIL done END REPEAT;

​ -- Close the cursor

​ CLOSE ordernumbers;

END;

使用触发器

触发器是MySQL响应以下任意语句而 自动执行的一条MySQL语句(或位于BEGIN和END语句之间的一组语句):DELETE、INSERT、UPDATE

创建触发器

CREATE TRIGGER newproduct AFTER INSERT ON products FOR EACH ROW SELECT 'Product added';

CREATE TRIGGER用来创建名为newproduct的新触发器。

AFTER INSERT,所以此触发器将在INSERT语句成功执行后执行。

FOR EACH ROW,因此代码对每个插入行执行。

这里文本Product added将对每个插入的行显示一次。

每个表最多支持6个触发器(每条INSERT、UPDATE和DELETE的之前和之后)。单一触发器不能与多个事件或多个表关联,所以,如果需要一个对INSERT和UPDATE操作执行的触发器,则应该定义两个触发器。

删除触发器

DROP TRIGGER newproduct;

使用触发器

在INSERT触发器代码内,可引用一个名为NEW的虚拟表,访问被插入的行;

在BEFORE INSERT触发器中,NEW中的值也可以被更新(允许更改被插入的值);

对于AUTO_INCREMENT列,NEW在INSERT执行之前包含0,在INSERT执行之后包含新的自动生成值。

CREATE TRIGGER neworder AFTER INSERT ON orders FOR EACH ROW SELECT NEW.order_num;

在插入一个新订单到orders表时,MySQL生成一个新订单号并保存到order_num中。触发器从NEW. order_num取得这个值并返回它。此触发器必须按照AFTER INSERT执行,因为在BEFORE INSERT语句执行之前,新order_num还没有生成。对于orders的每次插入使用这个触发器将总是返回新的订单号。

DELETE触发器

在DELETE触发器代码内,你可以引用一个名为OLD的虚拟表,访问被删除的行;

OLD中的值全都是只读的,不能更新。

CREATE TRIGGER deleteorder BEFORE DELETE 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;

在任意订单被删除之前,使用一条INSERT语句将OLD中的值保存到archive_orders的表中。

UPDATE触发器

在UPDATE触发器代码中,你可以引用一个名为OLD的虚拟表访问以前(UPDATE语句前)的值,引用一个名为NEW的虚拟表访问新更新的值;

在BEFORE UPDATE触发器中,NEW中的值可能也被更新(允许更改将要用于UPDATE语句中的值);

OLD中的值全都是只读的,不能更新。

CREATE TRIGGER updateevendor BEFORE UPDATE ON vendors FOR EACH ROW SET NEW.vend_state = Upper(NEW.vend_state);

每次更新一个行时,NEW.vend_state中的值(将用来更新表行的值)都用Upper(NEW.vend_state)替换。

管理事务处理

事务(transaction)指一组SQL语句;

回退(rollback)指撤销指定SQL语句的过程;

提交(commit)指将未存储的SQL语句结果写入数据库表;

保留点(savepoint)指事务处理中设置的临时占位符(place-holder),你可以对它发布回退(与回退整个事务处理不同)。

开始事务

START TRANSACTION;

使用ROLLBACK

SELECT * FROM ordertotals;

START TRANSACTION;

SELECT * FROM ordertotals;

ROLLBACK;

SELECT * FROM ordertotals;

使用COMMIT

START TRANSACTION;

DELETE FROM orderitems WHERE order_num = 20010;

DELETE FROM orders WHERE order_num = 20010;

COMMIT;

使用保留点

SAVEPOINT delete1;

ROLLBACK TO delete1;

更改默认的提交行为

SET autocommit=0;

autocommit标志决定是否自动提交更改,不管有没有COMMIT语句。设置autocommit为0(假)指示MySQL不自动提交更改(直到autocommit被设置为真为止)。