You can do it this way:
UPDATE table_users
SET cod_user = (case when user_role = 'student' then '622057'
when user_role = 'assistant' then '2913659'
when user_role = 'admin' then '6160230'
end),
date = '12082014'
WHERE user_role in ('student', 'assistant', 'admin') AND
cod_office = '17389551';
I don't understand your date format. Dates should be stored in the database using native date and time types.
Answer from Gordon Linoff on Stack OverflowYou can do it this way:
UPDATE table_users
SET cod_user = (case when user_role = 'student' then '622057'
when user_role = 'assistant' then '2913659'
when user_role = 'admin' then '6160230'
end),
date = '12082014'
WHERE user_role in ('student', 'assistant', 'admin') AND
cod_office = '17389551';
I don't understand your date format. Dates should be stored in the database using native date and time types.
MySQL allows a more readable way to combine multiple updates into a single query. This seems to better fit the scenario you describe, is much easier to read, and avoids those difficult-to-untangle multiple conditions.
INSERT INTO table_users (cod_user, date, user_rol, cod_office)
VALUES
('622057', '12082014', 'student', '17389551'),
('2913659', '12082014', 'assistant','17389551'),
('6160230', '12082014', 'admin', '17389551')
ON DUPLICATE KEY UPDATE
cod_user=VALUES(cod_user), date=VALUES(date)
This assumes that the user_rol, cod_office combination is a primary key. If only one of these is the primary key, then add the other field to the UPDATE list.
If neither of them is a primary key (that seems unlikely) then this approach will always create new records - probably not what is wanted.
However, this approach makes prepared statements easier to build and more concise.
Try either multi-table update syntax
UPDATE config t1 JOIN config t2
ON t1.config_name = 'name1' AND t2.config_name = 'name2'
SET t1.config_value = 'value',
t2.config_value = 'value2';
Here is a SQLFiddle demo
or conditional update
UPDATE config
SET config_value = CASE config_name
WHEN 'name1' THEN 'value'
WHEN 'name2' THEN 'value2'
ELSE config_value
END
WHERE config_name IN('name1', 'name2');
Here is a SQLFiddle demo
You can accomplish it with INSERT as below:
INSERT INTO mytable (id, a, b, c)
VALUES (1, 'a1', 'b1', 'c1'),
(2, 'a2', 'b2', 'c2'),
(3, 'a3', 'b3', 'c3'),
(4, 'a4', 'b4', 'c4'),
(5, 'a5', 'b5', 'c5'),
(6, 'a6', 'b6', 'c6')
ON DUPLICATE KEY UPDATE id=VALUES(id),
a=VALUES(a),
b=VALUES(b),
c=VALUES(c);
This insert new values into table, but if primary key is duplicated (already inserted into table) that values you specify would be updated and same record would not be inserted second time.
mysql - Updating multiple rows with different values in one query - Database Administrators Stack Exchange
Update a single column on multiple rows with one SQL query - Stack Overflow
sql server - MS SQL How to Update multiple rows with single value? - Stack Overflow
sql server - SQL update multiple rows in destination table with same id but different values from source table - Database Administrators Stack Exchange
Videos
| Id | Name | Price |
|---|---|---|
| 1 | Pen | 50 |
| 2 | Pencil | 60 |
This is my table structure now I want to update the price of Pen and Pencil at the same time with one SQL query
UPDATE mytable SET
fruit = CASE WHEN id=1 THEN 'orange' ELSE 'strawberry' END,
drink = CASE WHEN id=1 THEN 'water' ELSE 'wine' END,
food = CASE WHEN id=1 THEN 'pizza' ELSE 'fish' END
WHERE id IN (1,2);
Personally, using CASE WHEN THEN END looks clumsy.
You could code this using the IF function.
UPDATE mytable SET
fruit = IF(id=1,'orange','strawberry'),
drink = IF(id=1,'water','wine'),
food = IF(id=1,'pizza','fish')
WHERE id IN (1,2);
Give it a Try !!!
CAVEAT : CASE WHEN THEN END is only handy when dealing with multiple values (more than 2)
INSERT ... ON DUPLICATE KEY UPDATE
You will need to write very complicated conditions if you want to update more than two rows. In such a case you can use INSERT ... ON DUPLICATE KEY UPDATE approach.
INSERT into `mytable` (id, fruit, drink, food)
VALUES
(1, 'orange', 'water', 'pizza'),
(2, 'strawberry', 'wine', 'fish'),
(3, 'peach', 'jiuce', 'cake')
ON DUPLICATE KEY UPDATE
fruit = VALUES(fruit),
drink = VALUES(drink),
food = VALUES(food);
You could use the MERGE statement which is in the SQL:2003 standard and available in Transact-SQL since SQL Server 2008:
MERGE mytable
USING (VALUES (23, 'FOD'),
(47, 'ASD'),
(83, 'FGH'),
(88, 'JKL'),
(92, 'QWE'),
( 9, 'BAR')) AS pairs(id2, data2)
ON id = id2
WHEN MATCHED
THEN UPDATE SET data = data2
The USING clause allows to specify a derived table using a table value constructor (See example under point D on that page).
Alternatively, the more commonly implemented SQL:92 standard syntax to do this would be:
UPDATE mytable
SET data =
CASE id
WHEN 23 THEN 'FOD'
WHEN 47 THEN 'ASD'
WHEN 83 THEN 'FGH'
WHEN 88 THEN 'JKL'
WHEN 92 THEN 'QWE'
WHEN 9 THEN 'BAR'
END
WHERE id IN (23, 47, 83, 88, 92, 9);
The obvious downside is that you end up specifying the id values twice. You could do without the WHERE clause and add ELSE data in the CASE construct, but then you would actually update all rows, which is inefficient and may have undesired side-effects (via triggers).
I'm assuming that you are in MySQL. You can use a combination of "Field" and "Elt" functions to do what you need in a single query (beside the CASE WHEN THEN WHEN THEN WHEN THEN WHEN THEN WHEN THEN WHEN THEN WHEN THEN END or IF(<condition>,<output>,if(<condition2>,<output2>, if())) methods.
UPDATE [table] SET DATA=ELT(FIELD(ID,
13, 14, 15, 16, 17, 18, 19),'FOO', 'ASD', 'FGH', 'JKL', 'QWE', 'BAR');
This is similar to the DECODE() function in Oracle, which I wish had counterparts in other DBMS's.
Couldn't find a SQL Server 2008 fiddle engine so I had to opt for a SQL Server 2014 ... so not sure if the following will work in SQL Server 2008, but fwiw ...
Setup some sample data:
create table Table1(id int, Date datetime null);
create table Table2(id int, Date datetime);
insert Table1 values (1,null)
insert Table1 values (1,null)
insert Table1 values (2,null)
insert Table1 values (2,null)
insert Table1 values (2,null);
insert Table2 values (1,'2013-01-29 08:50:00.000')
insert Table2 values (1,'2013-01-29 15:28:00.000')
insert Table2 values (2,'2013-01-31 11:56:00.000')
insert Table2 values (2,'2013-03-11 16:08:00.000')
insert Table2 values (2,'2013-01-31 14:04:00.000');
Keeping in mind that we haven't been provided (yet) with any means to determine which rows to match between Table1 and Table2 for a given id value, I'll just let row_number() generate a 'matching' rowid.
And then we'll make use of SQL Server's ability to update Table1 via a derived table definition:
update T1
set T1.Date=T2.Date
from (select row_number() over(partition by id order by Date) as rowid,
id,
Date
from Table1
where Date is NULL) T1
join (select row_number() over(partition by id order by Date) as rowid,
id,
Date
from Table2) T2
on T1.id = T2.id
and T1.rowid = T2.rowid;
And the results:
select * from Table1;
id Date
--- --------------------
1 2013-01-29T08:50:00Z
1 2013-01-29T15:28:00Z
2 2013-01-31T11:56:00Z
2 2013-01-31T14:04:00Z
2 2013-03-11T16:08:00Z
And here's a SQL Fiddle for the above.
You stated that the order of the matching matters but it seems like you don't have anything to ORDER BY in table 1 to create a guaranteed order to match the other table and there is no way in SQL Server to order the rows after insertion date, because information about that is not stored. With this in mind it’s not possible to do a matching with the result you want. There is a solution to update the rows with an arbitrary match within each id. If that would be good enough.
UPDATE t
SET t.[date] = tt.[date]
FROM (SELECT *,
Row_number()
OVER (
partition BY id
ORDER BY [date]) AS rno
FROM Table1) AS t
INNER JOIN (SELECT *,
Row_number()
OVER (
partition BY id
ORDER BY [date]) AS rno
FROM Table2) AS tt
ON t.id = tt.id
AND t.rno = tt.rno
This solution will match all rows individually but can't guarantee the order.
DB Fiddle
Remarks
It is possible to update rows based on some condition. It is also possible to update multiple tables in one statement in MySQL.
Whether the latter is a good idea is debatable, though. The target tables would be joined together for the update, and when I say "joined", I mean it in a broader sense: you do not have to specify a joining condition, in which case theirs would be a cross join. In a cross join, when at least one of the tables has more than one row, the other table will inevitably have its rows duplicated in the joined set. If both have multiple rows, both will have them multiplied. Somewhat counter-intuitively, MySQL will still update each affected row just once, yet I would refrain from multi-table updates in such scenarios, even if solely because of the counter-intuitiveness.
Method 1
Anyway, moving on to your specific example, there is indeed no joining condition, only a filter on each table. You can specify those filters in the WHERE clause of the UPDATE. Now in order to select which value to update each column with, you can use a CASE expression. This is what the complete UPDATE statement might look like:
UPDATE
A, B
SET
A.col1 = 'abc',
A.col2 = 'xyz',
B.col1 = CASE B.col3
WHEN '1' THEN 'a'
WHEN '2' THEN 'b'
WHEN '3' THEN 'c'
END,
B.col2 = CASE B.col3
WHEN '1' THEN 'x'
WHEN '2' THEN 'y'
WHEN '3' THEN 'z'
END
WHERE
A.col3 = '1'
AND B.col3 IN ('1', '2', '3')
;
You can see that you have to repeat the same set of conditions in a CASE expression both for B.col1 and for B.col2. Is there a way to avoid that?
Method 2
Yes, there is. You can arrange the target values for B.col1 and B.col2 as well as the filtering values for B.col3 as a derived table and join it to B in the UPDATE clause, like this:
UPDATE
A,
B
INNER JOIN
(
SELECT 'a' AS col1, 'x' AS col2, '1' AS col3
UNION ALL
SELECT 'b', 'y', '2'
UNION ALL
SELECT 'c', 'z', '3'
) AS fltr ON B.col3 = fltr.col3
SET
A.col1 = 'abc',
A.col2 = 'xyz',
B.col1 = fltr.col1,
B.col2 = fltr.col2
WHERE
A.col3 = '1'
;
The join is also acting as a filter for B, so you can omit the one in the WHERE clause.
You can find a demo for each method at
db<>fiddle:
- Method 1
- Method 2
Better way
Finally, as have been remarked both at the beginning of this post and in the comments, you can have a separate UPDATE statement for each table. The result would be clear in intention both to the reader of your script and to the database engine. A simpler script enables the latter to have more options for optimisation.
Use either of the methods above for the table B update, but do both tables separately:
UPDATE
A
SET
A.col1 = 'abc',
A.col2 = 'xyz'
WHERE
A.col3 = '1'
;
UPDATE
B
INNER JOIN
(
SELECT 'a' AS col1, 'x' AS col2, '1' AS col3
UNION ALL
SELECT 'b', 'y', '2'
UNION ALL
SELECT 'c', 'z', '3'
) AS fltr ON B.col3 = fltr.col3
SET
B.col1 = fltr.col1,
B.col2 = fltr.col2
;
There is also another reason for splitting the updates in separate statements. Since for a single UPDATE statement the tables need to be joined, it is important that both tables have rows intended for the update. If one table has no matching rows, then, even if the other does, neither will be updated. This is because an empty set cross-joined to a non-empty set still results in an empty set.
So, the single UPDATE statement would have no rows to work with if at least one table had no rows matching the condition(s). That would not happen with separate UPDATEs, because each would work with its own table regardless of the contents of the other, therefore, absence of rows in one table would not affect the update of the other.
You can use below one for one table if you want to update many columns of one table.
UPDATE table
SET col1 = CASE WHEN col3 = 'name1' THEN 'a'
WHEN col3 = '2' THEN b
ELSE 0
END
, col2 = CASE WHEN col3 = '1' THEN 'b'
WHEN col3 = 'name2' THEN 'c'
ELSE ''
END
;