从存储过程插入SQL Server唯一行不起作用

时间:2012-02-02 23:21:00

标签: sql-server ajax perl stored-procedures locking

我的Intranet上有一个页面,它向perl CGI脚本提交请求。该脚本依次调用SQL Server DB上的存储过程,以检查是否存在具有某些属性的对象。如果是,则storproc返回乐器的id,如果不是,则创建一个新乐器并返回该乐器的id。存储过程创建一个事务,并在insert语句中使用with (TABLOCKX)。为了用户友好性,当所述用户同时提交一堆请求时,网页异步地将请求提交给perl脚本。我认为当提交的所有请求都需要一个新的工具时,第一个命中storproc会运行,锁定表,创建新仪器,释放锁,然后随后对storproc的调用会知道新仪器并使用它。我在实践中看到的是,会有几个请求创建新工具,其余的将使用最新的工具。我尝试在客户端使用setTimeout来隔离请求,但这似乎没有什么区别。关于我可能做错的任何想法?

以下是存储过程的代码:

CREATE PROCEDURE [dbo].[CreateFutures]
@code varchar(5),
@month int,
@year int,
@currency varchar(3)
AS
BEGIN
SET NOCOUNT ON;
BEGIN TRANSACTION

declare @ticker varchar(7)
declare @yearCode char(1)
declare @res as Table (id int)
declare @n as int

set @yearCode = convert(char(1), @year % 10)

set @ticker = (
    select @code + futures + @yearCode
    from FuturesMonthCodes 
    where month = @month
)

insert into @res
select top 1 instrument
from InstrumentFutures // This is a view that joins InstrumentText and InstrumentNumber data
where ticker = @ticker
and code = @code
and month = @month
and year = @year
and currency = @currency
order by instrument

set @n = (select COUNT(id) from @res)

if @n = 0
    begin
        print 'Creating Future'
        declare @id int
        declare @stamp datetime
        set @stamp = CURRENT_TIMESTAMP
        insert into Instrument with (TABLOCKX) (insertTime) values (@stamp)
        set @id = (select SCOPE_IDENTITY());

        insert into InstrumentText      (instrumentId, name, value) values (@id, 'type',    'futures')
        insert into InstrumentText      (instrumentId, name, value) values (@id, 'ticker',  @ticker)
        insert into InstrumentText      (instrumentId, name, value) values (@id, 'code',    @code)
        insert into InstrumentText      (instrumentId, name, value) values (@id, 'currency',@currency)
        insert into InstrumentNumber    (instrumentId, name, value) values (@id, 'month',   @month)
        insert into InstrumentNumber    (instrumentId, name, value) values (@id, 'year',    @year)

        insert into @res (id) values (@id)
    end
commit transaction

if @n = 0 --instrument created
    select top 1 id, 1 from @res order by id
else --returning existing instrument
    select top 1 id, 0 from @res order by id
END

1 个答案:

答案 0 :(得分:1)

这是比perl更多的SQL问题。

假设3个脚本试图在同一时间运行此存储过程。

第一次执行并锁定表。其他人等待表解锁,但是当锁定结束时他们没有重新读取数据,所以他们使用旧数据。

如果您的存储过程进行了选择,则必须在锁定消失后重新运行它。

此致