读书人

存储过程是怎么执行的

发布时间: 2012-08-22 09:50:34 作者: rapoo

存储过程是如何执行的?
有这样的数据库表,两个字段,id及xm。

id自动编号,xm可以为空。

比如有如下若干记录

SQL code
id         xm1          张三2          李四3          王五4          杨柳


由于id自动编号,一旦删除某条记录,以后即使再插入记录,也不会是 相同的 id 号。

为此,我采用的删除逻辑是将xm字段的值改为null,以后在插入新记录时先看看是否有xm是null的记录,若有就使用该记录,若不存在,再真正执行插入记录库的操作,对应的存储过程如下:
SQL code
ALTER PROCEDURE [dbo].[cs]     @xm varchar(50)ASBEGIN    SET NOCOUNT ON;    declare @id int    select @id=id from gen where xm is null    if @id is null        begin            insert into gen (xm) values (null)            select @id=SCOPE_IDENTITY()        end     update gen set xm=@xm where id=@id    select @idEND


现在我担心的是多人通过浏览器访问存储过程添加姓名时,是否会将新的数据更新到同一条xm是 null的记录上?

若存储过程在执行时是依次的,比如A用户先执行,完后再B用户,...,这样的话,应该是没问题的。

求高人指点迷津,O(∩_∩)O谢谢~~~

[解决办法]
楼主为何不直接删掉,id必须要连续吗?不连续应该不会影响查询或其他什么的。
[解决办法]
在没有并发的时候是没有问题的,并发的时候可以加锁的。

但是我不建议这样来处理。
删除了就是xm为null,那就直接删除了留着也没有什么用。

前面的id就是个唯一标示没有必要连续。

为了显示上的连续序号,用row_number() 加个序号就可以了。


[解决办法]
SQL code
declare @t table(id int identity(1,1),[xm] varchar(2))insert @tselect 'aa' union allselect 'bb' union allselect 'cc' union allselect 'dd' union allselect 'ee' union allselect 'ff'delete from @t where xm in ('bb','dd')select row_number() over (order by id) as nid,* from @t/*nid                  id          xm-------------------- ----------- ----1                    1           aa2                    3           cc3                    5           ee4                    6           ff*/
[解决办法]
你的担心当然存在,数据库是并发的,查询和修改之间有时间差,所以可能出现更新同一条数据而造成更新丢失。

解决方法:
1、ID号不连续一半是可以接受的,你现在找回原来的号的设计有点多余,最好改变设计,减少出错机会
2、如果是明确需求,可以用事务控制,注意用事务的代价是损失性能

SQL code
ALTER PROCEDURE [dbo].[cs]     @xm varchar(50)ASBEGIN    SET NOCOUNT ON;    declare @id int    SET XACT_ABORT ON    BEGIN TRANSACTION    select TOP 1 @id=id from gen WITH (UPLOCK) where xm is null    if @id is null        begin            insert into gen (xm) values (null)            select @id=SCOPE_IDENTITY()        end     update gen set xm=@xm where id=@id    COMMIT TRANSACTION    select @idEND
[解决办法]
直接删除,按照id的排序在查询时做一个序号列都是可行的,或者楼主可以将这个表单独做一个单表视图。

SQL code
--sql2005create view tbviewasselect id,xm,rid=row_number() over (order by id)from tb--sql2000create view tbviewasselect id,xm,rid=(select count(*) from tb where id <= t.id)from tb t
[解决办法]
现在ID基本上除了个主键,其他的没有什么意义了吧
[解决办法]
id 连续不连续都无所谓的,你为了让它强行一致,付出的代价太大了。
就跟6楼说的,必须的锁表才能控制并发不冲突,但是这样很容易block
[解决办法]
探讨

SQL code

ALTER PROCEDURE [dbo].[cs]
@xm varchar(50)
AS
BEGIN
SET NOCOUNT ON;
declare @id int
select top 1 @id=id from gen where xm is null
waitfor delay '00:00:10'
if @id ……

------解决方案--------------------


并发控制一定会出问题的。所以直接删除了最好;之后每次只需要做一次insert。
否则每次你的事务,很多时候是3次,先select,然后insert,然后再update,人家一件事情搞定,你3件事情搞定,不累啊!

读书人网 >SQL Server

热点推荐