3

我正在考虑创建一个由多个进程访问的存储过程,并想知道在这两种解决方案之间,哪个更好还是有第三种解决方案?

目标是在字段status中找到具有最大值的记录。字段状态包含十进制值,但定义为 varchar。一旦找到合适的记录,然后更新相同的记录(存储过程只能更新一条记录)。

存储过程将以 select 语句的形式返回 cusip。

解决方案:01

Declare @Cusiptable(Cusip varchar(100));
UPDATE  cusiptbl
SET processingdate = GetDate() ,
Status = 'In Progress',
batchid = @batchid_given,
Output Inserted.Cusip into @Cusiptable
From 
(
 select top(1) Cusip from cusiptbl  where batchid = -1 
 order by cast(status as decimal(18,4)) desc  
) Seconds
where cusiptbl.cusip = Seconds.cusip

select Cusip from @Cusiptable

解决方案02:

select top(1)  @CusipToBeUpdated = Cusip from cusiptbl 
        with (UPDLOCK)
        where batchid = -1 
        order by 
        (case when isnumeric(status) = 1 then 
            cast(status as decimal(18,7)) end) 
            desc

-- Update the status to given batchid and status as 'In Progress'
UPDATE  cusiptbl 
SET batchid = @batchid_given,
    processingdate = GetDate() ,
    Status = 'In Progress'
    where cusiptbl.cusip= @CusipToBeUpdated 
            and batchid = -1

 Select @CusipToBeUpdated Cusip
4

1 回答 1

0

order by cast(status as decimal(18,4))在评估非数字值时,第一个查询将失败。

重写它使用isnumeric(status) = 1以防止错误:

From 
(
 select top(1) Cusip from cusiptbl  
 where batchid = -1  AND isnumeric(status) = 1
 order by cast(status as decimal(18,4)) desc  
) Seconds

假设事务隔离级别是读取提交或更高,这两种解决方案都应该工作。

从 varchar 转换为 numeric 会阻止使用索引(如果有的话),如果您的表很大,那么您可以考虑向表中添加一个虚拟列,例如:

create table cusiptbl(
  ......
  status varchar(50),
  status_numeric as case when isnumeric(status) = 1 then 
            cast(status as decimal(18,7)) else null end
)

并在此虚拟​​列上创建索引:

create index num_status on cusiptbl( status_numeric )

或者可能是一个复合索引(因为您的查询使用 batchid=-1 条件过滤行,然后按状态对选定的行进行排序):

create index num_status_batch on cusiptbl( batchid, status_numeric )


然后重写查询并使用其中的虚拟列,例如:

From 
(
 select top(1) Cusip from cusiptbl 
 where batchid = -1 and status_numeric is not null
 order by status_numeric desc  
) Seconds
于 2013-08-15T09:27:49.940 回答