首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >为什么这个查询会产生PK违规错误?

为什么这个查询会产生PK违规错误?
EN

Stack Overflow用户
提问于 2018-08-27 20:48:11
回答 1查看 614关注 0票数 3

因此,我尝试在一个查询中,只插入一个不存在的行。

我的问题如下:

代码语言:javascript
复制
INSERT INTO [dbo].[users_roles] ([user_id], [role_id]) 
SELECT 29851, 1 WHERE NOT EXISTS (
  SELECT 1 FROM [dbo].[users_roles] WHERE user_id = 29851 AND role_id = 1)

有时(极少发生,但仍然是这样),它会生成以下错误:

违反主键约束'PK_USERS_ROLES‘。无法在对象'dbo.users_roles‘中插入重复的键。重复键值为(29851,1)。

PK_USERS_ROLES[user_id], [role_id]。下面是表模式的完整SQL:

代码语言:javascript
复制
create table users_roles
(
    user_id int not null
        constraint FK_USERS_ROLES_USER
        references user,
    role_id int not null
        constraint FK_USERS_ROLES_USER_ROLE
        references user_role,
    constraint PK_USERS_ROLES
    primary key (user_id, role_id)
)

Context

这是由Apache服务器上托管的PHP脚本执行的,并且“随机”地发生在数百次事件中(很可能是与并发相关的)。

更多信息:

  • SELECT @@VERSION给予:

PHP版本:SQL Server 2008 R2

  • Transaction隔离级别:ReadCommitted

  • This在显式事务内执行(通过语句,但我认为最终结果是相同的)

问题

happening?

  • What是一种安全的一次性插入(换句话说,在单个查询中)的有效方法,有人能解释一下为什么/如何使用
  • 吗?我见过诸如this one之类的其他答案,但这些解决方案都是针对存储过程的。

谢谢。

EN

回答 1

Stack Overflow用户

发布于 2018-08-28 00:12:12

明确地说明这一点可能会有所帮助。下面的代码在显式事务中运行它,显式地锁定行。

代码语言:javascript
复制
DECLARE @user_id INT; SET @user_id=29851;
DECLARE @role_id INT; SET @role_id=1;

BEGIN TRY
    BEGIN TRANSACTION;

    DECLARE @exists INT;
    SELECT @exists=1 
    FROM [dbo].[users_roles] WITH(ROWLOCK,HOLDLOCK,XLOCK)
    WHERE user_id=@user_id AND role_id=@role_id;

    IF @exists IS NULL
    BEGIN
        INSERT INTO [dbo].[users_roles] ([user_id], [role_id])
        VALUES(@user_id,@role_id);
    END

    COMMIT TRANSACTION;
END TRY
BEGIN CATCH
    ROLLBACK TRANSACTION;
END CATCH
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52039734

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档