2010-05-12 40 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