场景:我有一个相当通用的表(Data),它有一个标识列。此表中的数据已分组(按城市说)。
用户需要一个标识符才能在纸质表格上打印等。 用户只能访问他们的引用数据,因此如果他们为此目的使用标识列,他们将看到奇数(例如'纽约'用户可能会看到1,37,2028 ...作为列出的密钥。
理想情况下,他们会看到1,2,3 ...(或类似的东西)
问题当然是并发性,这是一个Web应用程序,你不能只有这样的东西: UserId =从Data = City ='New York'
的数据中选择Count(*)+ 1有没有人想出任何狡猾的解决这个问题的方法?
更新 - 从下面的评论中我想我想要类似下面的SP。不完全确定递归应该如何在CATCH块中起作用。
ALTER PROCEDURE [dbo].[DataContainer_Insert]
@SomeData varchar(max),
@DataContainerId int out
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
BEGIN TRY
SELECT @UserId = MAX(UserId) From DataContainer
INSERT INTO DataContainer (UserId, SomeData)
VALUES (@UserId, SomeData)
SELECT @DataContainerId = scope_identity()
END TRY
BEGIN CATCH
--try again
exec DataContainer_Insert @DataContainerId, @SomeData
END CATCH
END
答案 0 :(得分:1)
在关闭情况下,如果我从GROUP BY
T语句中使用SELEC
生成的服务器数据发送回来,并且每行需要id
,我使用ROW_NUMBER() (见http://msdn.microsoft.com/en-us/library/ms186734.aspx)。这在数据分页的情况下也很好(参见http://weblogs.asp.net/Firoz/archive/2005/06/12/411949.aspx中的一个简单示例)。这是因为这需要SQL Server 2005或更高版本。您没有编写您使用的SQL Server。
答案 1 :(得分:1)
好吧,如果你在city和UserId上添加跨越唯一性约束(为了保证只有1个特定Id和City的实例),你可以使用UserId = Select Count(*)+1 from Data Where City='New York'
想法。然后你只需要能够处理约束违规(通过重新提交)。
答案 2 :(得分:1)
作为一般性评论:您可以执行类似
的操作newUserId = Select MAX(UserId)+1 from Data Where City='New York'
INSERT INTO data (...) VALUES (newUserId, ...)
即使在并发访问方案(例如Web应用程序)中,只要您采用适当的并发控制,即(a)锁定或(b)事务,适当的隔离级别。
有关如何使用SQL Server执行此类操作的深入分析,请参阅question 1994771。