概述
1. 事物的基本操作
转账问题:
假定钱从A转到B,至少需要两步:
create table bank
(
cId char(4) primary key,
balance money, --余额
)
alter table bank
add constraint CH_balance check(balance >=10)
go
--delete from bank
insert into bank values('0001',1000)
insert into bank values('0002',10)
go
update bank set balance=balance-1000 where cid='0001'
update bank set balance=balance + 1000 where cid='0002'
--查看结果,注意是否会出现问题!
SELECT * FROM bank
注意约束:金额不能小于10
事务的ACID特性:
事务是作为单个逻辑工作单元执行的一系列操作。一个逻辑工作单元必须有四个属性,称为原子性、一致性、隔离性和持久性(ACID)属性,只有这样才能成为一个事务。
原子性:事务必须是原子工作单元;对于其数据修改,要么全都执行,要么全都不执行。
一致性:事务在完成时,必须使所有的数据都保持一致状态。在相关数据库中,所有规则都必须应用于事务的修改,以保持所有数据的完整性。事务结束时,所有的内部数据结构(如B树索引或双向链表)都必须是正确的。
隔离性:由并发事务所作的修改必须与任何其他并发事务所作的修改隔离。事务识别数据时数据所处的状态,要么是另一并发事务修改它之前的状态,要么是第二个事务修改它之后的状态,事务不会识别中间状态的数据。这称为可串行性,因为它能够重新装载起始数据,并且重播一系列事务,以使数据结束时的状态与原始事务执行的状态相同。
持久性:事务完成之后,它对于系统的影响是永久性的。该修改即使出现系统故障也将一直保持。
语法步骤:
例:SET @errorSum=@errorSum+@@error
SET IMPLICIT_TRANSACTIONS { ON | OFF }
如果设置为 ON,SET IMPLICIT_TRANSACTIONS 将连接设置为隐式事务模式。如果设置为 OFF,则使连接恢复为自动提交事务模式。
select * from bank
--使用事务
begin transaction
declare @error int
set @error = 0
update bank set balance=balance-1000 where cid='0001'
set @error = @error + @@error
update bank set balance=balance + 1000 where cid='0002'
set @error = @error + @@error
if @error != 0
rollback transaction
else
commit transaction
go
select * from bank
2. 存储过程的简单操作
执行速度更快 – 在数据库中保存的存储过程SQL语句都是编译过的
允许模块化程序设计 – 类似方法的复用
提高系统安全性 – 防止SQL注入
减少网络流通量 – 只要传输 存储过程的名称
系统存储过程:
由系统定义,存放在master数据库中
名称以“sp_”开头或”xp_”开头,自定义的存储过程可以以usp_开头
创建自定义存储过程:
CREATE PROC[EDURE] 存储过程名
@参数1 数据类型=默认值,
@参数n 数据类型=默认值OUTPUT
AS
SQL语句
无参数的存储过程调用:
有参数的存储过程两种调用法:
参数有默认值时:
create proc usp_GetAreaPage
@PageIndex int =3, --当前页码
@PageSize int = 10 --页容量
as
begin
select * from (select row_number() over (order by BID) as rownum, * from [BOOK].[dbo].[book]) as t
where t.rownum between @pageSize*(@PageIndex-1) and @pageSize*@pageIndex
end
exec usp_GetAreaPage 1,2
3. 触发器
触发器常用语法:
CREATETRIGGERtriggerNameON表名
after(for)(for与after都表示after触发器) | instead of
UPDATE|INSERT|DELETE(insert,update,delete)
AS
begin
…
end
例如: 触发器 - 插入
CREATE TRIGGER tr_updateStudent ON score --相当于外键检查约束
after INSERT -- 后置的新增触发器
AS
Begin
declare @sid int,@scoreid int--定义两个变量
select @sid = sId,@ scoreid=id from inserted--获得新增行的数据
if exists(select * from student where sid=@sid)--判断分数学员是否存在
print ‘插入成功’
else --如果不存在,则把更新增成功的分数记录给删除掉
delete from score where sid = @scoreId
End
Insert into score (studentId,english) values(100,100)
插入和删除 触发器:
drop table Records
create table Records
(
rId int identity(1,1) primary key,
rType int , -- 1存钱 -1 取钱
rMoney money,
userId char(4)
)
select * from bank
--创建触发器
create trigger tr_Records
on Records
for insert
as
declare @type int,@money money,@id char(4)
select @type = rType,@money=rMoney,@id=userId from inserted
update bank set balance = balance + @money*@type
where cId = @id
--当插入数据的时候就会引发触发器
insert into Records values(-1,10,'0002')
select * from Records
create trigger tr_del
on student
for delete
as
delete from score where studentId in (select sid from deleted)
触发器使用建议:
索引:
相当于字典中的目录
加快查询速度
在执行增删改的时候降低了速度
聚集索引:
相当于字典中拼音目录
拼音目录的顺序和数据的顺序是一致的
一个表中只能有一个聚集索引。
索引的排序顺序与表中数据的物理存储位置是一致的,一般新建主键列后回自动生成一个聚集索引。
非聚集索引(逻辑上的排序):
一个表中可以有多个非聚集索引。
相当于字典中笔画目录
笔画目录的顺序和数据是无关的
//建索引的目的是为了加快查询速度。
//索引之所以能加快查询速度是因为索引对数据进行了排序。
//建索引应该建在某个列上,就是说要对某个列排序,
//这是,如果用用户执行一条查询语句,where条件中包含了建索引的那列,那么这时,采用用到索引,否则,不会使用索引。Name=数据(用索引),namelike ‘%aa%’(不用索引)
=======非聚集索引=============
CREATENONCLUSTERED INDEX IX_SalesPerson_SalesQuota_SalesYTD ONSales.SalesPerson (SalesQuota,SalesYTD); GO
====创建唯一非聚集索引=============
CREATEUNIQUE INDEX AK_UnitMeasure_Name ONProduction.UnitMeasure(Name);GO
=======创建聚集索引=================
CREATETABLE t1 (a int, bint, cAS a/b); CREATE UNIQUE CLUSTERED INDEX Idx1 ON t1(c); INSERT INTO t1 VALUES (1,0);
最后
以上就是孤独自行车为你收集整理的数据库中事物、存储过程、触发器、索引、临时表 的简单应用的全部内容,希望文章能够帮你解决数据库中事物、存储过程、触发器、索引、临时表 的简单应用所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复