数据库触发器与事务

2008.10.13 / 标签: ,,,,,,, / 分类: 未分类

当对数据库中的一张表进行操作且同时又要对与之相关的其他表的数据进行修改时,要如何操作呢?一种方法是写出每一个操作的SQL语句,然后逐一执行。但是,如果碰到银行转账这种业务,我们需要先从A帐户扣钱,然后给B帐户加钱。若A帐户扣钱成功但是B帐户加钱失败,我们还得再多写一条SQL用以在失败的时候再把A的钱给加上。这样太麻烦而且需要我们在底层写很多数据库操作代码,容易出错也不安全。
此时就可以用触发器与事务来处理,当对A帐户进行修改时自动触发执行对B帐户的修改,并且当其中任何一个操作失败时,事务会自动回滚,取消之前所有的操作,这样就无形的减少了不少代码及安全隐患。
我所做的项目就有这样的一个需要:有一个文章表和一个文章类别表,文章类别表中有个字段用于存储该类别下的文章数量。所以,增加或删除一篇文章同时需要对类别表进行修改,只需要使用如下的代码创建一个触发器即可。

 
  1. CREATE TRIGGER trig_Article_Ins–开始创建触发器
  2. ON dbo.blog_Article–指明要对哪个表创建
  3. FOR INSERT–创建INSERT类型的触发器
  4. AS
  5. BEGIN TRANSACTION–开始事务
  6.     DECLARE @cateId int,@errorSum int–声明变量,分别用于存储类别ID和错误统计
  7.     SET @errorSum = 0–错误统计初值为0
  8.     SELECT @cateId=log_CateID FROM inserted–查到新插入的文章的类别ID
  9.     SET @errorSum=@errorSum+@@ERROR–累计错误
  10.     UPDATE blog_Category SET cate_Count=cate_Count+1 WHERE cate_ID=@cateId–对相应的表进行更新
  11.     SET @errorSum=@errorSum+@@ERROR–累计错误
  12.     
  13.     IF @errorSum <> 0–若执行期间出现错误则回滚,否则提交事务
  14.         BEGIN
  15.             print ‘创建失败,回滚事务!’
  16.             ROLLBACK TRANSACTION
  17.         END
  18.     ELSE
  19.         BEGIN
  20.             print ‘创建成功,提交事务!’
  21.             COMMIT TRANSACTION
  22.         END
  23. GO

 

另外,使用这个还有另外一个原因:好久没有写过这些东西了,该练练手了。所以,今天在编写这个触发器的时候还小查了一下帮助手册。

 

列名或所提供值的数目与表定义不匹配

2008.10.12 / 标签: ,,,,, / 分类: 未分类
Sofa

今天在操作数据库的时候报出了一个错误:java.sql.SQLException: [Microsoft][ODBC SQL Server Driver][SQL Server]插入错误: 列名或所提供值的数目与表定义不匹配。怎么可能呢,我昨天对同样的数据库同样的表执行同样的操作时候是没有问题的啊!开玩笑呢吧!开始抓虫…
首先从程序的代码入手,顺便用企业管理器打开对应的表,检查了一下字段数是对的呀,难道代码中的SQL我拼错了?给代码中又加了句System.out.println(sql)。

 
  1. public static boolean createCategory(CategoryBean cate)
  2.     {
  3.         String sql = "INSERT INTO blog_Category VALUES(‘"+cate.getCateName()+"’,"+cate.getCateCount()+")";
  4.         dbc = new DataSource();
  5.         System.out.println(sql);
  6.         stmt = dbc.getPreparedStatement(sql);
  7.         return dbc.executeUpdate(stmt);
  8.     }

接着再次执行了一下还是报错:
INSERT INTO blog_Category VALUES(‘测试’,0)
java.sql.SQLException: [Microsoft][ODBC SQL Server Driver][SQL Server]插入错误: 列名或所提供值的数目与表定义不匹配。
从输出的结果来看,我的SQL是绝对没有拼错的!OK,静下心来整理一下思路:
假如数据库中有张表,此表包含3个字段且均为必填,如果有一个字段是自增类型的标识列,那么我们写SQL的时候就不需要管它。反之,在插入一条数据的时候就必须有这一字段的数据,否则就会报出这样的错误。
OK,想明白了,也知道自己的SQL是的确没有拼错,那么问题就是出在我的标识列上了,仔细检查了一下这张表的主键列,结果发现竟然忘记设置它为标识列并令其自增了。这时突然想起来我昨天貌似把数据库重新覆盖过一次,用来覆盖的那个数据库是还没有设计完整的!我狂晕~
不过,其实遇到问题遇到错误是件好事,从中可以学到很多知识,没有问题才是最大的问题!切记:遇到问题时不要头大,或许当时有点烦躁,但一定要冷静一下,静下心来仔细想想为什么会出现这样的问题,你会发现原来问题如此简单!

解决SQL 2005 中不允许远程连接的方法

2008.09.27 / 标签: ,, / 分类: 未分类

今天在SQL2000的基础上又装了SQL2005结果发现SQL2005不能使用SA登陆只能集成认证方式登陆,郁闷了~,找了点资料来按部就班搞定。

1、打开外围应用配置器——》服务和连接的外围应用配置器,作如下配置后重启服务:

 

2、打开SQL Server Configuration Manager——》SQLEXPRESS的协议,启用TCP/IP

 

3、右键点击TCP/IP——》属性——》IP地址,作如下设置并重启服务

 

注:IPALL中的TCP动态端口设置为0,系统会自动成2391

4、使用SQL Server Management Studio连接数据库
 在只装了SQL2005的情况下使用IP直接连接就行了,不需要加SQLEXPRESS,如127.0.0.1即可
 若同时装了SQL2000和SQL2005在需要连接2005的时候要在IP地址后面加上SQLEXPRESS,如127.0.0.1\SQLEXPRESS

SQL Server数据库中函数的使用方法

2008.05.30 / 标签: ,,,, / 分类: 未分类
Sofa

1. 由于update里不能用存储过程,并且由于根据更新表的某些字段还要进行计算。所以很多人采用的是游标的方法,在这里我们可以用函数的方法实现。
函数部分:
CREATE FUNCTION [DBO].[FUN_GETTIME] (@TASKPHASEID INT)
RETURNS FLOAT AS
BEGIN
DECLARE
@TASKID INT,
@
HOUR FLOAT,
@PERCENT
FLOAT,
@
RETURN FLOAT
IF
@TASKPHASEID IS NULL
BEGIN
RETURN
(0.0)
END
SELECT
@TASKID=TASKID,@PERCENT=ISNULL(WORKPERCENT,0)/100
FROM TABLETASKPHASE
WHERE ID=@TASKPHASEID
SELECT @HOUR=ISNULL(TASKTIME,0) FROM TABLETASK
WHERE ID=@TASKID
SET @RETURN=@HOUR*@PERCENT
RETURN (@RETURN)
END
调用函数的存储过程部分:
CREATE PROCEDURE [DBO].[PROC_CALCCA]
@ROID
INT
AS
BEGIN
DECLARE
@CA FLOAT
UPDATE
TABLEFMECA
SET
Cvalue_M= ISNULL(MODERATE,0)*ISNULL
(FMERATE,
0)*ISNULL(B.BASFAILURERATE,0)*[DBO].[FUN_GETTIME](C.ID)
FROM TABLEFMECA ,TABLERELATION B,TABLETASKPHASE C
WHERE ROID=@ROID AND TASKPHASEID=C.ID AND B.ID=@ROID
SELECT @CA=SUM(ISNULL(Cvalue_M,0)) FROM TABLEFMECA WHERE ROID=@ROID
UPDATE TABLERELATION
SET CRITICALITY=@CA
WHERE ID=@ROID
END
GO
2. 我们要根据某表的某些记录,先计算后求和,因为无法存储中间值,平时我们也用游标的方法进行计算。但SQL Server 2000里支持。
SUM ( [
ALL DISTINCT ] eXPression )
expression
是常量、列或函数,或者是算术、按位与字符串等运算符的任意组合。因此我们可以利用这一功能。
函数部分:  
CREATE FUNCTION [DBO].[FUN_RATE] (@PARTID INT,
@ENID
INT,@SOURCEID INT, @QUALITYID INT,@COUNT INT)
RETURNS FLOAT AS
BEGIN
DECLARE
@QXS FLOAT, @G FLOAT, @RATE FLOAT
IF
(@ENID=NULL) OR (@PARTID=NULL) OR (@SOURCEID=NULL) OR (@QUALITYID=NULL)
BEGIN
RETURN
(0.0)
END
SELECT
@QXS= ISNULL(XS,0) FROM TABLEQUALITY WHERE ID=@QUALITYID
SELECT @G=ISNULL(FRATE_G,0) FROM TABLEFAILURERATE
WHERE (SUBKINDID=@PARTID)
AND( ENID=@ENID)
AND ( DATASOURCEID=@SOURCEID)
AND( ( (ISNULL(MINCOUNT,0)<=ISNULL(@COUNT,0))
AND ( ISNULL(MAXCOUNT,0)>=ISNULL(@COUNT,0)))
OR(ISNULL(@COUNT,0)>ISNULL(MAXCOUNT,0)))
SET @RATE=ISNULL(@QXS*@G,0)
RETURN (@RATE)
END
调用函数的存储过程部分:
CREATE PROC PROC_FAULTRATE
@PARTID
INTEGER, @QUALITYID INTEGER,@SOURCEID INTEGER,
@COUNT
INTEGER, @ROID INT, @GRADE INT,@RATE FLOAT=0 OUTPUTAS
BEGIN
DECLARE
@TASKID INT
SET
@RATE=0.0
SELECT @TASKID=ISNULL(TASKPROID,-1) FROM TABLERELATION
WHERE ID=(SELECT PID FROM TABLERELATION WHERE ID=@ROID)
IF (@TASKID=-1) OR(@GRADE=1) BEGIN
SET
@RATE=0
RETURN
END
SELECT
@RATE=SUM([DBO].[FUN_RATE]
(@PARTID,ENID,@SOURCEID, @QUALITYID,@COUNT) *ISNULL(WORKPERCENT,
0)/100.0)
FROM TABLETASKPHASE
WHERE TASKID=@TASKID
END
GO

无觅相关文章插件,快速提升流量