当前位置:Gxlcms > 数据库问题 > MySQL重要知识点

MySQL重要知识点

时间:2021-07-01 10:21:17 帮助过:29人阅读

如下两条语句的结果是一样的 select * from student limit 0,5; select * from student limit 5; //返回3到10行记录 select * from student limit 2,8;

+----+------+------+

| id | name | age  |

+----+------+------+

|  3 | chou |   13 |

|  4 | he   |   14 |

|  5 | lin  |   15 |

|  6 | ll   |   16 |

|  7 | chen |   17 |

|  8 | yu   |   18 |

|  9 | wu   |   19 |

| 10 | xie  |   20 |

【总结】若是从首条记录开始返回(即起始下标为0)则可以省略起始下标,否则都需要起始下标参数beginIndex

2. MySQL中以字符串的形式存储数组

2.1. 求数组中元素的个数

方法:按指定符号分割字符串,返回分割后的元素个数,方法很简单,就是看字符串中存在多少个分隔符号,然后再加一,就是要求的结果。

技术分享图片
CREATE function Get_StrArrayLength

(

@str varchar(1024), --要分割的字符串

@split varchar(10) --分隔符号

)

returns int

as

begin

declare @location int

declare @start int

declare @length int

set @str=ltrim(rtrim(@str))

set @location=charindex(@split,@str)

set @length=1

while @location<>0

begin

set @start=@location+1

set @location=charindex(@split,@str,@start)

set @length=@length+1

end

return @length

end

调用示例:select dbo.Get_StrArrayLength(78,1,2,3,,)

返回值:4
View Code

2.2. 得到数组中指定位置的元素

方法:按指定符号分割字符串,返回分割后指定索引的第几个元素,象数组一样方便

技术分享图片
CREATE function Get_StrArrayStrOfIndex

(

@str varchar(1024), --要分割的字符串

@split varchar(10), --分隔符号

@index int --取第几个元素

)

returns varchar(1024)

as

begin

declare @location int

declare @start int

declare @next int

declare @seed int

set @str=ltrim(rtrim(@str))

set @start=1

set @next=1

set @seed=len(@split)

set @location=charindex(@split,@str)

while @location<>0 and @index>@next

begin

set @start=@location+@seed

set @location=charindex(@split,@str,@start)

set @next=@next+1

end

if @location =0 select @location =len(@str)+1

--这儿存在两种情况:1、字符串不存在分隔符号 2、字符串中存在分隔符号,跳出while循环后,@location为0,那默认为字符串后边有一个分隔符号。

return substring(@str,@start,@location-@start)

end
View Code

调用示例:select dbo.Get_StrArrayStrOfIndex(‘8,9,4‘,‘,‘,2)

返回值:9

2.3. 结合以上两个函数,遍历数组中的元素

方法:结合上边两个函数,象数组一样遍历字符串中的元素

declare @str varchar(50)

set @str=1,2,3,4,5

declare @next int

set @next=1

while @next<=dbo.Get_StrArrayLength(@str,,)

begin

print dbo.Get_StrArrayStrOfIndex(@str,,,@next)

set @next=@next+1

end

调用结果:

1

2

3

4

5

3. MySQL中的日期函数

3.1. 转DATETIME类型为Date类型

将add_time=2013-01-12 23:23:56转化为date类型

select * from product where Date(add_time) = ‘2013-01-12‘

3.2. 获取时间中的年、月、日

select * from product where Year(add_time) = 2013 and Month(add_time) = 1

3.3. DAYOFYEAR(date) 
返回date在一年中的日数, 在1到366范围内。

mysql> select DAYOFYEAR(‘1998-02-03‘); 
-> 34

3.4. DAYOFMONTH(date) 
返回date的月份中日期,在1到31范围内。

mysql> select DAYOFMONTH(‘1998-02-03‘); 
-> 3

3.5. DAYOFWEEK(date) 

返回日期date的星期索引(1=星期天,2=星期一, ……7=星期六)。这些索引值对应于ODBC标准。

mysql> select DAYOFWEEK(‘1998-02-03‘); 
-> 3

3.6. WEEKDAY(date) 

返回date的星期索引(0=星期一,1=星期二, ……6= 星期天)

mysql> select WEEKDAY(‘1997-10-04 22:23:00‘); 
-> 5 
mysql> select WEEKDAY(‘1997-11-05‘); 
-> 2

3.7. MONTHNAME(date) 
返回date的月份名字。

mysql> select MONTHNAME("1998-02-05"); 
-> ‘February‘

3.8. DAYNAME(date) 
返回某日期是星期几

mysql> select DAYNAME("1998-02-05"); 
-> ‘Thursday‘

3.9. QUARTER(date) 

查找某日期属于该年中的哪一季度,取值1到4。

mysql> select QUARTER(‘98-04-01‘); 
-> 2

3.10. 求取两日期间的天数

mysql> SELECT something FROM table 
WHERE TO_DAYS(endTime) - TO_DAYS(beginTime) <= 30;

3.11.  日期加减函数

date_add(‘2012-05-25‘, interval 1 day) 表示 2012-05-26

date_add(‘2012-05-25‘, interval -1 day) 表示 2012-05-24

date_sub(‘2012-05-25‘,interval 1 day) 表示 2012-05-24
date_sub(‘2012-05-25‘,interval -1 day) 表示 2012-05-26
//括号里的参数day可以换成month及year

3.12. 获取当前的日期、时间以及日期时间

获得当前日期(date)函数:curdate()

获得当前时间(time)函数:curtime()

获得当前日期+时间(date + time)函数:sysdate()

 sysdate() 日期时间函数跟 now() 类似,不同之处在于:now() 在执行开始时值就得到了, sysdate() 在函数执行时动态得到值。

3.13. 将将日期时间转换成对应的字符串

SELECT DATE_FORMAT(NOW(),‘%Y%m%d‘) 日期字符串,DATE_FORMAT(NOW(), ‘%Y%m%d%H%i%s‘) 日期时间字符串

4. MySQL中游标的使用

4.1. 定义游标

--创建接收游标数据的变量  
    declare c int;  
    declare n varchar(20);  
--创建游标 
  declare cur cursor for select name,count  from store where name = iphone; 
--指定游标结束循环时的标志位
  declare continue HANDLER for not found set done = true; 

在MySql中,游标溢出时会引发mysql预定义的NOT FOUND错误,当游标已经指向最后一行时继续fetch会造成游标溢出,近而引发not found错误事件,指定这个事件发生时修改done变量的值为true,从而结束循环。

4.2. 打开游标

OPEN cur

4.3. 循环遍历游标

fetch cur into n,c; #先走一步 
    while(not done) do  
        set total = total + c;  
        fetch cur into n,c;  #继续向下走
end while; #当遍历到的结果为null时,遍历完成结束循环

注】

①用当型循环(while)遍历游标时,要先将游标向下走一步。

②fetch是获取游标当前指向的数据行,并将指针指向下一行,当游标已经指向最后一行时继续fetch会造成游标溢出。

4.4. 关闭游标

close cur;  

while循环遍历游标的完整代码

drop procedure if exists StatisticStore1;  
CREATEPROCEDURE StatisticStore1()  
BEGIN
declare c int;  
declare n varchar(20);  
declare total intdefault 0;  
declare done intdefaultfalse;  
declare cur cursorforselectname,count from store wherename = iphone;  
declarecontinue HANDLER for not found set done = true;  
set total = 0;  
open cur;  
fetch cur into n,c;  
    while(not done) do  
set total = total + c;  
fetch cur into n,c;  
end while;        
close cur;  
select total;  
END;    
call StatisticStore1();   

 

注意

①所有变量的定义必须要放在游标和句柄定义之前,否则将会报如下错误:

②所有的游标必须要在句柄之前定义 

5. MySQL中常用的系统函数

5.1. 数据类型转化函数

CAST(xxx AS 类型) , CONVERT(xxx,类型)

可用的类型

二进制,同带binary前缀的效果 : BINARY

字符型,可带参数 : CHAR()

日期 : DATE

时间: TIME

日期时间型 : DATETIME

浮点数 : DECIMAL

整数 : SIGNED

无符号整数 : UNSIGNED

注:varchar类型的变量可以自动转换为数字型,转换过程中把首字符为‘0’的字符串或其它非数字字符均转换为0

5.2. 获取新增记录自增长ID的方法

mysql和oracle插入的时候有一个很大的区别,oracle支持序列做id,mysql通常将自增长的整型列作为id,mysql在插入数据时一般无需插入id字段,那么插入数据后如何获得这个自增的id呢?

方法一:使用LAST_INSERT_ID()函数

LAST_INSERT_ID()函数用于返回当前Connection所更新记录的自增长字段值,这里的更新包括Insert和Update。因为LAST_INSERT_ID是基于Connection的,保证了能够找回各客户端自己的ID而不用担心其它客户端的活动,而且不需要加锁。

SELECT LAST_INSERT_ID();

【注意】:

1.若同一条insert语句中插入多行记录(如insert into tbl_name (col_a, col_b) values (‘aa‘, ‘bb‘), (‘aaa‘, ‘bbb‘),那么该函数返回的是第一条被插入记录的id值,不是最后一条插入记录的id值。因此该方法最适合一条insert语句只插入一条数据的情况。例如:

INSERT INTO t VALUES  (NULL, Mary), (NULL, Jane), (NULL, Lisa);

mysql> SELECT LAST_INSERT_ID();
    ->2;//返回的是所插入多条记录中的最后一条记录的自增长的字段值

2. LAST_INSERT_ID 与table无关的,如果向表a插入数据后,再向表b插入数据,LAST_INSERT_ID得到的是插入到表b的id值。

方法二:使用max(id)

使用LAST_INSERT_ID是基于连接的,如果换一个窗口的时候调用则会一直返回10,如果不是频繁的插入我们也可以使用这种方法来获取返回的id值。

select max(id) from user;

】该法不是基于连接的,故不适合高并发时获取插入记录的id值。如果同时插入的时候返回的值可能不准确。

方法三:使用系统全局变量@@identity

@@identity表示最近一次向具有identity属性(即自增列)的表中插入数据时对应的自增列的值,是系统定义的全局变量。如有表A,它的自增列是id,当向A表插入一条数据时自增列id的值为101,则通过select @@identity得到的值就是101。

select @@IDENTITY

【注】Insert语句后使用全局变量@@identity才有效,并且执行select @@identity的时候连接没有关闭,否则得到的将是NULL值。

5.3. 多个字符串的拼接

语法:CONCAT(str1,str2,…)                       
返回结果为连接参数产生的字符串。如有任何一个参数为NULL,则返回值为 NULL。可以有一个或多个参数。

SELECT CONCAT(‘My’, NULL, ‘SQL’);

由于参与拼接的参数含null,所以返回结果为null

5.4. 补齐函数

5.4.1. 从左边补齐LPAD(str,length, padchar)

若字符串str的长度不够length,则将其左边用字符padchar补齐至长为length;若str的长度本身就大于length,则将其从右边起截取至length长度。

select LPAD(123, 8, 0);

select LPAD(123, 2, 0);//超过固定的长度后从右截取

5.4.2. 从右边补齐RPAD (str,length, padchar)

若字符串str的长度不够length,则将其右边用字符padchar补齐至长为length;若str的长度本身就大于length,则将其从右边起截取至length长度。

select RPAD(123, 8, 0);

select RPAD(123, 2, 0);//超过固定的长度后从右截取

【注】当超过固定的长度后左右补齐都是将右边截取

6. MySQL中变量大体可以分为四种类型

6.1. 局部变量

局部变量一般用在sql语句块中,比如存储过程的begin/end。其作用域仅限于该语句块,在该语句块执行完毕后,局部变量就消失了。

局部变量一般用declare来声明,可以使用default来说明默认值。

例如在存储过程中定义局部变量:

drop procedure if exists add;
create procedure add
(
in a int,
in b int
)
begin
declare c int default 0;
set c = a + b;
select c as c;
end;

在上述存储过程中定义的变量c就是局部变量

6.2. 用户变量

用户变量的作用域要比局部变量要广。用户变量可以作用于当前整个连接,但是当当前连接断开后,其所定义的用户变量都会消失。

用户变量使用如下(这里我们无须使用declare关键字进行定义,可以直接这样使用):

select @变量名

对用户变量赋值有两种方式,一种是直接用"="号,另一种是用":="号。其区别在于使用set命令对用户变量进行赋值时,两种方式都可以使用;当使用select语句对用户变量进行赋值时,只能使用":="方式,因为在select语句中,"="号被看作是比较操作符。

示例程序如下:

drop procedure if exists math;
create procedure math
(
    in a int,
    in b int
)
begin
    set @var1 = 1;
    set @var2 = 2;
    select @sum:=(a + b) as sum, @dif:=(a - b) as dif;
end;

调用过程

mysql> call math(3, 4);
+------+------+
| sum  | dif  |
+------+------+
|    7 |   -1 | 
+------+------+
查看用户变量@var1
mysql> select @var1; //var1
为用户变量
+-------+
| @var1 |
+-------+
| 1     | 
+-------+

查看用户变量@var1
mysql> select @var2; //var2
为用户变量
+-------+
| @var2 |
+-------+
| 2     | 
+-------+

6.3. 会话变量

服务器为每个连接的客户端维护一系列会话变量。在客户端连接时,使用相应全局变量的当前值对客户端的会话变量进行初始化。设置会话变量不需要特殊权限,但客户端只能更改自己的会话变量,而不能更改其它客户端的会话变量。会话变量的作用域与用户变量一样,仅限于当前连接。当当前连接断开后,其设置的所有会话变量均失效。

设置会话变量有如下三种方式:
set session var_name = value;
set @@session.var_name = value;
set var_name = value;

查看一个会话变量也有如下三种方式:
select @@var_name;
select @@session.var_name;
show session variables like "%var%";

6.4. 全局变量

全局变量影响服务器整体操作。当服务器启动时,它将所有全局变量初始化为默认值。这些默认值可以在选项文件中或在命令行中指定的选项进行更改。要想更改全局变量,必须具有SUPER权限。全局变量作用于server的整个生命周期,但是不能跨重启。即重启后所有设置的全局变量均失效。要想让全局变量重启后继续生效,需要更改相应的配置文件。

要设置一个全局变量,有如下两种方式:

set global var_name = value; //注意:此处的global不能省略。根据手册,set命令设置变量时若不指定GLOBAL、SESSION或者LOCAL,默认使用SESSION

set @@global.var_name = value; //同上

要想查看一个全局变量,有如下两种方式:

select @@global.var_name;

show global variables like "%var%";

【注】仅当对非局部变量赋值时才可以用“:=”,局部变量的赋值是不能用“:=”

7. MySQL设计定时器

7.1. 创建定时器

创建evevt(定时器)要调用的存储过程test_proce

drop procedure if exists test_proce
create procedure test_proce()
begin
insert into test(time) values(now());
end

创建事件test_event(其作用:每隔一秒自动调用test_proce()存储过程)
drop event if exists test_event;
create event test_event
on schedule every 1 second
on completion preserve disable
do call test_proce();

7.2. 开启定时器

MySQL中evevt功能默认是关闭的,可以使用下面的语句来看evevt的状态,如果是OFF或者0,表示是关闭的。

show variables like event_scheduler;
开启evevt功能
SET GLOBAL event_scheduler = 1;

7.3. 设置MySQL服务启动时所有定时器自启动

在文件夹选项下的查看菜单勾选显示隐藏的文件,使系统盘下的ProgramData文件夹显示出来

在ProgramData目录下找到MySQL Server的my.ini文件,将其打开后在 [mysqld]节点的如下位置添加:event_scheduler=ON

8. MySQL中varchar类型的长度含义

首先我们知道varchar类型是长度可变,但有上限的字符串类型。例如varchar(n)则表示最大长度为n个字符的字符串,注意这里n表示最大的字符数而非字节数。

实例论证:

CREATE TABLE `test_varchar_utf8` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(12) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8

8.1. 插入非中文字符

mysql> insert into test_varchar_utf8(name)values(123456789012);
Query OK, 1 row affected (0.00 sec)

mysql> insert into test_varchar_utf8(name)values(1234567890123);

ERROR 1406 (22001): Data too long for column name at row 1

#发现,对于非中文字符串,可以插入包含12个字符以及小于12个字符的字符串,当大于12个字符时报错。
#因为对于非中文的字符一个字符占用一个字节,所以,至此还不能说明varchar(n)中的n究竟代表字节数还是字符数

8.2. 插入包含中文字符的字符串

mysql> insert into test_varchar_utf8(name)values(你好么亲爱的你好么亲爱的);

Query OK, 1 row affected (0.00 sec)

mysql> insert into test_varchar_utf8(name)values(你好么亲爱的你好么亲爱的你);

ERROR 1406 (22001): Data too long for column name at row 1

#发现,对于中文字符串,也可以插入包含12个字符以及小于12个字符的字符串,当大于12个字符时报错。

#因为对于中文的字符一个字符占用三个字节,所以,说明varchar(n)中的n代表字符数而非字节数

【总结】MySQL中varchar(n)类型的长度n表示最多可接受的字符长度,而不是字节数。非中文字符时每个字符占用一个字节,当为中文字符时每个字符占用3个字节。

9. MySQL存储过程中执行动态SQL语句

--存储过程名和参数,参数中in表示传入参数,out标示传出参数,inout表示传入传出参数
create procedure p_procedurecode(in sumdate varchar(10))  
begin
     declare v_sql varchar(500);    --需要执行的SQL语句
     declare sym varchar(6);
     declare var1 varchar(20);
     declare var2 varchar(70);
     declare var3 integer;
     --定义游标遍历时,作为判断是否遍历完全部记录的标记
     declare no_more_departments integer DEFAULT 0;    
     --定义游标名字为C_RESULT
     DECLARE C_RESULT CURSOR FOR
             SELECT barcode,barname,barnum FROM tmp_table;
    --声明当游标遍历完全部记录后将标志变量置成某个值
     DECLARE CONTINUE HANDLER FOR NOT FOUND
             SET no_more_departments=1;
     set sym=substring(sumdate,1,6); --截取字符串,并将其赋值给一个遍历
     --连接字符串构成完整SQL语句,动态SQL执行后的结果记录集,在MySQL中无法获取,因此需要转变思路将其放置到一个临时表中(注意代码中的写法)。一般写法如下:
     -- Create TEMPORARY Table   表名(Select的查询语句);
     set v_sql= concat(Create TEMPORARY Table tmp_table(select aa as aacode,bb as aaname,count(cc) as ccnum from h,sym, where substring(dd,1,8)=‘‘‘,sumdate,‘‘‘ group by aa,bb));
     set @v_sql=v_sql;   --注意很重要,将连成成的字符串赋值给一个变量(可以之前没有定义,但要以@开头)
     prepare stmt from @v_sql;  --预处理需要执行的动态SQL,其中stmt是一个变量
     EXECUTE stmt;      --执行SQL语句

     deallocate prepare stmt;     --释放掉预处理段

     OPEN C_RESULT;       --打开之前定义的游标

    REPEAT                      --直到型循环语句的关键词

      FETCH C_RESULT INTO VAR1, VAR2, VAR3;   --取出每条记录并赋值给相关变量,注意顺序

       --执行查询语句,并将获得的值付给一个变量 @oldaacode(注意如果以@开头的变量可以不用通过declare语句事先声明)

       select @oldaacode:=vcaaCode from T_sum where vcaaCode=var1 and dtDate=sumdate;

           if @oldaacode=var1 then    --判断

              update T_sum set iNum=var3 where vcaaCode=var1 and dtDate=sumdate;

           else

               insert into T_sum(vcaaCode,vcaaName,iNum,dtDate) values(var1,var2,var3,sumdate);

           end if;

     UNTIL no_more_departments END REPEAT;    --循环语句结束

     CLOSE C_RESULT;                            --关闭游标

     DROP TEMPORARY TABLE tmp_table;       --删除临时表

end;

10. MySQL中事物详解

10.1. 事物的定义及特性

事务是一组操作数据库的SQL语句组成的工作单元,该工作单元中所有操作要么同时成功,要么同时失败。事物有如下四个特性,ACID简称“酸性”。

1)原子性:工作单元中所有的操作要么都成功,要么都不成功,不会出现部分成功的情况。

2)一致性:工作完成其结果应与预期一致,比如由A账户向B账户转账的事物,若该事物执行成功则必须保证A账户转出多少钱,B账户相应转入多少钱;若该事物失败,则此次转账即失败。事物的其它三个性质都是为了保证该一致性的。

3)隔离性:隔离性还可以称为并发控制、可串行化、锁等。事物中所操作的数据要隔离起来,以防止其他用户访问这些数据而带来的不一致情况。

4)持久性:事务一旦提交,其所做的修改就会永久保存到数据库中,即使数据库发生故障也不应该对其有任何影响。

事务的持久性不能做到100%的持久,只能从事务本身的角度来保证永久性,而一些外部原因导致数据库发生故障,如硬盘损坏,那么所有提交的数据可能都会丢失。

10.2. MySQL中开启事务的方法

10.2.1. 方法一

用BEGIN或START TRANSACTION来开启一个事物,COMMIT或ROLLBACK来结束该事物。

-- 保存点 savepoint  

begin  

  declare is_error int default false;#是否出错的标志  

  declare continue handler for sqlexception  

  set is_error=true;#声明异常处理程序,如果sql异常,则把标志为设置为true  

  start TRANSACTION;#开启事务,则会同时失败,同时成功  

  savepoint s1;#创建保存点  

  insert into employee(id,name,salary) values(146,cq,9000);  

  savepoint s2;  

  insert into employee(id,name,salary) values(101,cq,9000);  

  insert into employee(id,name,salary) values(102,cq,9000);  

  if is_error THEN  

    rollback to savepoint s1;-- 还原到s1  

    insert into employee(id,name,salary) values(151,cq,9000);  

    insert into employee(id,name,salary) values(152,cq,9000);  

    commit;  

  end if;  

end;  

10.2.2. 方法二

关闭自动提交,设置SET AUTOCOMMIT = 0,该语句后的所有操作都将变成事物操作,而且关闭自动提交的情况下,每个事物结束其后续操作都将开启新的事物。

set autocommit=0;#关闭自动提交  

#因为关闭了自动提交事务,则添加数据不会保存到数据库中  

insert into employee(id,name,salary) values(143,cq,9000);  

commit;#手动提交所有未执行的数据 

#由于是关闭自动提交的方式开启的事务,所以每个事物结束其后的操作自动开启新的事物

insert into employee(id,name,salary) values(258,wd,8000); #该操作属于新启的事物

10.3. 事物的隐式提交

由于事物不能被嵌套,所以当新事物开启时其前的旧事物会被隐式提交。如下情况会导致事物被隐式提交:

1)新事物的开启会导致旧事物的隐式提交

START TRANSACTION;

INSERT INTO `dm_性别`(性别名称) VALUES(不限);#该操作会被隐式提交

START TRANSACTION;

INSERT INTO `dm_性别`(性别名称) VALUES(男女);

ROLLBACK;

2)InnoDB中所有的DDL或DCL操作都会开启一个新的事物,所以DDL或DCL语句会导致旧事物的隐式提交

SET AUTOCOMMIT = 0;#利用法二关闭自动提交来开启事务 

BEGIN;  

INSERT INTO t1 VALUES (1); 

#该DDL语句会导致其前面的插入操作隐式提交 ,并开启一单一的事物

CREATE TABLE t2 (pk int primary key);

INSERT INTO t2 VALUES (2); #自动开启新的事物 

ROLLBACK; #插入表t1的数据已提交,仅能回滚插入表t2的操作

3)过程的执行区结束End之前会有一次隐式提交

BEGIN

START TRANSACTION;

INSERT INTO `dm_性别`(性别名称) VALUES(不限);

INSERT INTO `dm_性别`(性别名称) VALUES(男女);

END #在此之前会导致事物的隐式提交

10.4. 有关事物操作的注意事项

①   存储过程的执行区Begin会开启一个事物,执行区结束End会隐式提交一次

BEGIN

INSERT INTO `dm_性别`(性别名称) VALUES(‘不限‘);

INSERT INTO `dm_性别`(性别名称) VALUES(‘男女‘);

## COMMIT隐式提交该执行区域的操作

END

②   不要在事物的中途进行提交操作,一方面会破坏事物的原子性 ,另一方面该事物会到此结束

create table testproc(id int(4) primary key, name varchar(100));

#测试过程

CREATE PROCEDURE test_proc_ins( 

IN i_id INT, 

IN i_name VARCHAR(100) 

BEGIN 

start transaction; #本意是将两次插入操作捆绑成一个事物 

     INSERT INTO testproc VALUES (i_id, i_name); 

COMMIT;#由于中途提交导致该事物提交前结束,其后的操作不再是事物操作

      INSERT INTO testproc VALUES (i_id, i_name); #这里故意违反主键约束

ROLLBACK;#由于第一条插入数据的操作已提交,故这里的ROLLBACK无效

END;

 

 

③   由于DDL或DCL操作会创建新的事物,这导致其前的操作会隐式提交,从而破坏事物的原子性,所以尽量不要在过程中使用DDL或DCL语句。而且在过程中使用DDL或DCL语句的语法是比较复杂的,所以不建议在过程中使用DDL或DCL语句。

SET AUTOCOMMIT = 0;  

BEGIN;  

INSERT INTO t1 VALUES (1);  

#该DDL语句开启新事物会隐式提交其前的事物 

CREATE TABLE t2 (pk int primary key); INSERT INTO t2 VALUES (2);  

ROLLBACK;  

SHOW TABLES

④   Start Transaction(Begin)

人气教程排行