Sql server 具有标识的sql复合密钥

Sql server 具有标识的sql复合密钥,sql-server,sql-server-2000,Sql Server,Sql Server 2000,是否可以在sql 2000中创建以下形式的复合键: 事件id id2 adf 1 adf2 adf 3 cfg 1 cfg 2 edf 1 id2在每次更改事件id时重新启动计数。我需要通过创建表或其他SELECT语句技巧使编号与此完全相同 编辑: 我可能不太清楚,我只是暂时需要这个表来进行连接。我会避免将它称为标识,因为它不是,并且会让大多数其他人感到困惑 我认为您必须通过插入触发器和围绕递增序列的事务锁定来实现这一点。您无法让SQL自动为您实现这一点 如果您真的不需要这个,那么跳过它,您需要

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

事件id id2
adf 1
adf2
adf 3
cfg 1
cfg 2
edf 1

id2在每次更改事件id时重新启动计数。我需要通过创建表或其他SELECT语句技巧使编号与此完全相同

编辑:
我可能不太清楚,我只是暂时需要这个表来进行连接。

我会避免将它称为标识,因为它不是,并且会让大多数其他人感到困惑


我认为您必须通过插入触发器和围绕递增序列的事务锁定来实现这一点。

您无法让SQL自动为您实现这一点

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


我称之为序列,而不是ID,但是你会有一个更好的PK,只有一个常规标识,你仍然可以有一个SEQ列

您可以使用触发器来执行此操作。我认为在一次插入一行的情况下可以这样做,但我想不出一种方法来执行多行插入,因为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);
有点像这样:

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

这是我给另一张海报的答案,但它正好说明了你的要求:

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列添加到temp表中,并用新的数字更新它,而不是每次都计算它。我在猜测什么时候进行更新性能会更好。。。测试已经就绪。

您是否考虑过使用触发器完全按照您的要求填充这些字段?(这只是一个简单的想法,因为我必须离开)您能发布源表定义吗?SQl Server 2000在功能上没有rownumber(),我在问题中忽略了这一点。我的错。这是我一直遇到的问题,它是SQL 2000,但它将在大约一个月后升级,所以我可能会等待并找到一个简单的方法来完成。如果两个人获得相同的最大值,这可能会遇到并发问题。@HLGEM——确实如此。一个好的解决方案应该实施锁定策略来防止这种情况。