我们经常会遇到“如果不存在,就插入”的情况。Dan Guzman 的博客对如何使这个进程线程安全进行了出色的调查。
我有一个基本表,它只是将字符串从SEQUENCE
. 在存储过程中,我需要获取值的整数键(如果存在),或者INSERT
获取结果值。列上有唯一性约束,dbo.NameLookup.ItemName
因此数据完整性没有风险,但我不想遇到异常。
这不是IDENTITY
我无法得到的,在某些情况下SCOPE_IDENTITY
价值可能是。NULL
在我的情况下,我只需要处理INSERT
桌子上的安全问题,所以我试图决定这样使用是否更好MERGE
:
SET NOCOUNT, XACT_ABORT ON;
DECLARE @vValueId INT
DECLARE @inserted AS TABLE (Id INT NOT NULL)
MERGE
dbo.NameLookup WITH (HOLDLOCK) AS f
USING
(SELECT @vName AS val WHERE @vName IS NOT NULL AND LEN(@vName) > 0) AS new_item
ON f.ItemName= new_item.val
WHEN MATCHED THEN
UPDATE SET @vValueId = f.Id
WHEN NOT MATCHED BY TARGET THEN
INSERT
(ItemName)
VALUES
(@vName)
OUTPUT inserted.Id AS Id INTO @inserted;
SELECT @vValueId = s.Id FROM @inserted AS s
我可以在不使用MERGE
条件的情况下执行此操作,INSERT
然后使用SELECT
我认为第二种方法对读者来说更清楚,但我不相信这是“更好”的做法
SET NOCOUNT, XACT_ABORT ON;
INSERT INTO
dbo.NameLookup (ItemName)
SELECT
@vName
WHERE
NOT EXISTS (SELECT * FROM dbo.NameLookup AS t WHERE @vName IS NOT NULL AND LEN(@vName) > 0 AND t.ItemName = @vName)
DECLARE @vValueId int;
SELECT @vValueId = i.Id FROM dbo.NameLookup AS i WHERE i.ItemName = @vName
或者也许还有另一种我没有考虑过的更好的方法
我确实搜索并参考了其他问题。这个:https ://stackoverflow.com/questions/5288283/sql-server-insert-if-not-exists-best-practice是我能找到的最合适的,但似乎不太适用于我的用例。IF NOT EXISTS() THEN
我认为不可接受的方法的其他问题。