2010-05-12 37 views
2

场景:我有一个相当通用的表(数据),它具有标识列。该表中的数据被分组(可以按城市说)。如何创建唯一的用户密钥

用户需要一个标识符才能在纸张表格上打印等。 用户只能访问他们的引用数据,所以如果他们使用标识列来达到这个目的,他们会看到奇数(例如'纽约“用户可能会看到1,37,2028 ......所列出的键。

Idealy他们会看到1,2,3 ...(或类似的东西)

当然,问题是并发性,这作为一个Web应用程序,你不能只是有这样的: UserId =从数据选择计数(*)+ 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 
+2

您是否需要确实能够稍后查看此ID,还是纯粹用于显示(打印)目的? – Aaronaught 2010-05-12 21:56:41

+0

我需要稍后查找此ID。我现在添加了一些示例代码。 – 2010-05-20 23:35:49

回答

1

那么,如果您在city和UserId上添加了一个跨越唯一性约束(以确保只有一个特定Id和城市的实例),那么您可以使用UserId = Select Count(*)+1 from Data Where City='New York'想法。那么你只需要能够处理约束违规(通过重新提交)。

+0

是的,我喜欢这种方法(而不是锁定),只是寻找一些示例代码。 – 2010-05-16 01:31:40

1

在接近的情况下,如果我把从SELEC牛逼语句中使用GROUP BY生产的服务器数据备份,并且需要有像每一行的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。

+0

谢谢,是的,我使用相同的功能进行分页。但当然,分页这个ID不会持久。 – 2010-05-12 22:48:53

+0

你是什么意思“分页这个ID是不是持久”?我展示一张桌子。确切地说,我显示jqGrid里面充满了数据和分页按钮。使用jqGrid关联了一个用户依赖的URL,它与CTE的复杂SELECT语句相对应(请参阅http://www.sqlteam.com/article/server-side-paging-using-sql-server-2005)。我需要在jqGrid中放置数据的“id”。如果我使用ROW_NUMBER()作为id,我可以在jqGrid中将选定的行标识为SELECT语句中的对应行。所以我没有问题。 – Oleg 2010-05-12 23:15:46

+0

如果我有类似下面的代码段(添加一个Id),我会根据标识列获得一个Id号码,只要没有列被删除,这将返回相同的结果,那么当发生不同的结果返回的id列将会不同。 选择ROW_NUMBER()OVER(ORDER BY号), 'ID',\t \t \t ROW_NUMBER()OVER(ORDER BY sortColumn)AS行,* – 2010-05-16 01:21:56

1

作为一般说明:您可以这样做

newUserId = Select MAX(UserId)+1 from Data Where City='New York' 
INSERT INTO data (...) VALUES (newUserId, ...) 

即使在并发访问的情况(如Web应用程序),只要你使用正确的并发控制,即(一)锁定或(b)交易与适当的隔离级别。

请参阅question 1994771深入分析如何使用SQL Server进行类似操作。

+0

这会给你什么?该特定会话的唯一标识符?如果来自同一城市的两个人同时打印?如果在用户打印时添加用户会怎么样? – 2010-05-12 22:21:35

+0

这将是确定新用户的id的过程(例如,INSERT INTO Data(UserId,...)SELECT MAX(UserId)+1,...)。我只是使用与问题中使用的符号相同的符号。我已经编辑了我的答案来澄清这一点。 – Heinzi 2010-05-12 22:58:34