20

I want to update a row in my date base. The problem is, through a mistake on my part, I have two identical rows of data. How do I run the update on just one row?

Scott W
  • 9,742
  • 2
  • 38
  • 53
dan_vitch
  • 4,477
  • 12
  • 46
  • 69

5 Answers5

23

In SQL Server 2005+, you can use

UPDATE TOP (1) ....

The advantage of this over SET ROWCOUNT is that any triggers will not be subject to a ROWCOUNT limit, which is almost certainly a good thing.

Martin Smith
  • 438,706
  • 87
  • 741
  • 845
spender
  • 117,338
  • 33
  • 229
  • 351
18

Often tables have a unique ID. And you should filter on that.

For example,

UPDATE YourTable
SET YourColumnToUpdate = 'your_value'
WHERE YourUniqueColumn = @Id

If your table does not have a unique ID, consider adding one: an integer column with a Primary Key and Identity.

Bill Paetzke
  • 13,332
  • 6
  • 44
  • 46
3

I suggest you go back and normalize your database. At the very least add a auto increment int primary key column and use that id. Using UPDATE TOP 1 might work and directly answers your question, but non - normalization of your database is the "real" problem.

http://en.wikipedia.org/wiki/Database_normalization

RandyMorris
  • 1,264
  • 9
  • 17
0

Use SET ROWCOUNT;

SET ROWCOUNT 1; UPDATE Production.ProductInventory SET Quantity = 400 WHERE Quantity < 300; GO

http://msdn.microsoft.com/en-us/library/ms188774.aspx

Ryan Anderson
  • 937
  • 10
  • 23
  • "Using SET ROWCOUNT will not affect DELETE, INSERT, and UPDATE statements in the next release of SQL Server. Do not use SET ROWCOUNT with DELETE, INSERT, and UPDATE statements in new development work, and plan to modify applications that currently use it. Also, for DELETE, INSERT, and UPDATE statements that currently use SET ROWCOUNT, we recommend that you rewrite them to use the TOP syntax. For more information, see DELETE (Transact-SQL), INSERT (Transact-SQL), or UPDATE (Transact-SQL)." – Francisco Soto May 25 '10 at 23:09
  • Nice Francisco, very important to know! Thanks! – Ryan Anderson May 25 '10 at 23:13
0
-- 01. create the table for the test-data
CREATE TABLE dbo.Orders (
    ID INTEGER
    ,Value DECIMAL(10, 2)
    ,Descr NVARCHAR(100)
    ,BookingDate DATETIME
    ,UserName NVARCHAR(100)
    ,CountMeasure INTEGER
)

-- 02. save the timestamp for the inserts
DECLARE @date AS DATETIME
SET @date = getdate()

-- 03. inserting test-data
INSERT INTO dbo.Orders VALUES (1,499.99,'Notebook',@date,'tgr',0)
INSERT INTO dbo.Orders VALUES (2,650.00,'PC',@date,'tgr',0)
INSERT INTO dbo.Orders VALUES (3,29.50,'Keyboard',@date,'tgr',0)

-- 04. adding the duplicate entry
INSERT INTO dbo.Orders VALUES (2,650.00,'PC',@date,'tgr',0)

-- 05. viewing the 4 Rows
SELECT * FROM dbo.Orders

-- 06. viewing the distinct 3 Rows
SELECT DISTINCT * FROM dbo.Orders

/* You don't want to delete the duplicate row, but you want to count 
   the distinct IDs using SUM on the CountMeasure-Column */

-- 07. alternativ solution (which may does not fit your requirements)
/* So your result shoud be the same like this */
SELECT COUNT(DISTINCT ID) as DistinctCount
FROM dbo.Orders

-- 08. Understanding the solution
/* To understand the solution we take a look on the main-part 
   We generate for each ID a Row-Number ordered by random  
   Details: https://msdn.microsoft.com/de-de/library/ms186734%28v=sql.120%29.aspx */
SELECT * , ROW_NUMBER() OVER (PARTITION BY ID ORDER BY NEWID()) AS RowNumberForEachId
FROM dbo.Orders

-- 09. The update statement
/* We use this part to update our table */
UPDATE a
SET CountMeasure = 1
FROM (-- Orders incl
      SELECT * , ROW_NUMBER() OVER (PARTITION BY ID ORDER BY NEWID()) as rowNum
      FROM dbo.Orders
) as a
WHERE rowNum = 1

-- 10. Viewing the Result 
SELECT * FROM dbo.Orders 

-- 11. Comparing Count(DISTINCT ...) with the SUM(...) alternative
SELECT COUNT(DISTINCT ID) as countDistinct, SUM(CountMeasure) as sumCountMeasure
FROM dbo.Orders

-- 12. Removing the test-table
DROP TABLE dbo.Orders
tgr
  • 244
  • 1
  • 9