简体   繁体   English

SQL Server功能-防止重复

[英]SQL Server function - prevent duplicates

I have a SQL Server 2005 database. 我有一个SQL Server 2005数据库。 Table A has an identity column in it as well as another manual Id column that spans several rows. Table A有一个标识列,以及另一个跨越几行的手动Id列。 The second id column is in the format of '0000000098' and must be a string. 第二个id列的格式为'0000000098'并且必须为字符串。 I cannot change the data type. 我无法更改数据类型。

Function A gets the max ID column value, increments it by one, cast as string. Function A获取最大ID列值,将其递增1,并转换为字符串。

My stored proc gets the new ID, and then does several inserts using this id. 我存储的proc获取新的ID,然后使用该ID进行多次插入。

How can I prevent two clients from running the stored procedure and getting the same ID before the update occurs? 如何防止两个客户端在更新发生之前运行存储过程并获得相同的ID? Can I lock table a from reads until the proc is done processing or is there a more efficient way? 我可以锁定表a进行读取,直到proc完成处理为止,或者有没有更有效的方法?

If I could change the data type and/or structure, it would be easy, but I can't. 如果我可以更改数据类型和/或结构,那将很容易,但是我做不到。

If you can formulate your function as a single UPDATE statement, then no explicit locking is needed - the UPDATE statement will require an update lock ( U ) and this is exclusive, eg no two readers can get an update lock on the same row at the same time. 如果您可以将函数表示为单个UPDATE语句,则不需要显式锁定UPDATE语句将需要一个更新锁( U ),这是排他性的,例如,没有两个读取器可以在该行的同一行上获得更新锁。同时。

UPDATE dbo.TableA
SET ManualID = CAST(CAST(ManualID AS INT) + 1 AS VARCHAR(20))
OUTPUT Inserted.ManualID  -- return the newly inserted manual ID for your use
WHERE ..........

If you need to have a two-step process - SELECT before UPDATE - then I'd use the WITH (UPDLOCK) hint on the SELECT 如果您需要两步过程-在UPDATE之前先进行SELECT那么我将在SELECT上使用WITH (UPDLOCK)提示

DECLARE @OldManualID VARCHAR(20)

BEGIN TRANSACTION

SELECT @OldManualID = ManualID 
FROM dbo.TableA WITH (UPDLOCK)
WHERE........

-- do something with that manual ID

UPDATE dbo.TableA
SET ManualID = (new value of ManualID)
WHERE ..........

COMMIT TRANSACTION

In both cases, since the single UPDATE or the SELECT/UDPATE run under an update lock, no two processes can run this at the same time. 在这两种情况下,由于单个UPDATE或SELECT / UDPATE在更新锁下运行,因此没有两个进程可以同时运行。 I don't think you need any further locking at all - most definitely not a total table lock.... 我认为您根本不需要任何进一步的锁定-绝对不是总表锁定。

Yes, you can lock the table. 是的,您可以锁定桌子。 You need to do all the things inside the transaction and when you read the table for the very first time you can place on it an exclusive continuous lock with hints (updlock, holdlock) or even (TABLOCKX) 您需要做事务内的所有事情,当您第一次阅读该表时,可以在其上放置带有提示(updlock,holdlock)甚至(TABLOCKX)的独占连续锁。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM