SQLのupdateについてまとめています。
SQLのUPDATEの構文
updateは、指定したテーブルの値を更新するSQLです。以下は、employees2テーブルのemp_no=10001のレコードのfirst_nameをTarou、last_nameをYamadaに書き換える例です。update文を実行する前後でselect文を実行し、値が更新されたことを確認しています。
mysql> select * from employees2 limit 10; +--------+------------+------------+-----------+--------+------------+ | emp_no | birth_date | first_name | last_name | gender | hire_date | +--------+------------+------------+-----------+--------+------------+ | 10001 | 1953-09-02 | Georgi | Facello | M | 1986-06-26 | | 10002 | 1964-06-02 | Bezalel | Simmel | F | 1985-11-21 | | 10003 | 1959-12-03 | Parto | Bamford | M | 1986-08-28 | | 10004 | 1954-05-01 | Chirstian | Koblick | M | 1986-12-01 | | 10005 | 1955-01-21 | Kyoichi | Maliniak | M | 1989-09-12 | | 10006 | 1953-04-20 | Anneke | Preusig | F | 1989-06-02 | | 10007 | 1957-05-23 | Tzvetan | Zielinski | F | 1989-02-10 | | 10008 | 1958-02-19 | Saniya | Kalloufi | M | 1994-09-15 | | 10009 | 1952-04-19 | Sumant | Peac | F | 1985-02-18 | | 10010 | 1963-06-01 | Duangkaew | Piveteau | F | 1989-08-24 | +--------+------------+------------+-----------+--------+------------+ 10 rows in set (0.00 sec) mysql> update employees2 set first_name='Tarou', last_name='Yamada' where emp_no=10001; Query OK, 1 row affected (0.00 sec) Rows matched: 1 Changed: 1 Warnings: 0 mysql> select * from employees2 limit 10; +--------+------------+------------+-----------+--------+------------+ | emp_no | birth_date | first_name | last_name | gender | hire_date | +--------+------------+------------+-----------+--------+------------+ | 10001 | 1953-09-02 | Tarou | Yamada | M | 1986-06-26 | | 10002 | 1964-06-02 | Bezalel | Simmel | F | 1985-11-21 | | 10003 | 1959-12-03 | Parto | Bamford | M | 1986-08-28 | | 10004 | 1954-05-01 | Chirstian | Koblick | M | 1986-12-01 | | 10005 | 1955-01-21 | Kyoichi | Maliniak | M | 1989-09-12 | | 10006 | 1953-04-20 | Anneke | Preusig | F | 1989-06-02 | | 10007 | 1957-05-23 | Tzvetan | Zielinski | F | 1989-02-10 | | 10008 | 1958-02-19 | Saniya | Kalloufi | M | 1994-09-15 | | 10009 | 1952-04-19 | Sumant | Peac | F | 1985-02-18 | | 10010 | 1963-06-01 | Duangkaew | Piveteau | F | 1989-08-24 | +--------+------------+------------+-----------+--------+------------+ 10 rows in set (0.00 sec)
【関連記事】
▶SQLでアップデートする方法|様々な条件付きでデータを更新するやり方も解説
Oracleのupdateの構文
UPDATE [ hint ] { dml_table_expression_clause | ONLY (dml_table_expression_clause) } [ t_alias ] update_set_clause [ where_clause ] [ returning_clause ] [error_logging_clause] ;
Oracleでは、RETURNING句を使って、更新された行の値をPL/SQL変数に格納することが可能です。以下のSQLでは、更新された行のsalary*0.25、last_name、department_idをそれぞれPL/SQL変数のbnd1、bnd2、bnd3に格納します。
UPDATE employees SET job_id ='SA_MAN', salary = salary + 1000, department_id = 140 WHERE last_name = 'Jones' RETURNING salary*0.25, last_name, department_id INTO :bnd1, :bnd2, :bnd3;
また、Oracleではselect文にfor updateを指定して行単位のロックをかけることができます。
【関連記事】
▶SQLのfor updateは行レベルでテーブルをロックする トランザクションで有効
SQL Serverのupdateの構文
[ WITH <common_table_expression> [...n] ] UPDATE [ TOP ( expression ) [ PERCENT ] ] { { table_alias | <object> | rowset_function_limited [ WITH ( <Table_Hint_Limited> [ ...n ] ) ] } | @table_variable } SET { column_name = { expression | DEFAULT | NULL } | { udt_column_name.{ { property_name = expression | field_name = expression } | method_name ( argument [ ,...n ] ) } } [ <OUTPUT Clause> ] [ FROM{ <table_source> } [ ,...n ] ] [ WHERE { <search_condition> | { [ CURRENT OF { { [ GLOBAL ] cursor_name } | cursor_variable_name } ] } } ] [ OPTION ( <query_hint> [ ,...n ] ) ] [ ; ]
参考)UPDATE (Transact-SQL) – SQL Server | Microsoft Docs
SQL Serverでは、TOP句を使用して更新される行の数を指定することが可能です。指定条件が複数の行に合致する場合に、指定した件数のみ更新できるんですね。
ただし、更新される対象はランダムになります。以下のSQLのケースでは、HumanResourcesデータベースのEmployeeテーブルに対して、ランダムに10件、VacationHoursの値を25%増し(1.25倍)に更新します。
USE AdventureWorks2012; GO UPDATE TOP (10) HumanResources.Employee SET VacationHours = VacationHours * 1.25 ; GO
MySQLのupdateの構文
UPDATE [LOW_PRIORITY] [IGNORE] table_reference SET col_name1={expr1|DEFAULT} [, col_name2={expr2|DEFAULT}] ... [WHERE where_condition] [ORDER BY ...] [LIMIT row_count]
参考)MySQL :: MySQL 5.6 リファレンスマニュアル :: 13.2.11 UPDATE 構文
MySQLでは、複数テーブルの更新が可能です。以下のSQLでは、itemsテーブルとmonthテーブルに対して、idが同一のデータの価格(price)を更新しています。
UPDATE items,month SET items.price=month.price WHERE items.id=month.id;
上記の記述方法以外にも、SELECT文で使用可能な結合(LEFT JOIN)などを使用可能です。
PostgreSQLのupdateの構文
[ WITH [ RECURSIVE ] with_query [, ...] ] UPDATE [ ONLY ] table_name [ * ] [ [ AS ] alias ] SET { column_name = { expression | DEFAULT } | ( column_name [, ...] ) = ( { expression | DEFAULT } [, ...] ) } [, ...] [ FROM from_list ] [ WHERE condition | WHERE CURRENT OF cursor_name ] [ RETURNING * | output_expression [ [ AS ] output_name ] [, ...] ]
PostgreSQLのupdateは標準SQLに準拠していますが、FROM句、RETURNING句、WITHはPostgreSQLの拡張です。
FROM句を使うと、他テーブルの結合結果を更新対象にすることができるんですね。下記SQLのケースでは、顧客名Acme Corporationを持つ営業担当のsales_countを1増加します。
UPDATE employees SET sales_count = sales_count + 1 FROM accounts WHERE accounts.name = 'Acme Corporation' AND employees.id = accounts.sales_person;
標準SQLで記述すると、以下のように副問合せを使ったSQLと同じ操作になります。
UPDATE employees SET sales_count = sales_count + 1 WHERE id = (SELECT sales_person FROM accounts WHERE name = 'Acme Corporation');
SQLのupdateのまとめ
- updateは、データの更新を行なうSQL
- updateは標準SQLだが、TOP句、FROM句やRETURNING句など主要DBMSごとに独自拡張あり
- 一部のDBMSでは、select文にfor updateを指定して、更新用に行単位のロックが可能