2013-04-11 68 views
-1

使用SQL Server 2008,有三个表,表a,表b和表c。TSQL:获取下一个可用ID

所有具有ID列,但对表a和b的ID列是identity integer,对于表C ID列是varchar

目前存储过程采取的名称PARAM,以下某些逻辑,插入到表格a或表格b中,获得标识,以'A'或'B'作为前缀,然后插入到表格c中。

问题是,表C ID列可能具有重复值,即如果来自表A的标识为2,表C的ID列中可能已经有'A2','A3','A5'编写T-SQL查询以确定表C中的下一个可用值,然后确保相应地更新表A/B?

[更新] 这是当前步骤, 1.取决于输入参数,插入到表A或表B中 2.初始化种子值= @@身份 3.计算ID值插入到表C中通过前缀'A'或将种子值追加'B' 4.通过步骤3的ID值查找表C中的记录匹配,如果未找到任何记录,则插入它,否则将种子值增加1,然后重复步骤3

问题出现在某个值范围内,表C ID中可能存在一个巨大的值块,即现在在表C ID中存在A3000到A500000,如果遵循现有的数据库,数据库查询会非常慢逻辑。需要找出一个逻辑巧妙地获得最小可用数量(没有前缀)

这很难描述,希望这更有意义,我真的很感谢任何帮助提前在此谢谢!

+5

重新设计这将会好得多。这真的不是一个好方法 – RBarryYoung 2013-04-11 20:33:28

+1

如果表A和B中的“ID”确实是“INT IDENTITY” - 它怎么会给你重复?如果你在表C中使用表前缀(A或B)加上表A或B中'ID'列的** unique **值,那么对我来说这似乎是不可能的。 – 2013-04-11 20:35:27

+0

@Tommy Wang,你能编辑你的文章并给我们一个更详细的例子吗? – PowerUser 2013-04-11 21:00:10

回答

1

这应该是关键。简单的自我提取示例将在SSMS中运行。为了以防万一,我甚至做到了这一点。您只需将您的表更改为@Data所在的位置,然后更改标识符字段以替换“ID”。

declare @Data Table (Id varchar(3)); 

insert into @Data values ('A5'),('A2'),('B1'),('A3'),('B2'),('A4'),('A1'),('A6'); 

With a as 
    (
    Select 
     ID 
    , cast(right(Id, len(Id)-1) as int) as Pos 
    , left(Id, 1) as TableFrom 
    from @Data 
    ) 
select 
    TableFrom 
, max(Pos) + 1 as NextNumberUp 
from a 
group by TableFrom 

编辑:如果你想不用担心生产数据,你可以添加最后一部分修改我写的:

Select 
    TableFrom 
, max(Pos) as LastPos 
into #Temp 
from a 
group by TableFrom 

select TableFrom, LastPos + 1 
from #Temp 

不管,如果这是生产环境下,你将不得不打的一部分它在某个时间获取数据。如果数据集不是太大,只是varchar(256)或更少,只有500万行或更少,则可以将整个列从tableC转储到临时表。诚实地查询性能与进口数据在系统之间变化很大。

+1

这可能在单用户测试环境中工作得很好 - 但在负载下的生产系统中,有多个用户正在访问数据库,“SELECT MAX(+ 1)”方法迟早会失败并产生重复值。 ..... – 2013-04-11 21:28:40

+0

不够公平,我会用临时表格更新我的答案,以表明你的陈述可能是真实的。 – djangojazz 2013-04-11 21:59:18

+1

+1对于一个丑陋问题的良好答案。但是你只是让一个糟糕的数据设计继续存在。 – Paparazzi 2013-04-11 22:17:48

1

按照您的设计,考虑到A和B是唯一的,表C中不应有任何重复项。

A | B | C 
1 1 A1 
2 2 A2 
     B1 
     B2