title: Why does an insert that groups by the primary key throw a primary key constraint violation error?
body: <p>I have an insert statement that's throwing a primary key error but I don't see how I could possibly be inserting duplicate key values.</p>
  
  <p>First I create a temp table with a primary key.</p>
  
  <pre><code>SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED //Note: I've tried committed and uncommited, neither materially affects the behavior. See screenshots below for proof.
  
  IF (OBJECT_ID('TEMPDB..#P')) IS NOT NULL DROP TABLE #P;
  
  CREATE TABLE #P(idIsbn INT NOT NULL PRIMARY KEY, price SMALLMONEY, priceChangedDate DATETIME);
  </code></pre>
  
  <p>Then I pull prices from the Prices table, grouping by idIsbn, which is the primary key in the temp table.</p>
  
  <pre><code>INSERT  INTO #P(idIsbn, price, priceChangedDate)
  SELECT  idIsbn ,
          MIN(lowestPrice) ,
          MIN(priceChangedDate)
  FROM Price p
  WHERE p.idMarketplace = 3100
  GROUP BY p.idIsbn
  </code></pre>
  
  <p>I understand that grouping by idIsbn by definition makes it unique. The idIsbn in the prices table is: <code>[idIsbn] [int] NOT NULL</code>.</p>
  
  <p>But every once in a while when I run this query I get this error:</p>
  
  <pre><code>Violation of PRIMARY KEY constraint 'PK__#P________AED35F8119E85FC5'. Cannot insert duplicate key in object 'dbo.#P'. The duplicate key value is (1447858).
  </code></pre>
  
  <p>NOTE: I've got a lot of questions about timing. I will select this statement, press F5, and no error will occur. Then I'll do it again, and it will fail, then I'll run it again and again and it will succeed a couple times before it fails again. I guess what I'm saying is that I can find no pattern for when it will succeed and when it won't.</p>
  
  <p>How can I be inserting duplicate rows if (A) I just created the table brand new before inserting into it and (B) I'm grouping by the column designed to be the primary key?</p>
  
  <p>For now, I'm solving the problem with <code>IGNORE_DUP_KEY = ON</code>, but I'd really like to know the root cause of the problem.</p>
  
  <p>Here is what I'm actually seeing in my SSMS window. There is nothing more and nothing less:</p>
  
  <p><a href="https://i.stack.imgur.com/FLHWU.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/FLHWU.png" alt="enter image description here"></a></p>
  
  <p>@@Version is:</p>
  
  <pre><code>Microsoft SQL Server 2008 (SP3) - 10.0.5538.0 (X64) 
      Apr  3 2015 14:50:02 
      Copyright (c) 1988-2008 Microsoft Corporation
      Standard Edition (64-bit) on Windows NT 6.1 &lt;X64&gt; (Build 7601: Service Pack 1)
  </code></pre>
  
  <p>Execution Plan:
  <a href="https://i.stack.imgur.com/rKbK8.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/rKbK8.png" alt="enter image description here"></a></p>
  
  <p>Here is an example of what it looks like when it runs fine. Here I'm using READ COMMITTED, but it doesn't matter b/c I get the error no matter whether I read it committed or uncommited.
  <a href="https://i.stack.imgur.com/h436H.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/h436H.png" alt="enter image description here"></a></p>
  
  <p>Here is another example of it failing, this time w/ READ COMMITTED.</p>
  
  <p><a href="https://i.stack.imgur.com/k8LXR.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/k8LXR.png" alt="enter image description here"></a></p>
  
  <p>Also:</p>
  
  <ul>
  <li>I get the same error whether I'm populating a temp table or a
  persistent table.</li>
  <li>When I add <code>option (maxdop 1)</code> to the end of the insert it seems to fail every time, though I can't be exhaustively sure of that b/c I can't run it for infinity. But it seems to be the case.</li>
  </ul>
  
  <p>Here is the definition of the price table. Table has 25M rows. 108,529 updates in the last hour.</p>
  
  <pre><code>CREATE TABLE [dbo].[Price](
      [idPrice] [int] IDENTITY(1,1) NOT NULL,
      [idIsbn] [int] NOT NULL,
      [idMarketplace] [int] NOT NULL,
      [lowestPrice] [smallmoney] NULL,
      [offers] [smallint] NULL,
      [priceDate] [smalldatetime] NOT NULL,
      [priceChangedDate] [smalldatetime] NULL,
   CONSTRAINT [pk_Price] PRIMARY KEY CLUSTERED 
  (
      [idPrice] ASC
  )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY],
   CONSTRAINT [uc_idIsbn_idMarketplace] UNIQUE NONCLUSTERED 
  (
      [idIsbn] ASC,
      [idMarketplace] ASC
  )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
  ) ON [PRIMARY]
  </code></pre>
  
  <p>And the two non-clustered indexes:</p>
  
  <pre><code>CREATE NONCLUSTERED INDEX [IX_Price_idMarketplace_INC_idIsbn_lowestPrice_priceDate] ON [dbo].[Price]
  (
      [idMarketplace] ASC
  )
  INCLUDE (   [idIsbn],
      [lowestPrice],
      [priceDate]) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
  GO
  
  CREATE NONCLUSTERED INDEX [IX_Price_idMarketplace_priceChangedDate_INC_idIsbn_lowestPrice] ON [dbo].[Price]
  (
      [idMarketplace] ASC,
      [priceChangedDate] ASC
  )
  INCLUDE (   [idIsbn],
      [lowestPrice]) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
  GO
  </code></pre>