Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/sql-server-2008/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server TSQL:获取下一个可用ID_Sql Server_Sql Server 2008_Tsql - Fatal编程技术网

Sql server TSQL:获取下一个可用ID

Sql server TSQL:获取下一个可用ID,sql-server,sql-server-2008,tsql,Sql Server,Sql Server 2008,Tsql,使用SQLServer2008,有三个表,表a、表b和表c 它们都有一个ID列,但对于表a和b,ID列是一个identity整数,对于表c,ID列是一个varchar类型 当前,存储过程采用名称param,遵循特定逻辑,插入表a或表b,获取标识,前缀为“a”或“b”,然后插入表c 问题是,表CID列可能有重复的值,即,如果表A中的标识为2,则表C的ID列中可能已经有“A2”、“A3”、“A5”,如何编写T-SQL查询以识别表C中的下一个可用值,然后确保相应地更新表A/B [更新] 这是目前的步骤

使用SQLServer2008,有三个表,表a、表b和表c

它们都有一个
ID
列,但对于表a和b,
ID
列是一个
identity整数
,对于表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.初始化种子值=@@Identity 3.通过前缀“A”计算要插入表C的ID值,或用种子值附加“B” 4.根据步骤3中的ID值查找表C中的记录匹配项,如果未找到任何记录,请插入它,否则将种子值增加1,然后重复步骤3

问题是在某个值范围内,表C ID中可能存在一个巨大的值块,即表C ID中现在存在3000到500000个值,如果遵循现有逻辑,数据库查询速度会非常慢。需要找出一个逻辑,以便智能地获取最小可用号码(不带前缀)


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

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

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

这应该能奏效。简单的自解压示例将在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转储到临时表。诚实地说,不同系统的查询性能与导入相比有很大的变化。

重新设计这个系统会更好。如果表a和表B中的
ID
实际上是
INT-IDENTITY
,那么这真的不是一个好方法-它怎么会给你重复的?对我来说似乎不可能,如果你使用表前缀(A或B)加上表C中表A或表B中
ID
列的唯一值…@Tommy Wang,你能编辑你的帖子并给我们一个更详细的例子吗?@Tommy Wang,您是否试图阻止A的键ID列与B的键ID列具有任何相同的值?如果是这样的话,您是否考虑过使用guid作为主键而不是整数?这在单用户测试环境中可能会很好地工作-但是在负载下的生产系统中,当多个用户访问您的数据库时,
SELECT MAX()+1
方法迟早会失败,并产生重复的值……公平地说,我会用临时表更新我的答案,说明你所说的可能是真的。+1是一个丑陋问题的好答案。但你只是让一个糟糕的数据设计继续存在。我想补充一点,如果你在一个生产环境中,你不应该这样做,因为我认为Marc_S暗示的例子是:如果你在时间x得到一个值,比如上午11:00。用户在时间y不断插入,比如上午11:01,我的数据可能已经无效了。因此,您需要考虑到数据可能会过时,或者知道在运行查询时,数据仅适用于该时间范围内列出的事务。解决这个问题的唯一方法是在完成之前将表锁定,但对于一个简单的例子,我的解决方案是有效的。