Update a single row with t-sql
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
.
How to update only one row in a table?
you can use ROWCOUNT
SET ROWCOUNT 1
UPDATE table1
SET name2 = '01'
WHERE name1='xx'
SET ROWCOUNT 0
or you can use update top
UPDATE TOP (1) table1
SET name2 = '01'
WHERE name1='xx'
SQL Update only updates one row
First of all let's reduce the eye hurting SQL to what it really is:
update sde.sy1.valve_evw
set ma = (select mc from sde.sy1.valve_join_evw)
where primarykey in (select primarykey from sde.sy1.valve_join_evw where ma <> mc)
WHERE clause
We look for all primarykey
in valve_join_evw
where a record's ma <> mc
. We update all valve_evw
records with such primarykey
.
SET clause
For a record we want to update, we set ma
to the value found with:
select mc from sde.sy1.valve_join_evw
But this query has no where clause, so what value does it select to fill the record's ma
field? It selects all mc
from valve_join_evw
, so the DBMS probably picks one of these values arbitrarily. (It would be better, it raised an error.)
Conclusion
It is very easy to see which records the statement will update.
Which primarykey
:
select primarykey from sde.sy1.valve_join_evw where ma <> mc
Which rows:
select *
from sde.sy1.valve_evw
where primarykey in (select primarykey from sde.sy1.valve_join_evw where ma <> mc)
As to the SET
clause: Add a WHERE
clause to your subquery that relates the record to select to the record to update (same ma
? same primarykey
?) E.g.:
set ma =
(
select mc
from sde.sy1.valve_join_evw vj
where vj.primarykey = valve_evw.primarykey
and vj.ma = valve_evw.ma
)
SQL update one single row table with data from another
You can use a CTE with a ROW_NUMBER()
function to do this. Simple example:
DECLARE @TABLE AS TABLE (Testing INT, Testing2 VARCHAR(55), Testing3 BIT);
INSERT INTO @TABLE VALUES (1, '1', 1);
INSERT INTO @TABLE VALUES (1, '1', 1);
INSERT INTO @TABLE VALUES (1, '1', 1);
INSERT INTO @TABLE VALUES (1, '1', 1);
INSERT INTO @TABLE VALUES (1, '1', 1);
INSERT INTO @TABLE VALUES (1, '1', 1);
INSERT INTO @TABLE VALUES (1, '1', 1);
INSERT INTO @TABLE VALUES (1, '1', 1);
WITH CTE AS
(
SELECT
ROW_NUMBER() OVER (ORDER BY Testing) AS RowID
,Testing
,Testing2
,Testing3
FROM @TABLE
)
UPDATE CTE
SET Testing = 2, Testing2 = '2', Testing3 = 0
WHERE RowID = 1
;
SELECT * FROM @TABLE
;
SQL Update single row, Where clause
I like to write SQL scripts that are idempotent:
UPDATE Users
SET Enabled=1
WHERE Id=1
AND Enabled<>1; -- if column is defined as NOT NULL
Scenarios:
- trigger that writes to shadow/history table (it will fire only once)
- last update date (will change only once)
- change tracking will not mark row as updated
- maybe slower but more consistent
Is update/select of a single column in a single row atomic and safe in SQL Server?
For the table structure you have shown both the UPDATE
and the SELECT
are standalone transactions and can use clustered index seeks to do their work without needing to read unnecessary rows and take unnecessary locks so I would not be particularly concerned about deadlocks with this procedure.
I would be more concerned about the fact that you don't have the UPDATE
and SELECT
inside the same transaction. So the X
lock on the row will be released as soon as the update statement finishes and it will be possible for another transaction to change the column value (or even delete the whole row) before the SELECT
is executed.
If you execute both statements inside the same transaction then I still wouldn't be concerned about deadlock potential as the exclusive lock is taken first (it would be a different matter if the SELECT
happened before the UPDATE
)
You can also address the concurrency issue by getting rid of the SELECT
entirely and using the OUTPUT
clause to return the post-update value to the client.
UPDATE Test SET Column1 = Column1 & ~2
OUTPUT INSERTED.Column1
WHERE Id = 1
Can't update only 1 row. How to change 1 row?
You need just a slight, provided that your DB's version is at least 12c
, change by replacing the part WHERE Position IN (SELECT Position
with WHERE ID IN (SELECT ID
as having a primary column. The current case has no sense, since all testers will be converted to managers even replacing the IN <subquery>
with ='Tester'
. So use the following update statement by removing double quotes
UPDATE Schedule
SET Position = 'Manager'
WHERE ID IN
(SELECT ID
FROM Schedule
WHERE Position = 'Tester'
FETCH NEXT 1 ROW ONLY);
Demo
How to update a single row from multiple rows with UPDATE JOIN
One method is pre-aggregation:
update u
set date_role_assigned = coalesce(user_role, u.date_role_assigned)
u.date_role_assigned),
date_activated = coalesce(a.user_account_activated, u.date_activated),
date_deactivated = coalesce(a.user_account_activated, u.date_deactivated)
from dbo.[User] u join
(select a.entid,
max(case when a.event_name = 'USER_ROLE_CHANGED' then a.event_date end) as user_role,
max(case when a.event_name = 'USER_ACCOUNT_ACTIVATED' then a.event_date end) as user_account_activated,
max(case when a.event_name = 'USER_ACCOUNT_DEACTIVATED' then a.event_date end) as user_account_deactivated
from dbo.AuditEventsPivot a
group by a.entid
) a
on a.entid = u.empid;
Updating Single Row per Group
You can define the row to update by using row_number()
in a CTE. This identifies the first row in the group for the update:
with toupdate as (
select tt.*, row_number() over (partition by OrderNumber order by id) as seqnum
from #tempTable tt
)
UPDATE toupdate
SET toupdate.guestCount = q.guestCount
FROM toupdate
INNER JOIN queryTable q
ON temp.OrderNumber = q.OrderNumber
where toupdate.seqnum = 1;
The problem with you query is that temp
is based on an aggregation subquery. Such a subquery is not updatable, because it does not have a 1-1 relationship with the rows of the original query. Using the CTE with row_number()
is updatable. In addition, your set
statement uses the table alias cc
which is not defined in the query.
Related Topics
How to Find Which Columns Don't Have Any Data (All Values Are Null)
Limit Ignored in Query with Group_Concat
Does Ms Access Suppress Primary Key Violations on Inserts
Put Pg_Try_Advisory_Xact_Lock() in a Nested Subquery
How to Substitute a String If Record Is Null in T-Sql
Query for How to Add the Missing Dates in SQL
Passing Multiple Values in Single Parameter
Porting from MySQL to T-Sql. Any Inet_Aton() Equivalent
How to Distinct or Group by a Text (Or Ntext) in SQL Server 2005
Oracle - Literal Does Not Match Format String Error
Performance and Readability of Regexp_Substr VS Instr and Substr
How to Create a Dates Table in Redshift