SQL server(全局变量、局部变量、循环、事务、幻读、脏读、不重复读等)

--每页10行,查询第2页,按成绩排序降序

--两种方式:1、top  2、row_number()

--1、top方式:

select top(10) * from student where 成绩 not in

(select top(10*(2-1)) 成绩 from student order by 成绩 desc) as t

order by 成绩 desc

;

--2、row_number()方式:思路:1、先在后面加一列序号   2、把加完序号的虚表作为原表,查询指定范围

select * from

(select *,序号=ROW_NUMBER() over(order by id) from student)as t

where t.序号 between 10*(2-1)+1 and 10*2;

;

--mysql实现:

select * from student limit 10*(2-1)+1,10;

--咱们以后用的是mysql和oracle,绝对不用sqlserver   select * from

 

------------------------局部变量--------------------------------

--java中怎么声明变量   int a;   private int a;  public static int a;  a = 10;

declare @a int;

set @a=10;

select @a;

use wx105;

declare @name nvarchar(50);

select top(1) @name=name from stuInfo_new where id=1;

select @name='赵云';

set @name='赵云';

select @name;

--总结:声明变量只有一种方式:declare   给变量赋值有三种:1、set 2、select 3、select查询后的结果赋值

declare @name nvarchar(50);

declare @gexing nvarchar(100);

set @name='刘书靖';

select @gexing='窈窕淑女!哈哈哈!!!';

select @name as 姓名,@gexing as 个性;

--java中一次声明多个变量:int a,b,c,d,e  sql中也可以

declare @name nvarchar(100), @gexing nchar(50); --一次性声明多个变量

set @name='刘书靖';

select @gexing='窈窕淑女!哈哈哈!!!';

--select @name as 姓名,@gexing as 个性;

print @name;--print不能一次性打印多个变量

 

-----------------------循环(while)----------------------

declare @a int

set @a = 10

while (@a<20) begin

print @a

set @a+=1

end

 

--计算1到100之间所有整数之和

declare @i int  = 1

declare @sum int = 0

while(@i<=100)begin

set @sum=@sum+@i

set @i = @i + 1

end

select @sum

--java中的if else

--输出100以内所有的奇数

declare @i int  = 1;

while(@i<=100)begin

if(@i%2!=0)begin

print @i;

end

set @i = @i+1;

end

 

--需求:当i是10的时候,输出“刘淑静是个大美女”,然后结束本循环

declare @i int = 1

while(@i<=100)begin

print @i

if(@i=10)begin

print '刘淑静是个大美女'

break

 end

 print @i

 set @i = @i + 1

 end

--需求:当i是10的时候,输出“高帅是个大美男”,然后结束本次循环,继续下次循环

declare @i int = 0;

while(@i<=100)begin

set @i = @i + 1

select @i

if(@i=10)begin

select '高帅是个大美男'

continue

 end

select @i

 end

 

 

--1到100之间所有偶数之和

declare @i int = 1,@sum int = 0

while(@i<=100)begin

if(@i%2 <> 0)begin  --  <>和!=一样,而java中的==在sql中没有,只有=

set @sum = @sum + @i

end

set @i = @i+1

 end

 print @sum

 

 --sql中没有for循环

 

 

 --全局变量,由系统维护,我们只能查询,不能修改。但是我们可以自己创建

 print @@version;(SQLserver的版本信息)

 set @@VERSION='哈哈哈';

 declare @@a int =10

 set @@a = 100

 print @@a

 print @@error(最后一个T-SQL错误的错误号

 select * from stuInfo_new group by name;

 update accout set 余额=余额-1000000 where name='将冲';

 update accout set 余额=余额+1000000 where name='赵与';

 print @@error

 

 print @@identity(最后一次插入的标识值)

 print @@language(当前使用的语言名称)

 print @@max_connections(可以创建的同时连接最大的数目)

 select * from stuInfo_new

 print @@rowcount(受到上一个SQL语句影响的行数

 

create table account

(

id int primary key identity(1,1),

name nvarchar(100) not null,

money bigint not null check(money>=10) default(10)

)

insert into account values('蒋冲',100)

insert into account values('赵云',90)

 

select * from account

 

二个选一个写即可

begin transaction  --开启一个事务

declare @e int = 0

 

update account set money = money- 90 where name like '赵云'

set @e += @@error  --有个特点,读取一次之后,重置为0

update account set money = money+ 90 where name like '蒋冲'

set @e += @@error  

 

if(@e<>0)begin   --@e不等于0,说明出过错

rollback   --回滚

end else begin

commit   --提交

end

 

--需求:把上面代码再写一遍


begin transaction --开启一个事务   在这里,可以把transaction简写成tran,但是不能省略

declare @sum int = 0

update account set money = money-90 where name like '赵云'

set @sum += @@ERROR    --记录错误信息

update account set money = money+90 where name like '蒋冲'

set @sum += @@ERROR

if(@sum<>0)begin    --判断是否出过错

rollback transaction  --在这里,transaction可以简写成tran,也可以省略掉不写

end else begin

commit transaction  --在这里,transaction可以简写成tran,也可以省略掉不写

end

--默认隐式事务未开启

update account set money = money-90 where name like '赵云'

update account set money = money+90 where name like '蒋冲'

 

select * from account

--

set implicit_transactions on --开启隐式事务,开启后,必须手动提交或者回滚

--蒋冲的操作

update account set money = money-10 where name like '赵云'

update account set money = money+10 where name like '蒋冲'

--刘振兴的操作

update account set money = money-1000 where name like '蒋冲'

--马晓雨的操作

update account set money = money+1000 where name like '赵云'

rollback

 

(重在理解)最好用自己的话记。

--------------------脏读、不可重复读、幻读(虚读)----------------------

--脏读:即读取到不正确的数据,因为另一个事务可能还没提交最终数据,这个读的事务就读取了中途的数据,这个数据可能是不正确的。 解决办法就是后面要讲的设置事务的隔离级别为“Read committed(读已提交) ”。

--不可重复读:即在一次事务之间,进行了两次读取,但是结果不一样,可能第一次id为1的人叫“李三”,第二次读id为1的人就叫了“李四”。原因是因为读取操作不会阻止其他事务。 解决办法就是后面要讲的设置事务的隔离级别为“Repeatable read(可重复读) ”。

--幻读:可重复读阻止的写事务包括update和delete(只给存在的表加上了锁),但是不包括insert(新行不存在,所以没有办法加锁),所以一个事务第一次读取可能读取到了10条记录,但是第二次可能读取到11条,这就是幻读。 解决办法就是后面要讲的设置事务的隔离级别为“Serializable(串行化) ”。

--总结:这三个的区别:脏读是读取到了对方没有提交的数据,原因是这边的读取操作无法控制别人的事务操作。通俗点说就是帅兵转10000给赵云,还没提交,赵云就查看了,发现已经到账了,但是之后帅兵又回滚了,那刚才赵云读到的数据就是脏的

--不可重复读是两次读取数据不一样,原因是无法阻止别的事务的所有操作(增、删、改、查),通俗点说就是蒋冲在ATM机上查询余额的时候,不能阻止他媳妇的任何操作

--幻读是两次读取的表的行数不一样,原因是即使设置了可重复读,也无法阻止别人的插入操作,通俗点说就是第一次查看咱班的表行数是46,然后别人进咱班了,我又查看了一次,发现变成47人了,这种情况就是幻读

--以上这几个问题需要解决:隔离

--隔离有四种,分别解决以上三个问题:

--1、read commited(读已提交):解决了脏读问题,就是说只要设置数据库的隔离级别为这个级别,就不会出现脏读情况了。原理:当表被更新但没提交或回滚时,此表处于隔离状态,其他用户(会话)无法查询

--   演示脏读现象:数据库默认级别是read commited级别,已经不会出现脏读现象了,所以我们为了演示,把级别降低为

DBCC USEROPTIONS

 

set transaction isolation level read uncommitted  --设置本会话的隔离级别为最低级别

select * from account

 

set transaction isolation level read committed  --设置本会话的隔离级别为最低级别

select * from account

update account set money=1000 where name like '赵云';

--2、repeatable read(可以重复读):解决了不可重复读的问题,就是说只要设置数据库的隔离级别为这个级别,就不会出现不可重复读的情况了

--演示不可重复读现象:

set implicit_transactions on --手动设置事务

select * from account where name like '蒋冲';

commit

set transaction isolation level repeatable read

set implicit_transactions on

select * from account where name like '蒋冲';

select * from account where name like '蒋冲';

commit

--3、serializable(串行化):解决了幻读的问题,就是说只要设置数据库的隔离级别为这个级别,就不会出现幻读的情况了

--演示幻读现象:

select * from account

commit

select * from account

delete from account where name like '马晓雨';

commit

--解决方案:设置隔离级别为serializable

    set transaction isolation level serializable

select * from account

commit

select * from account

--总结:read uncommitted < read committed  < repeatable read  < serializable  这几个级别越来越高,高的级别可以把前面所有的问题都解决掉,注意:越往后效率越低

 

猜你喜欢

转载自blog.csdn.net/qq_39115649/article/details/80592131