带有标识的sql复合键

时间:2009-06-24 17:10:23

标签: sql-server sql-server-2000

是否可以在以下格式的sql 2000中创建复合键:

event_id id2
adf 1
adf 2
adf 3
cfg 1
cfg 2
edf 1

其中id2在每次更改event_id时重新开始计数。我需要通过创建表或其他SELECT语句技巧来使编号完全相同。

编辑: 我可能不太清楚我只是暂时需要这个表来加入。

5 个答案:

答案 0 :(得分:2)

我会避免称这是一个身份,因为它不会,并且会让大多数人感到困惑。

我认为你必须通过插入触发器和事件锁定来完成这个过程。

答案 1 :(得分:0)

您无法让SQL自动为您执行此操作。

如果你真的不需要这个,那么跳过它,你需要查询表以获取下一个值然后必须插入行,同时锁定选择,所以没有其他人查询得到相同的下一个。

我称之为SEQuence而不是ID,但是你只有一个更好的PK,只有一个普通的身份,你仍然可以有一个SEQ列。

答案 2 :(得分:0)

您可以使用INSTEAD OF触发器执行此操作。我认为你可以在一次插入一行的情况下使用它,但我想不出为多行插入执行它的方法,因为SQL 2000没有ROW_NUMBER()函数。

我认为您最好的方法是使用存储过程。类似的东西:

CREATE PROC insert_event(@event_id char(3)) AS
DECLARE @max int;
SELECT @max = MAX(identity) WHERE event_id = @event_id;
INSERT INTO [table] (event_id, identity) VALUES (@event_id, @max + 1);

答案 3 :(得分:0)

这是我给另一张海报的答案,但它确切地证明了你的要求:

SELECT
   seqid = identity(int, 1, 1),
   event_id,
   S.name
INTO #EventNames
FROM
   celcat200809.dbo.CT_EVENT_STAFF ES
   LEFT JOIN celcat200809.dbo.CT_STAFF S ON ES.staff_id = S.staff_id
ORDER BY
   event_id,
   S.name

SELECT
   EN.event_id,
   Max(CASE seqid - minseqid WHEN 0 THEN EN.name ELSE '' END))
   + Max(Coalesce(' + ' + CASE seqid - minseqid WHEN 1 THEN EN.name ELSE NULL END, ''))
   + Max(Coalesce(' + ' + CASE seqid - minseqid WHEN 2 THEN EN.name ELSE NULL END, ''))
   + Max(Coalesce(' + ' + CASE seqid - minseqid WHEN 3 THEN EN.name ELSE NULL END, ''))
   + Max(Coalesce(' + ' + CASE seqid - minseqid WHEN 4 THEN EN.name ELSE NULL END, ''))
   + Max(Coalesce(' + ' + CASE seqid - minseqid WHEN 5 THEN EN.name ELSE NULL END, ''))
   + Max(Coalesce(' + ' + CASE seqid - minseqid WHEN 6 THEN EN.name ELSE NULL END, ''))
   + Max(Coalesce(' + ' + CASE seqid - minseqid WHEN 7 THEN EN.name ELSE NULL END, ''))
   + Max(Coalesce(' + ' + CASE seqid - minseqid WHEN 8 THEN EN.name ELSE NULL END, ''))
   + Max(Coalesce(' + ' + CASE seqid - minseqid WHEN 9 THEN EN.name ELSE NULL END, ''))
   + Max(Coalesce(' + ' + CASE seqid - minseqid WHEN 10 THEN EN.name ELSE NULL END, ''))
FROM
   #EventNames EN
   INNER JOIN (
      SELECT event_id, minseqid = Min(seqid) FROM #EventNames GROUP BY event_id
   ) X ON EN.event_id = X.event_id
GROUP BY EN.event_id

您可以忽略10个Max()表达式。关键部分是: - 将值粘贴到带有标识列的临时表中,按组按顺序排序。 - 使用聚合查询获取每组的最小值(上面派生的表X) - 从身份值中减去最小值(如果需要从1开始编号,则加1)并且每个组的数字重新开始为1!

如果您要使用select两次以上的结果,那么在创建时将另一个int列添加到临时表并使用新数字更新它,而不是每次都计算它。我猜测性能何时更好地进行更新...测试是有序的。

答案 4 :(得分:-1)

有点像这样:

CREATE TABLE #Temp (val char(3))
INSERT INTO #Temp VALUES ('adf')
INSERT INTO #Temp VALUES ('adf')
INSERT INTO #Temp VALUES ('adf')
INSERT INTO #Temp VALUES ('cfg')
INSERT INTO #Temp VALUES ('cfg')
INSERT INTO #Temp VALUES ('edf')

SELECT 
    Val,
    ROW_NUMBER() OVER (PARTITION BY Val ORDER BY Val)
 FROM #Temp

DROP TABLE #Temp