cru*_*ush 3 t-sql sql-server sql-server-2012
我一直在寻找类似于此问题的问题,我现在还没有找到任何东西,所以如果以前曾经问过这个问题,那至少可以作为那些对正确命名法无知的人的指针.
INSERT INTO基于唯一键,如果一行尚不存在,我想要一个表.它确实存在,然后我想获得该行的主键ID.
想象一下一个包含电子邮件地址的表:
EmailAddressId(PK) | EmailAddress(UK)
Run Code Online (Sandbox Code Playgroud)
我想在INSERT该表中添加一个新的电子邮件地址,但是有一个独特的约束条件EmailAddress.因此,如果新的电子邮件地址与现有电子邮件地址相同,INSERT则将失败.在那种情况下,我想EmailAddressId从数据库中选择现有的EmailAddress.
我想在最少的操作中执行此操作,假设碰撞将是罕见的情况.
因此,我TRY...CATCH在存储过程中设置了一个块,如下所示:
ALTER PROCEDURE [dbo].[EmailAddressWrite]
@EmailAddress nvarchar[256]
BEGIN
SET NOCOUNT ON;
BEGIN TRANSACTION
DECLARE @EmailAddressId INT
BEGIN TRY
INSERT INTO EmailAddress VALUES (@EmailAddress)
SET @EmailAddressId = (SELECT SCOPE_IDENTITY())
END TRY
BEGIN CATCH
SET @EmailAddressId = (SELECT EmailAddressId FROM EmailAddress WHERE EmailAddress = @EmailAddress)
END CATCH
--Do some more stuff with the Id now.
COMMIT TRANSACTION
RETURN @EmailAddressId
END
Run Code Online (Sandbox Code Playgroud)
上面的代码起作用,并产生所需的结果,但互联网让我觉得TRY...CATCH以这种方式使用可能会很慢......因此我不确定这是否是最佳解决方案.
我只找到了另一个解决方案,SELECT第一个和INSERT第二个.这几乎在所有时间都会导致2次操作,因为我预计很少有重复的电子邮件地址(至少一个月或更长时间).
INSERT和2次INSERT失败操作的最佳解决方案吗?INSERT和2次INSERT失败操作?如果我误用了任何术语,请更正.
DECLARE @id INT
DECLARE @newid TABLE
(
emailAddressId INT NOT NULL PRIMARY KEY
)
;
WITH t AS
(
SELECT *
FROM emailAddress WITH (ROWLOCK, HOLDLOCK)
WHERE emailAddress = @emailAddress
)
MERGE
INTO t
USING (
SELECT @emailAddress
) s (emailAddress)
ON 1 = 1
WHEN NOT MATCHED BY TARGET THEN
INSERT (emailAddress)
VALUES (emailAddress)
WHEN MATCHED THEN
UPDATE
SET @id = 1
OUTPUT INSERTED.emailAddressId
INTO @newid
;
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
62 次 |
| 最近记录: |