2013-07-03 41 views
2

这是我的试样台,主键是由SQL 2012 Sequence对象ASequence生成的A密钥+ B密钥SQL Server 2012的序列对象

 
Akey Bkey ItemSequence  
---- ---- ------------ 
1  1  1 
1  5  2 
1  7  3 
2  7  1 
3  2  1 
3  3  2 

A密钥的组合密钥。在大多数情况下,我一次插入一行,必要时我称之为序列的下一个值。不过,我需要从类似的声明做插入:

 
SELECT DENSE_RANK() OVER (ORDER BY Something) as AKey, 
    Bkey, Sequence 
FROM TABLEB 

下一个值的OVER子句,因为我需要能够插入记录为一组,但只增加序列一次每不起作用这种方式DENSE_RANK集。 所以我们有了ALTER SEQUENCE命令,并且可以将序列设置为我想要的。对此的警告是它必须是一个常量,并且不会接受一个变量。我的解决方法是:

 
DECLARE @startingID INT 
DECLARE @sql VARCHAR(MAX) 
DECLARE @newSeed INT 

SET @startingID = NEXT VALUE FOR ASequence 

INSERT TABLEA 
SELECT DENSE_RANK() OVER (ORDER BY Something) + @startingID as AKey, 
    Bkey, Sequence 
FROM TABLEB 

SELECT @newSeed = MAX(Akey) FROM TABLEA 

SET @sql = ‘ALTER SEQUENCE ASEQUENCE RESTART WITH ‘ + cast(@newSeed+1 as varchar(10)) 
EXEC(@sql) 

似乎在Dynamic SQL中有这样的DML语句可怕。有一个更好的方法吗?

+0

弗拉德提供的解决方案是要走的路。但是,如果将来必须使用动态SQL,请务必使用[sp_executesql](http://msdn.microsoft.com/zh-cn/library/ms188001.aspx)而不是EXEC。 – kheld

回答

0

这应做到:

INSERT TABLEA 
SELECT NEXT VALUE FOR ASequence OVER(ORDER BY Something) as AKey, 
    Bkey, Seq 
FROM TABLEB 
+0

你试过了你的代码吗?它不会以这种方式工作。 NEXT VALUE的OVER子句仅适用于排序。它指定每行应用序列的顺序。我需要按照我的问题所述的顺序为每套提供1个值。经过很多研究,我总结出这是不可能的,除了我详细说明的方式。我希望有人能在我的发现中证明我错了。起初,你会认为NEXT VALUE会以这种方式工作,也似乎是一个逻辑功能。 – Jeff

+0

看看sp_sequence_get_range对你来说听起来比动态DDL更好。无论哪种情况,此代码在同时从多个连接运行时都会产生不正确的结果。 –

+0

你是否介意我问,为什么你在乎AKey每个等级组或每个记录增加?你可以把它作为TableA中的PK,并使用直接标识(或序列)? –

0

或者说,这个怎么样:

CREATE TABLEA 
(
    GroupID INT, 
    AKey INT, 
    BKey INT, 
    ItemSequence INT, 
    CONSTRAINT PK_TABLEA PRIMARY KEY CLUSTERED 
    (
     GroupID, 
     AKey, 
     BKey 
    ) 
) 

DECLARE @GroupID INT 
SET @GroupID = NEXT VALUE FOR ASequence 

INSERT TABLEA 
SELECT @GroupID, DENSE_RANK() OVER (ORDER BY Something) as AKey, 
    Bkey, Sequence 
FROM TABLEB 

,如果您需要AKEY的价值,因为它是你的榜样,你可以做群ID + AKEY这里。