如果不是EXISTS似乎不起作用

时间:2013-07-12 12:21:58

标签: sql sql-server sql-server-2008

我有以下脚本:

BEGIN
    IF NOT EXISTS (SELECT SessionID FROM SessionData WHERE SessionID = @SessionID)
    BEGIN
    SELECT @RegionID = RegionID
    FROM Region
    WHERE Domain = @Domain
    INSERT INTO SessionData (
    SessionID,
    SystemID,
    RegionID,
    RegionDomain,
    RemoteAddr,
    CreatePage)
    VALUES (
    @SessionID,
    @SystemID,
    @RegionID,
    @RegionDomain,
    @RemoteAddr,
    @CreatePage)
END
END

网站偶尔会产生如下错误:

  

违反PRIMARY KEY约束'PK_SessionData'。无法插入   对象'sbuser.SessionData'中的重复键。 duiplicate键   值是(1h6l61h069srw1nmw73j)。来源:Microsoft OLE DB Provider for   SQL Server编号:-2147217873

为什么它会运行脚本,如果有重复的密钥..?我很困惑..非常感谢任何帮助。

非常感谢..

2 个答案:

答案 0 :(得分:4)

两个并发重叠进程都将通过NOT EXISTS检查并尝试INSERT。

也就是说,NOT EXISTS是对INSERT的单独查询

NOT EXISTS和INSERT都可以写入单个MERGE

MERGE INTO
    SessionData WITH (SERIALIZABLE) S
USING (
    SELECT
        @SessionID AS SessionID ,
        @SystemID AS SystemID ,
        RegionID,
        @RegionDomain AS RegionDomain ,
        @RemoteAddr AS RemoteAddr ,
        @CreatePage AS CreatePage 
    FROM Region
    WHERE Domain = @Domain
    ) src ON S.SessionID = src.SessionID
WHEN NOT MATCHED THEN
   INSERT (
       SessionID,
       SystemID,
       RegionID,
       RegionDomain,
       RemoteAddr,
       CreatePage)
    VALUES (
       src.SessionID,
       src.SystemID,
       src.RegionID,
       src.RegionDomain,
       src.RemoteAddr,
       src.CreatePage);

答案 1 :(得分:-1)

这个怎么样:

INSERT INTO SessionData (
   SessionID,
   SystemID,
   RegionID,
   RegionDomain,
   RemoteAddr,
   CreatePage)
SELECT
   @SessionID,
   @SystemID,
   (SELECT TOP 1 RegionID FROM Region WHERE Domain = @Domain),
   @RegionDomain,
   @RemoteAddr,
   @CreatePage)
WHERE
   NOT EXISTS (SELECT SessionID FROM SessionData WITH (UPDLOCK, HOLDLOCK) 
                                WHERE SessionID = @SessionID)

这是一种在没有任何MERGE或事务的情况下获得原子操作的简明方法。