- 浏览: 426228 次
- 性别:
- 来自: 深圳
文章分类
最新评论
-
Glogo:
楼主您好,我在试验您的代码的时候发现新开的三个子线程并没有一直 ...
java 高并发 ReentrantLock -- 可重入的锁 -
univasity:
最近发觉也被限速了,投诉一下就好一会~~ 看来明天又要和电信M ...
ADSL上网速度慢 都是帐号限速惹的祸 -
liuyuanhui0301:
java 高并发 ReentrantLock -- 可重入的锁 -
dang_java:
呵.很好的说明文档.
JXTA技术与应用发展 -
helloqidi:
谢谢,学习了
SQL中exists和in的区别
1、触发器。
定义: 何为触发器?在SQL Server里面也就是对某一个表的一定的操作,触发某种条件,从而执行的一段程序。触发器是一个特殊的存储过程。
常见的触发器有三种:分别应用于Insert , Update , Delete 事件。(SQL Server 2000定义了新的触发器,这里不提)
我为什么要使用触发器?比如,这么两个表:
Create Table Student( --学生表
StudentID int primary key, --学号
....
)
Create Table BorrowRecord( --学生借书记录表
BorrowRecord int identity(1,1), --流水号
StudentID int , --学号
BorrowDate datetime, --借出时间
ReturnDAte Datetime, --归还时间
...
)
用到的功能有:
1.如果我更改了学生的学号,我希望他的借书记录仍然与这个学生相关(也就是同时更改借书记录表的学号);
2.如果该学生已经毕业,我希望删除他的学号的同时,也删除它的借书记录。
等等。
这时候可以用到触发器。对于1,创建一个Update触发器:
Create Trigger truStudent
On Student
for Update
-------------------------------------------------------
--Name:truStudent
--func:更新BorrowRecord 的StudentID,与Student同步。
--Use :None
--User:System
--Author: 懒虫 # SapphireStudio (www.chair3.com)
--Date : 2003-4-16
--Memo : 临时写写的,给大家作个Sample。没有调试阿。
-------------------------------------------------------
As
if Update(StudentID)
begin
Update BorrowRecord
Set br.StudentID=i.StudentID
From BorrowRecord br , Deleted d ,Inserted i
Where br.StudentID=d.StudentID
end
理解触发器里面的两个临时的表:Deleted , Inserted 。注意Deleted 与Inserted分别表示触发事件的表“旧的一条记录”和“新的一条记录”。
一个Update 的过程可以看作为:生成新的记录到Inserted表,复制旧的记录到Deleted表,然后删除Student记录并写入新纪录。
对于2,创建一个Delete触发器
Create trigger trdStudent
On Student
for Delete
-------------------------------------------------------
--Name:trdStudent
--func:同时删除 BorrowRecord 的数据
--Use :None
--User:System
--Author: 懒虫 # SapphireStudio (www.chair3.com)
--Date : 2003-4-16
--Memo : 临时写写的,给大家作个Sample。没有调试阿。
-------------------------------------------------------
As
Delete BorrowRecord
From BorrowRecord br , Delted d
Where br.StudentID=d.StudentID
从这两个例子我们可以看到了触发器的关键:A.2个临时的表;B.触发机制。
这里我们只讲解最简单的触发器。复杂的容后说明。
事实上,我不鼓励使用触发器。触发器的初始设计思想,已经被“级联”所替代。
2.游标
在SQL 2000之前,游标可谓是SQL Server心中的痛: 老牛般的速度(CPU),河马般的胃口(内存)。可你却不能不用他。
什么叫游标呢?说白了就是像高级语言一样,是存放数据集,并逐条访问的一种机制。
比如在Delphi里面,要实现类似于这样的功能:(呵呵,不好意思,我只会Delphi,所以只能举一个Delphi的例子)
//这是一段Delphi的源代码
adoDataSet1.Close;
adoDataSet1.CommandText:=\' Select * From Student order by StudentID \';
adoDataSet1.Open;
While Not adoDAtaSet1.Eof Do
Begin
YourVar:=adoDAtaSet1.FieldByName(\'StudentID\').AsInteger;
DoSomeThing();
....
adoDataSet1.Next;
End
在SQL Server 并没有很好的数据逐条访问机制,如果有,那就是游标。
还是举例子:
对于表
Create Table BorrowRecord( --学生借书记录表
BorrowRecord int identity(1,1), --流水号
StudentID int , --学号
StudentFeeID int , --费用结算号 (外键)
BorrowDate datetime, --借出时间
ReturnDAte Datetime, --归还时间
Fee Money --借书费用
...
)
Create Table StudentFee( --学生费用结算表
StudentFeeID int primarykey , --费用结算号 (主键)
StudentID int , --学号
BorrowBookAllFee Money, --所有借书总费用
...
)
两者关系为多对一的关系,关联字段为StudentFeeID
由于某种原因StudentFee表的数据遭到了破坏,我想StudentFee循环一遍将“所有借书总费用”重算 。
-----------------------------------------------------------------------
-------------------------------------------------------
--Name:一部分代码
--func:更新学生借书总费用
--Use :
--User:
--Author: 懒虫 # SapphireStudio (www.chair3.com)
--Date : 2003-4-16
--Memo : 临时写写的,给大家作个Sample。没有调试阿。
-------------------------------------------------------
--声明一个游标
Declare curStudentFee Cursor
for
Select StudentFeeID From StudentFee
--声明两个费用变量
Declare @mBorrowBookAllFee Money --总费用
Declare @iStudentFeeID Int --借书结算号
--初始化
Set @mBorrowBookAllFee=0
Set @iStudentFeeID=0
--打开游标
Open curStudentFee
--循环并提取记录
Fetch Next From curStudentFee Into @iStudentFeeID
While ( @@Fetch_Status=0 )
begin
--从借书记录中计算某一学生的借书总记录的总费用
Select @mBorrowBookAllFee=Sum(BorrowBookAllFee)
From BorrowRecord
Where StudentFeeID=@iStudentFeeID
--更新到汇总表。
Update StudentFee Set BorrowBookAllFee=@mBorrowBookAllFee
Where StudentFeeID=@iStudnetFeeID
Fetch Next From curStudentFee Into @mFee
end
--关闭游标
Close curStudentFee
--释放游标
Deallocate curStudentFee
-----------------------------------------------------------------------
关注游标的要点:1、声明、打开、关闭、释放 ; 2、@@Fetch_Status 游标提取状态标志,0表示正确
这里,我也要提到,我不鼓励使用游标。更多的情况下,在SQL 2000 里面 ,函数已经能够实现绝大部分游标的功能。
好累,好不容易算是将1、2点讲完,算是上部分把。后面的几点等会再说了……:(:(。
大家给点鼓励?
--------------------------------------------------------------------------------
-- 作者:流星翩翩
-- 发布时间:2005-7-25 18:17:26
--
这里决定把4与3调换一下,先讲解4(存储过程,以下用sp来简称;函数,以下用fn来简称)
4、存储过程。
存储过程是数据库编程里面最重要的表现方式了。
呵呵,这里我要提到上次说道的:我拒绝使用触发器。这里我要开始猛批一顿触发器了。
在SQL 2000里,说实话,我实在找不出触发器可以存在的理由。回忆一下:触发器是一种特殊的存储过程。它在一定的事件(Insert,Update,Delete 等)里自动执行。我建议使用sp和级联来代替触发器。
在SQL 7 里面,触发器通常用于更新、或删除相关表的数据,以维护数据的完整。SQL 7里面,没有级联删除和级联修改的功能。 只能建立起关系。既然SQL 2000里面提供了级联,那么触发器就没有很好的存在理由。更多的情况下是作为一个向下兼容的技术而存在。
当然,也有人喜欢把触发器作为处理数据逻辑,甚至是业务逻辑的自动存储过程。 这种方法并不足取。这里列举以下使用触发器的一些坏处:
a、“地下”运行 。
触发器没有很好的调试、管理环境。调试一段触发器,要比调试一段sp更耗费时间与精力。
b、类似于goto语句。(过分自由的另外一个说法是:无政府主义!)
一个表,可以写入多个触发器,包括同样for Update的10个触发器!同样for Delete的10个触发器。也就是说,你每次要对这个表进行写操作的时候,你要一个一个检查你的触发器,看看他们是做什么的,有没有冲突。
或许,你会很牛B的对我说:我不会做那么傻B的事情,我记得住我做了些什么!3个月以后呢?10个月以后呢?你还会对我说你记得住么?
c、嵌套触发器、递归触发器
你敢说你这么多的触发器中不会存在Table1更新了Table2表,从而触发Table2表更新TAble3,TAble3的触发器再次触发Table1更新Table2…… ??
或许还会发生这种情况:你的程序更新了Table1.Fd1,触发器立马更新Table1.fd1,再次触发事件,触发器再次更新Table1.fd1……
当然,SQL Server可以设置和避免应用程序进入死循环,可是,得到的结果,或许就不是你想要的。
……
我想不出触发器更多的坏处了,因为我早就抛弃了它。算了,不批它了,酸是各人爱好把!我建议使用完全存储过程来实现数据逻辑和事务逻辑!
先讲讲sp的编写格式(我个人的编程习惯)。良好的习惯有助于日后的维护。
Create Proc spBuyBook( --@@存储过程头,包括名字、参数、说明文档
@iBookID int, --书的ID --@@参数
@iOperatorID int --操作员ID
)
------------------------------------------------------- @@说明文档
--Name : spBuyBook @@名字
--func : 购买一本书的业务逻辑 @@存储过程的功能
--Return: 0,正确;-1,没找到该书;-2,更新Book表出错;-3..... @@返回值解释
--Use : spDoSomething,spDoSomething2.... @@引用了那些外部程序,比如sp,fn,vw等
--User : 懒虫 @@该存储过程的使用者
--Author: 懒虫 # SapphireStudio (www.chair3.com) @@作者
--Date : 2003-5-4 @@最后更新日期
--Memo : 临时写写的,给大家作个Sample。没有调试阿。 @@备注
-------------------------------------------------------
As --@@程序开始
begin
Begin Tran --@@激活事务
Exec spDoSomething --@@调用其他sp
if @@Error<>0 --@@判断是否错误
begin
Rollback Tran --@@回滚事务
RaisError (\'SQL SERVER,spBuyBook: 调用spDoSomeThing发生错误。\', 16, 1) with Log --@@记录日志
Return -1 --@@返回错误号
end
.... --更多其他代码
Commit Tran --@@提交事务
end
妈 的我怎么这么背啊我??什么时候不死机,偏偏在这时!!丢了不少……:(:(
下面默哀3分钟……
1……
2……
3……
好了,继续!回忆刚才写的内容ing ……
AA、存储过程的几个要素: a. 参数 b.变量 c.语句 d.返回值 e.管理存储过程
BB、更高级的编程要素: a.系统存储过程 b.系统表 c.异常处理 d.临时表 e.动态SQL f.扩展存储过程 g.DBCC命令
AA.a 参数: 知识要点包括:输入参数,输出参数,参数默认值
Sample:
Create Proc spTest(
@i int =0 , --输入参数
@o int output --输出参数
)
As
Set @o=@i*2 --对输出参数付值
Use the Sample:
Declare @o int
Exec spTest 33,@o output
Select @o --此时@o应该等于33*2=66。
----------------------------------------------------------------------
以上代码没有测试,顺手写写的。希望不会出错:)
--懒虫 # SapphireStudio
精彩世界,尽在3腿软件网(www.chair3.com)!!
-----------------------------------------------------------------------
AA.b 变量:AA.a中已经有声明变量的例子了,就是Declare @o int
AA.c 语句:在Sql Server 中,如果仅仅使用标准SQL语句将是不可想象的,通常认为,标准的SQL 语句就那么几条,如:
Select, Update, Delete
因此,我们需要引入更多更强大的功能,那就是T-SQL语句:
赋值语句:Set
循环语句:While
分支语句:if , Case ( Case语句不能单独使用,与一般高级语言的不同)
一起举个例子吧:
Sample :
Declare @i int
Set @i=0
While @i<100
begin
if @i<=20
begin
Select Case Cast(@i As Float)/2 When (@i/2) then Cast(@i As varchar(3)) + \'是双数\'
else Cast(@i As varchar(3)) + \'是单数\'
end
end
Set @i=@i+1
end
----------------------------------------------------------------------
以上代码判断20之内的单数与双数。
--懒虫 # SapphireStudio
精彩世界,尽在3腿软件网(www.chair3.com)!!
-----------------------------------------------------------------------
AA.d 返回值
Sample:
Create Proc spTest2
As
Return 22
Use the Sample
Declare @i int
Exec @i=spTest2
Select @i
AA.e 管理存储过程: 创建,修改,删除。
分别为:
Create Proc ... , Alter Proc ... , Drop Proc ...
BB、更高级的编程要素: a.系统存储过程 b.系统表 c.异常处理 d.临时表 e.动态SQL f.扩展存储过程 g.DBCC命令
哈哈,以下课程收费!!(玩笑,实际上打算放到后面去讲了。)
3、函数。
函数是SQL 2000的新功能。一般的编程语言都有函数,我就不用解释函数是什么东东了。:)
或许不少朋友会问:我用存储过程不就可以了么,我为什么要使用函数?
这里特别指出的一点:fn可以嵌套在Select语句中使用,而sp不可以。
这里不打算大批特批一番游标了,当然,在我的程序里面,基本抛弃了游标(这里特别说明,是“基本”!因为还是有很多地方费用导游表不可的。),转而采用了fn。游标太消耗资源了。受不了……我快要感动得要流泪了…
fn其实要比sp要简单得多。因为它的不确定性,从而也使他受到了不少的限制。
举个函数的小粒子:
Create Function fnTest ( @i int )
Returns bit
As
begin
Declare @b bit
if (Cast(@i As Float)/2)=(@i/2)
Set @b= 1
else
Set @b= 0
Return @b
end
----------------------------------------------------------------------
以上代码判断@i是单数还是双数。
--懒虫 # SapphireStudio
精彩世界,尽在3腿软件网(www.chair3.com)!!
-----------------------------------------------------------------------
Use the Sample:
Create Table #TT( fd1 int)
Declare @i int
Set @i=0
While @i<=20
begin
Insert Into #tt Values(@i)
Set @i=@i+1
end
Select fd1,
\'是否双数\'=dbo.fnTest(fd1) --在这里调用了函数,注意哈:函数之前一定要加上他的owner.
From #tt
Drop Table #tt
----------------------------------------------------------------------
以上代码虚拟一段数据,然后判断数据表中是单数还是双数。
--懒虫 # SapphireStudio
精彩世界,尽在3腿软件网(www.chair3.com)!!
-----------------------------------------------------------------------
有了sp的编程基础,写fn也就不是什么很难的事情了。刚才我提到了,fn受到限制颇多,这里稍稍列举:
chair1. 只能调用确定性函数,不可以调用不确定函数。 比如,不可以调用GetDate(),以及自己定义的不确定性函数。
chair2. 不可以使用动态SQL 。如:Execute, sp_ExecuteSQL (这是我最痛苦的事情了,痛哭中……)
chair3. 不可以调用扩展存储过程
chair4. 不可以调用Update语句对表进行更新
chair5. 不可以在函数内部创建表(Create TAble ),修改表(Alter TAble)
等等……头脑发昏中……反正稍微一些不可预测后果,无法返回后果的都不能用。
5.事务
什么叫事务? 这些就是数据库特有的术语了。懒虫在这里口头解释:就是把多件事情当做一件事情来处理。也就是大家同在一条船上,要活一起活,要over一起over !
我为什么要使用事务? 俺这里再举个很俗很俗的例子:
俺到银行存钱,于是有这么几个步骤:
1、把钱交给工作人员;2、工作人员填单;3、将单子给我签字;4、工作人员确认并输入电脑。
要是,要是我把钱交给工作人员之后,进行到3我签字了。那哥们突然心脏病发作,over掉了,那,我的钱还没有输入电脑,但我却交了钱又签字确认了,而并没有其他任何记录。我岂不是要亏死了???我的血汗钱啊!赶紧退给我!!
于是,在数据库里产生了这么一个术语:事务(Transaction),也就是要么成功,要么失败,并恢复原状。
还是写程序把:
Create Proc sp我去存款(@M Money , @iOperator Int)
As
Begin
Declare @i int
Begin Tran --激活事务
Exec @i=sp交钱 @m,@iOperator
if @i<>0 --这里一般用系统错误号 @@Error。 我这里为了举例子没有用到。需要根据实际情况。
begin
Rollback Tran --回滚事务
RaisError (\'银行的窗口太少了,我懒得排队,不交了!:( \', 16, 1) with Log --记录日志
Return -1 --返回错误号
end
Exec @i=sp填单 @m,@iOperator
if @i<>0
begin
Rollback Tran --回滚事务
RaisError (\'银行的哥们打印机出了点毛病,打印不出单子来,把钱退回来给我吧??\', 16, 1) with Log
Return -2
end
Exec @i=sp签字 @m
if @i<>0
begin
Rollback Tran --回滚事务
RaisError (\'我 靠?什么烂银行,换了3支笔都写不出水来!!老子不存了!!不签!\', 16, 1) with Log
Return -3
end
Exec @i=sp输入电脑 @m,@iOperator
if @i<>0
begin
Rollback Tran --回滚事务
RaisError (\'什么意思?磁盘空间已满?好了好了,把钱给我,我到旁边的这家银行!\', 16, 1) with Log
Return -4
end
Commit Tran --提交事务
Return 0
End
----------------------------------------------------------------------
以上是伪代码,模拟我去存款的过程。
--懒虫 # SapphireStudio
精彩世界,尽在3腿软件网(www.chair3.com)!!
-----------------------------------------------------------------------
事务的几个要点 Begin Tran , @@Error(我这里没有用到,见上面的注释) , Rollback Tran , Commit Tran。
另:事务可以嵌套使用。这个时候需要命名。请参见sql server online help 。
定义: 何为触发器?在SQL Server里面也就是对某一个表的一定的操作,触发某种条件,从而执行的一段程序。触发器是一个特殊的存储过程。
常见的触发器有三种:分别应用于Insert , Update , Delete 事件。(SQL Server 2000定义了新的触发器,这里不提)
我为什么要使用触发器?比如,这么两个表:
Create Table Student( --学生表
StudentID int primary key, --学号
....
)
Create Table BorrowRecord( --学生借书记录表
BorrowRecord int identity(1,1), --流水号
StudentID int , --学号
BorrowDate datetime, --借出时间
ReturnDAte Datetime, --归还时间
...
)
用到的功能有:
1.如果我更改了学生的学号,我希望他的借书记录仍然与这个学生相关(也就是同时更改借书记录表的学号);
2.如果该学生已经毕业,我希望删除他的学号的同时,也删除它的借书记录。
等等。
这时候可以用到触发器。对于1,创建一个Update触发器:
Create Trigger truStudent
On Student
for Update
-------------------------------------------------------
--Name:truStudent
--func:更新BorrowRecord 的StudentID,与Student同步。
--Use :None
--User:System
--Author: 懒虫 # SapphireStudio (www.chair3.com)
--Date : 2003-4-16
--Memo : 临时写写的,给大家作个Sample。没有调试阿。
-------------------------------------------------------
As
if Update(StudentID)
begin
Update BorrowRecord
Set br.StudentID=i.StudentID
From BorrowRecord br , Deleted d ,Inserted i
Where br.StudentID=d.StudentID
end
理解触发器里面的两个临时的表:Deleted , Inserted 。注意Deleted 与Inserted分别表示触发事件的表“旧的一条记录”和“新的一条记录”。
一个Update 的过程可以看作为:生成新的记录到Inserted表,复制旧的记录到Deleted表,然后删除Student记录并写入新纪录。
对于2,创建一个Delete触发器
Create trigger trdStudent
On Student
for Delete
-------------------------------------------------------
--Name:trdStudent
--func:同时删除 BorrowRecord 的数据
--Use :None
--User:System
--Author: 懒虫 # SapphireStudio (www.chair3.com)
--Date : 2003-4-16
--Memo : 临时写写的,给大家作个Sample。没有调试阿。
-------------------------------------------------------
As
Delete BorrowRecord
From BorrowRecord br , Delted d
Where br.StudentID=d.StudentID
从这两个例子我们可以看到了触发器的关键:A.2个临时的表;B.触发机制。
这里我们只讲解最简单的触发器。复杂的容后说明。
事实上,我不鼓励使用触发器。触发器的初始设计思想,已经被“级联”所替代。
2.游标
在SQL 2000之前,游标可谓是SQL Server心中的痛: 老牛般的速度(CPU),河马般的胃口(内存)。可你却不能不用他。
什么叫游标呢?说白了就是像高级语言一样,是存放数据集,并逐条访问的一种机制。
比如在Delphi里面,要实现类似于这样的功能:(呵呵,不好意思,我只会Delphi,所以只能举一个Delphi的例子)
//这是一段Delphi的源代码
adoDataSet1.Close;
adoDataSet1.CommandText:=\' Select * From Student order by StudentID \';
adoDataSet1.Open;
While Not adoDAtaSet1.Eof Do
Begin
YourVar:=adoDAtaSet1.FieldByName(\'StudentID\').AsInteger;
DoSomeThing();
....
adoDataSet1.Next;
End
在SQL Server 并没有很好的数据逐条访问机制,如果有,那就是游标。
还是举例子:
对于表
Create Table BorrowRecord( --学生借书记录表
BorrowRecord int identity(1,1), --流水号
StudentID int , --学号
StudentFeeID int , --费用结算号 (外键)
BorrowDate datetime, --借出时间
ReturnDAte Datetime, --归还时间
Fee Money --借书费用
...
)
Create Table StudentFee( --学生费用结算表
StudentFeeID int primarykey , --费用结算号 (主键)
StudentID int , --学号
BorrowBookAllFee Money, --所有借书总费用
...
)
两者关系为多对一的关系,关联字段为StudentFeeID
由于某种原因StudentFee表的数据遭到了破坏,我想StudentFee循环一遍将“所有借书总费用”重算 。
-----------------------------------------------------------------------
-------------------------------------------------------
--Name:一部分代码
--func:更新学生借书总费用
--Use :
--User:
--Author: 懒虫 # SapphireStudio (www.chair3.com)
--Date : 2003-4-16
--Memo : 临时写写的,给大家作个Sample。没有调试阿。
-------------------------------------------------------
--声明一个游标
Declare curStudentFee Cursor
for
Select StudentFeeID From StudentFee
--声明两个费用变量
Declare @mBorrowBookAllFee Money --总费用
Declare @iStudentFeeID Int --借书结算号
--初始化
Set @mBorrowBookAllFee=0
Set @iStudentFeeID=0
--打开游标
Open curStudentFee
--循环并提取记录
Fetch Next From curStudentFee Into @iStudentFeeID
While ( @@Fetch_Status=0 )
begin
--从借书记录中计算某一学生的借书总记录的总费用
Select @mBorrowBookAllFee=Sum(BorrowBookAllFee)
From BorrowRecord
Where StudentFeeID=@iStudentFeeID
--更新到汇总表。
Update StudentFee Set BorrowBookAllFee=@mBorrowBookAllFee
Where StudentFeeID=@iStudnetFeeID
Fetch Next From curStudentFee Into @mFee
end
--关闭游标
Close curStudentFee
--释放游标
Deallocate curStudentFee
-----------------------------------------------------------------------
关注游标的要点:1、声明、打开、关闭、释放 ; 2、@@Fetch_Status 游标提取状态标志,0表示正确
这里,我也要提到,我不鼓励使用游标。更多的情况下,在SQL 2000 里面 ,函数已经能够实现绝大部分游标的功能。
好累,好不容易算是将1、2点讲完,算是上部分把。后面的几点等会再说了……:(:(。
大家给点鼓励?
--------------------------------------------------------------------------------
-- 作者:流星翩翩
-- 发布时间:2005-7-25 18:17:26
--
这里决定把4与3调换一下,先讲解4(存储过程,以下用sp来简称;函数,以下用fn来简称)
4、存储过程。
存储过程是数据库编程里面最重要的表现方式了。
呵呵,这里我要提到上次说道的:我拒绝使用触发器。这里我要开始猛批一顿触发器了。
在SQL 2000里,说实话,我实在找不出触发器可以存在的理由。回忆一下:触发器是一种特殊的存储过程。它在一定的事件(Insert,Update,Delete 等)里自动执行。我建议使用sp和级联来代替触发器。
在SQL 7 里面,触发器通常用于更新、或删除相关表的数据,以维护数据的完整。SQL 7里面,没有级联删除和级联修改的功能。 只能建立起关系。既然SQL 2000里面提供了级联,那么触发器就没有很好的存在理由。更多的情况下是作为一个向下兼容的技术而存在。
当然,也有人喜欢把触发器作为处理数据逻辑,甚至是业务逻辑的自动存储过程。 这种方法并不足取。这里列举以下使用触发器的一些坏处:
a、“地下”运行 。
触发器没有很好的调试、管理环境。调试一段触发器,要比调试一段sp更耗费时间与精力。
b、类似于goto语句。(过分自由的另外一个说法是:无政府主义!)
一个表,可以写入多个触发器,包括同样for Update的10个触发器!同样for Delete的10个触发器。也就是说,你每次要对这个表进行写操作的时候,你要一个一个检查你的触发器,看看他们是做什么的,有没有冲突。
或许,你会很牛B的对我说:我不会做那么傻B的事情,我记得住我做了些什么!3个月以后呢?10个月以后呢?你还会对我说你记得住么?
c、嵌套触发器、递归触发器
你敢说你这么多的触发器中不会存在Table1更新了Table2表,从而触发Table2表更新TAble3,TAble3的触发器再次触发Table1更新Table2…… ??
或许还会发生这种情况:你的程序更新了Table1.Fd1,触发器立马更新Table1.fd1,再次触发事件,触发器再次更新Table1.fd1……
当然,SQL Server可以设置和避免应用程序进入死循环,可是,得到的结果,或许就不是你想要的。
……
我想不出触发器更多的坏处了,因为我早就抛弃了它。算了,不批它了,酸是各人爱好把!我建议使用完全存储过程来实现数据逻辑和事务逻辑!
先讲讲sp的编写格式(我个人的编程习惯)。良好的习惯有助于日后的维护。
Create Proc spBuyBook( --@@存储过程头,包括名字、参数、说明文档
@iBookID int, --书的ID --@@参数
@iOperatorID int --操作员ID
)
------------------------------------------------------- @@说明文档
--Name : spBuyBook @@名字
--func : 购买一本书的业务逻辑 @@存储过程的功能
--Return: 0,正确;-1,没找到该书;-2,更新Book表出错;-3..... @@返回值解释
--Use : spDoSomething,spDoSomething2.... @@引用了那些外部程序,比如sp,fn,vw等
--User : 懒虫 @@该存储过程的使用者
--Author: 懒虫 # SapphireStudio (www.chair3.com) @@作者
--Date : 2003-5-4 @@最后更新日期
--Memo : 临时写写的,给大家作个Sample。没有调试阿。 @@备注
-------------------------------------------------------
As --@@程序开始
begin
Begin Tran --@@激活事务
Exec spDoSomething --@@调用其他sp
if @@Error<>0 --@@判断是否错误
begin
Rollback Tran --@@回滚事务
RaisError (\'SQL SERVER,spBuyBook: 调用spDoSomeThing发生错误。\', 16, 1) with Log --@@记录日志
Return -1 --@@返回错误号
end
.... --更多其他代码
Commit Tran --@@提交事务
end
妈 的我怎么这么背啊我??什么时候不死机,偏偏在这时!!丢了不少……:(:(
下面默哀3分钟……
1……
2……
3……
好了,继续!回忆刚才写的内容ing ……
AA、存储过程的几个要素: a. 参数 b.变量 c.语句 d.返回值 e.管理存储过程
BB、更高级的编程要素: a.系统存储过程 b.系统表 c.异常处理 d.临时表 e.动态SQL f.扩展存储过程 g.DBCC命令
AA.a 参数: 知识要点包括:输入参数,输出参数,参数默认值
Sample:
Create Proc spTest(
@i int =0 , --输入参数
@o int output --输出参数
)
As
Set @o=@i*2 --对输出参数付值
Use the Sample:
Declare @o int
Exec spTest 33,@o output
Select @o --此时@o应该等于33*2=66。
----------------------------------------------------------------------
以上代码没有测试,顺手写写的。希望不会出错:)
--懒虫 # SapphireStudio
精彩世界,尽在3腿软件网(www.chair3.com)!!
-----------------------------------------------------------------------
AA.b 变量:AA.a中已经有声明变量的例子了,就是Declare @o int
AA.c 语句:在Sql Server 中,如果仅仅使用标准SQL语句将是不可想象的,通常认为,标准的SQL 语句就那么几条,如:
Select, Update, Delete
因此,我们需要引入更多更强大的功能,那就是T-SQL语句:
赋值语句:Set
循环语句:While
分支语句:if , Case ( Case语句不能单独使用,与一般高级语言的不同)
一起举个例子吧:
Sample :
Declare @i int
Set @i=0
While @i<100
begin
if @i<=20
begin
Select Case Cast(@i As Float)/2 When (@i/2) then Cast(@i As varchar(3)) + \'是双数\'
else Cast(@i As varchar(3)) + \'是单数\'
end
end
Set @i=@i+1
end
----------------------------------------------------------------------
以上代码判断20之内的单数与双数。
--懒虫 # SapphireStudio
精彩世界,尽在3腿软件网(www.chair3.com)!!
-----------------------------------------------------------------------
AA.d 返回值
Sample:
Create Proc spTest2
As
Return 22
Use the Sample
Declare @i int
Exec @i=spTest2
Select @i
AA.e 管理存储过程: 创建,修改,删除。
分别为:
Create Proc ... , Alter Proc ... , Drop Proc ...
BB、更高级的编程要素: a.系统存储过程 b.系统表 c.异常处理 d.临时表 e.动态SQL f.扩展存储过程 g.DBCC命令
哈哈,以下课程收费!!(玩笑,实际上打算放到后面去讲了。)
3、函数。
函数是SQL 2000的新功能。一般的编程语言都有函数,我就不用解释函数是什么东东了。:)
或许不少朋友会问:我用存储过程不就可以了么,我为什么要使用函数?
这里特别指出的一点:fn可以嵌套在Select语句中使用,而sp不可以。
这里不打算大批特批一番游标了,当然,在我的程序里面,基本抛弃了游标(这里特别说明,是“基本”!因为还是有很多地方费用导游表不可的。),转而采用了fn。游标太消耗资源了。受不了……我快要感动得要流泪了…
fn其实要比sp要简单得多。因为它的不确定性,从而也使他受到了不少的限制。
举个函数的小粒子:
Create Function fnTest ( @i int )
Returns bit
As
begin
Declare @b bit
if (Cast(@i As Float)/2)=(@i/2)
Set @b= 1
else
Set @b= 0
Return @b
end
----------------------------------------------------------------------
以上代码判断@i是单数还是双数。
--懒虫 # SapphireStudio
精彩世界,尽在3腿软件网(www.chair3.com)!!
-----------------------------------------------------------------------
Use the Sample:
Create Table #TT( fd1 int)
Declare @i int
Set @i=0
While @i<=20
begin
Insert Into #tt Values(@i)
Set @i=@i+1
end
Select fd1,
\'是否双数\'=dbo.fnTest(fd1) --在这里调用了函数,注意哈:函数之前一定要加上他的owner.
From #tt
Drop Table #tt
----------------------------------------------------------------------
以上代码虚拟一段数据,然后判断数据表中是单数还是双数。
--懒虫 # SapphireStudio
精彩世界,尽在3腿软件网(www.chair3.com)!!
-----------------------------------------------------------------------
有了sp的编程基础,写fn也就不是什么很难的事情了。刚才我提到了,fn受到限制颇多,这里稍稍列举:
chair1. 只能调用确定性函数,不可以调用不确定函数。 比如,不可以调用GetDate(),以及自己定义的不确定性函数。
chair2. 不可以使用动态SQL 。如:Execute, sp_ExecuteSQL (这是我最痛苦的事情了,痛哭中……)
chair3. 不可以调用扩展存储过程
chair4. 不可以调用Update语句对表进行更新
chair5. 不可以在函数内部创建表(Create TAble ),修改表(Alter TAble)
等等……头脑发昏中……反正稍微一些不可预测后果,无法返回后果的都不能用。
5.事务
什么叫事务? 这些就是数据库特有的术语了。懒虫在这里口头解释:就是把多件事情当做一件事情来处理。也就是大家同在一条船上,要活一起活,要over一起over !
我为什么要使用事务? 俺这里再举个很俗很俗的例子:
俺到银行存钱,于是有这么几个步骤:
1、把钱交给工作人员;2、工作人员填单;3、将单子给我签字;4、工作人员确认并输入电脑。
要是,要是我把钱交给工作人员之后,进行到3我签字了。那哥们突然心脏病发作,over掉了,那,我的钱还没有输入电脑,但我却交了钱又签字确认了,而并没有其他任何记录。我岂不是要亏死了???我的血汗钱啊!赶紧退给我!!
于是,在数据库里产生了这么一个术语:事务(Transaction),也就是要么成功,要么失败,并恢复原状。
还是写程序把:
Create Proc sp我去存款(@M Money , @iOperator Int)
As
Begin
Declare @i int
Begin Tran --激活事务
Exec @i=sp交钱 @m,@iOperator
if @i<>0 --这里一般用系统错误号 @@Error。 我这里为了举例子没有用到。需要根据实际情况。
begin
Rollback Tran --回滚事务
RaisError (\'银行的窗口太少了,我懒得排队,不交了!:( \', 16, 1) with Log --记录日志
Return -1 --返回错误号
end
Exec @i=sp填单 @m,@iOperator
if @i<>0
begin
Rollback Tran --回滚事务
RaisError (\'银行的哥们打印机出了点毛病,打印不出单子来,把钱退回来给我吧??\', 16, 1) with Log
Return -2
end
Exec @i=sp签字 @m
if @i<>0
begin
Rollback Tran --回滚事务
RaisError (\'我 靠?什么烂银行,换了3支笔都写不出水来!!老子不存了!!不签!\', 16, 1) with Log
Return -3
end
Exec @i=sp输入电脑 @m,@iOperator
if @i<>0
begin
Rollback Tran --回滚事务
RaisError (\'什么意思?磁盘空间已满?好了好了,把钱给我,我到旁边的这家银行!\', 16, 1) with Log
Return -4
end
Commit Tran --提交事务
Return 0
End
----------------------------------------------------------------------
以上是伪代码,模拟我去存款的过程。
--懒虫 # SapphireStudio
精彩世界,尽在3腿软件网(www.chair3.com)!!
-----------------------------------------------------------------------
事务的几个要点 Begin Tran , @@Error(我这里没有用到,见上面的注释) , Rollback Tran , Commit Tran。
另:事务可以嵌套使用。这个时候需要命名。请参见sql server online help 。
发表评论
-
mysql查询优化之索引类型、最左前缀
2012-03-22 00:42 1089一、什么是索引? 索引用来快速地寻找那些具有特定值的记录, ... -
Checkpoint not Complete
2009-04-30 15:36 1504alter_ORCL.log如下: Wed Jun 25 0 ... -
How to resize redo log file?
2009-04-30 15:33 1069I wrote a script named 'checkRe ... -
Oracle: REDO&UNDO
2009-04-25 13:41 1041在这里会介绍UNDO,REDO ... -
DBCP,数据库断开自动连接的问题及解决方法
2009-04-20 13:34 2721以前公司开发的一个项 ... -
Oracle : How to drop database
2009-04-06 01:05 1037字号: 大大 中中 小小 D:\>set or ... -
执行计划和执行顺序
2009-04-02 17:53 942如果要了解执行计划和执行顺序,必须理解执行计划的 ... -
Oracle timestamp
2009-02-01 10:47 3084select systimestamp from dual s ... -
Oracle日期函数与应用
2009-01-19 16:26 1167相信很多人都有过统计某些数据的经历,比如,要统计财务的情况 ... -
start with ... connect by用法简介
2008-12-22 17:17 1286sql有向图问题期待新解决方案 /************* ... -
START WITH and CONNECT BY in Oracle SQL
2008-12-22 16:55 1302A simple example In the follow ... -
利用伪列算出每个月那几天是星期天(ORACLE)
2008-12-22 16:05 15601.首先我们要用到LEVEL .... CONNE ... -
Oracle层次查询和分析应用在号段选取
2008-12-22 15:33 11241. 问题的提出 在实际工作中,我们常常会碰到号段选取的 ... -
有关Oracle表分区进行(DML)维护后对索引的影响的分析
2008-12-15 14:30 2216今天对数字电视系统的 ... -
Oracle表分区和索引分区精彩汇总
2008-12-15 14:29 1986分区概述 为了简化数据库大表的管理,例如在数据仓库中 ... -
为什么有时Oracle数据库不用索引来查找数据?
2008-12-15 14:24 1257当你运用SQL语言,向数 ... -
怎样成长为一个真正的Oracle DBA
2008-12-15 12:59 934本文网址:http://bbs.bitscn.com/1674 ... -
MYSQL编码问题
2008-12-04 21:56 674一.原理篇Mysql的字符 ... -
ORACEL SQL 性能优化
2008-10-16 15:18 12491. 选用适合的ORACLE优化器 ORACLE的优化器共有 ... -
mysql 的mysql数据库
2008-09-20 17:06 1032授权表的用途: ...
相关推荐
Mysql存储过程、游标、函数调用、事务处理、触发器代码示例,可用作学习参考。
MySQL是世界上最流行的开源关系型数据库管理系统之一,它包含多种功能,如函数、存储过程、触发器和游标,这些功能极大地增强了数据库管理的灵活性和效率。以下是对这些概念的详细解释: 1. **MySQL函数**:MySQL...
此外,存储过程还可以用于实现游标、批量处理、事务管理和并发控制,为数据库应用程序带来更大的灵活性和效率。 在《Oracle触发器与存储过程高级编程》第3版中,读者可以期待学习到以下内容: 1. 触发器的创建、...
综上所述,MySQL中的索引、视图、触发器、游标、事务和存储过程都是高级特性,这些工具可以帮助开发人员更好地管理和操作数据库。通过对这些概念的理解和实践,可以大幅提升数据库应用的性能和可靠性。
它会详细讲解触发器和存储过程的各种高级特性,包括但不限于:触发器的时间线(Before/After)、级联触发、触发器中的事务控制、存储过程的返回值、游标在存储过程中的应用、异常处理机制等。通过阅读这份资料,你将...
存储过程可以包含控制流语句,如IF-ELSE、WHILE循环,以及游标和事务管理,使得复杂的业务逻辑得以实现。执行存储过程时,可以使用EXEC或者sp_executesql函数。 在实际应用中,存储过程和触发器经常协同工作。例如...
这个压缩包“PLSQL操作存储过程、函数、游标、触发器、定时任务等实例SQL脚本.zip”包含了关于如何使用PL/SQL来处理数据库的各种关键概念的实例脚本。下面,我们将详细探讨这些知识点。 1. **存储过程**:存储过程...
【存储过程和触发器】 在数据库管理中,存储过程和触发器是两个重要的概念,它们在数据处理和业务逻辑执行方面发挥着关键作用。在Oracle数据库中,这些特性被广泛用于提高性能、确保数据一致性以及简化复杂的操作...
存储过程、函数和触发器是PL/SQL中的核心概念,它们在数据库管理中扮演着至关重要的角色。 一、存储过程 存储过程是一组预编译的SQL语句和PL/SQL代码,可以视为数据库中的可执行对象。它们允许开发者封装一系列的...
通过学习这些案例,你可以了解如何在实际应用中灵活运用Oracle游标,包括在存储过程、触发器等高级功能中。案例中的7-游标使用很可能是对各种游标操作的具体示例,如打开、关闭、提取数据、循环处理等,有助于加深...
对于Java程序员来说,熟练掌握数据库操作技术,如函数、存储过程和触发器,对于提升系统性能和数据处理效率至关重要。Oracle数据库系统是其中的佼佼者,其强大的功能和稳定性使其成为企业级应用的首选。 1. **函数*...
以上是关于“数据库系统概论——存储过程和触发器.ppt”文档中涉及的主要知识点,包括Transact-SQL编程基础、事务管理、游标、存储过程和触发器的详细介绍。这些内容对于理解和操作SQL Server数据库至关重要,能够...
PL/SQL 代码块可以嵌入到 SQL 语句中,或者作为独立的存储过程、函数或触发器存在。 5. **动手实践** - 首先,了解 Oracle 的基本安装和常用命令至关重要。Oracle 提供不同版本以满足不同需求,例如企业版、标准版...
### Oracle PL/SQL编程 创建存储过程、函数、触发器等 #### 一、PL/SQL 概念回顾 PL/SQL(Procedural Language for SQL)是Oracle数据库中的一种过程化语言,它结合了SQL的强大数据操作能力和传统过程化语言的控制...
根据提供的文件内容,以下是关于存储过程、触发器以及ODBC数据库编程的知识点整理。 知识点一:存储过程概述 存储过程是一组为了完成特定功能的SQL语句集,它在数据库中存储并且编译好,可以被多次调用执行。从文档...
Oracle数据库中的触发器是一种存储过程,它被设计为当特定事件发生时自动执行。这些事件包括数据修改操作,如INSERT、UPDATE或DELETE等。触发器可以确保数据的一致性和完整性,并帮助实现复杂的业务逻辑。 在某些...
总结来说,Oracle 的存储过程和函数提供了强大的机制来实现复杂的业务逻辑,而游标和触发器则进一步增强了数据处理的能力和灵活性。通过合理运用这些特性,开发者可以构建出高效且易于维护的应用程序。