開発者ドキュメント

How To Update Data in SQL

序章

データベースを操作する場合、データベースにすでに挿入されているデータを変更する必要がある場合があります。 たとえば、スペルミスのあるエントリを修正する必要がある場合や、不完全なレコードに追加する新しい情報がある場合があります。 構造化照会言語—より一般的には SQL として知られています—は、ユーザーがテーブル内の既存のデータを変更できるようにするUPDATEキーワードを提供します。

このガイドでは、SQLのUPDATE構文を使用して1つ以上のテーブルのデータを変更する方法の概要を説明します。 また、SQLが外部キー制約と競合するUPDATE操作を処理する方法についても説明します。

前提条件

このガイドに従うには、SQLを使用するある種のリレーショナルデータベース管理システム(RDBMS)を実行しているコンピューターが必要です。 このガイドの手順と例は、次の環境を使用して検証されています。

:多くのRDBMSは、独自のSQL実装を使用していることに注意してください。 このチュートリアルで概説されているコマンドはほとんどのRDBMSで機能しますが、MySQL以外のシステムでテストした場合、正確な構文または出力が異なる場合があります。

このページに埋め込まれているインタラクティブ端末を使用して、このチュートリアルのサンプルクエリを試すこともできます。 次のLaunch an Interactive Terminal!ボタンをクリックして開始します。

MySQLへの接続とサンプルデータベースの設定

SQLデータベースシステムがリモートサーバーで実行されている場合は、ローカルマシンからサーバーにSSHで接続します。

  1. ssh sammy@your_server_ip

次に、MySQLサーバープロンプトを開き、sammyをMySQLユーザーアカウントの名前に置き換えます。 このページに埋め込まれたインタラクティブ端末を使用している場合、プロンプトが表示されたときに使用するパスワードはsecretという単語であることに注意してください。

  1. mysql -u sammy -p

updateDBという名前のデータベースを作成します。

  1. CREATE DATABASE updateDB;

データベースが正常に作成されると、次のような出力が表示されます。

Output
Query OK, 1 row affected (0.01 sec)

updateDBデータベースを選択するには、次のUSEステートメントを実行します。

  1. USE updateDB;
Output
Database changed

updateDBデータベースを選択した後、そのデータベース内にいくつかのテーブルを作成します。 このガイドで使用されている例では、タレントエージェンシーを運営していて、SQLデータベースでクライアントとそのパフォーマンスの追跡を開始することにしたと想像してください。 最初に2つのテーブルから始めることを計画しており、最初のテーブルにはクライアントに関する情報が格納されます。 このテーブルには4つの列が必要であると判断しました。

次の4つの列を持つclientsという名前のテーブルを作成します。

  1. CREATE TABLE clients
  2. (clientID int PRIMARY KEY,
  3. name varchar(20),
  4. routine varchar(30),
  5. standardFee decimal (5,2)
  6. );

2番目のテーブルには、ローカル会場でのクライアントのパフォーマンスに関する情報が格納されます。 このテーブルには5つの列が必要であると判断します。

clientID列が有効なクライアントID番号を表す値のみを保持するようにするには、clientsテーブルのclientID列。 外部キー制約は、それが適用される列の値が、それが参照する列にすでに存在している必要があることを要求することによって、2つのテーブル間の関係を表現する方法です。 次の例では、FOREIGN KEY制約では、showsテーブルのclientID列に追加された値が、clientテーブルのclientID列。

次の5つの列を持つclientsという名前のテーブルを作成します。

  1. CREATE TABLE shows
  2. (showID int PRIMARY KEY,
  3. showDate date,
  4. clientID int,
  5. attendance int,
  6. ticketPrice decimal (4,2),
  7. CONSTRAINT client_fk
  8. FOREIGN KEY (clientID)
  9. REFERENCES clients(clientID)
  10. );

この例では、外部キー制約の名前client_fkが提供されていることに注意してください。 MySQLは、追加した制約の名前を自動的に生成しますが、後でこの制約を参照する必要がある場合は、ここで名前を定義すると便利です。

次に、次のINSERT INTOステートメントを実行して、clientsテーブルに5行のサンプルデータをロードします。

  1. INSERT INTO clients
  2. VALUES
  3. (1, 'Gladys', 'song and dance', 180),
  4. (2, 'Catherine', 'standup', 99.99),
  5. (3, 'Georgeanna', 'standup', 45),
  6. (4, 'Wanda', 'song and dance', 200),
  7. (5, 'Ann', 'trained squirrel', 79.99);

次に、別のINSERT INTOステートメントを実行して、showsテーブルに10行のサンプルデータをロードします。

  1. INSERT INTO shows
  2. VALUES
  3. (1, '2019-12-25', 4, 124, 15),
  4. (2, '2020-01-11', 5, 84, 29.50),
  5. (3, '2020-01-17', 3, 170, 12.99),
  6. (4, '2020-01-31', 5, 234, 14.99),
  7. (5, '2020-02-08', 1, 86, 25),
  8. (6, '2020-02-14', 3, 102, 39.5),
  9. (7, '2020-02-15', 2, 101, 26.50),
  10. (8, '2020-02-27', 2, 186, 19.99),
  11. (9, '2020-03-06', 4, 202, 30),
  12. (10, '2020-03-07', 5, 250, 8.99);

これで、ガイドの残りの部分に従い、SQLを使用してデータを更新する方法について学習する準備が整いました。

単一のテーブルのデータを更新する

UPDATEステートメントの一般的な構文は次のようになります。

  1. UPDATE table_name
  2. SET column_name = value_expression
  3. WHERE conditions_apply;

UPDATEキーワードの後には、更新するデータを格納するテーブルの名前が続きます。 その後、SET句があり、どの列のデータをどのように更新するかを指定します。 SET句は、指定された列の値を、指定した値式と同じに設定するものと考えてください。

SQLでは、値式(スカラー式とも呼ばれます)は、更新されるすべての行に対して単一の値を返す任意の式です。 これは、文字列リテラル、または列内の既存の数値に対して実行される数学演算である可能性があります。 すべてのUPDATEステートメントに少なくとも1つの値の割り当てを含める必要がありますが、複数の列のデータを更新するために複数の値の割り当てを含めることができます。

SET句の後には、WHERE句があります。 この構文例のようにUPDATEステートメントにWHERE句を含めると、更新したくない行を除外できます。 WHERE句は、UPDATEステートメントでは完全にオプションですが、これを含めない場合、操作はテーブルのすべての行を更新します。

SQLがUPDATE操作を処理する方法を説明するために、clientsテーブルのすべてのデータを確認することから始めます。 次のクエリには、テーブルのすべての列を表すSQLの省略形であるアスタリスク(*)が含まれているため、このクエリはclientsテーブルのすべての列からすべてのデータを返します。

  1. SELECT * FROM clients;
Output
+----------+------------+------------------+-------------+ | clientID | name | routine | standardFee | +----------+------------+------------------+-------------+ | 1 | Gladys | song and dance | 180.00 | | 2 | Catherine | standup | 99.99 | | 3 | Georgeanna | standup | 45.00 | | 4 | Wanda | song and dance | 200.00 | | 5 | Ann | trained squirrel | 79.99 | +----------+------------+------------------+-------------+ 5 rows in set (0.00 sec)

たとえば、キャサリンの名前のつづりが間違っていることに気付いたとします。名前は「K」で始まるはずですが、表では「C」で始まるので、次のUPDATEを実行してその値を変更することにします。声明。 この操作は、Catherineという名前の行のname値をKatherineに変更することにより、name列の値を更新します。

  1. UPDATE clients
  2. SET name = 'Katherine'
  3. WHERE name = 'Catherine';
Output
Query OK, 1 row affected (0.01 sec) Rows matched: 1 Changed: 1 Warnings: 0

この出力は、1つの行のみが更新されたことを示しています。 これは、前のSELECTクエリを再度実行することで確認できます。

  1. SELECT * FROM clients;
Output
+----------+------------+------------------+-------------+ | clientID | name | routine | standardFee | +----------+------------+------------------+-------------+ | 1 | Gladys | song and dance | 180.00 | | 2 | Katherine | standup | 99.99 | | 3 | Georgeanna | standup | 45.00 | | 4 | Wanda | song and dance | 200.00 | | 5 | Ann | trained squirrel | 79.99 | +----------+------------+------------------+-------------+ 5 rows in set (0.00 sec)

この出力は、以前はCatherineと表示されていた値が実際にKatherineに変更されたことを示しています。

この例では、name列の値を1つだけ更新しました。 ただし、排他的でないWHERE句を使用して、複数の値を更新できます。

説明のために、スタンダップコメディや歌と踊りのルーチンを実行するすべてのクライアントに対して標準の成功報酬を交渉するとします。 次のステートメントは、standardFee列の値を、140と等しく設定することによって更新します。

この例のWHERE句にはLIKE演算子が含まれているため、routine値が指定されたワイルドカードと一致する各クライアントのperformanceFee値のみが更新されることに注意してください。パターン's%'。 つまり、ルーチンが文字「s」で始まるすべてのパフォーマーの成功報酬を更新します。

  1. UPDATE clients
  2. SET standardFee = 140
  3. WHERE routine LIKE 's%';
Output
Query OK, 4 rows affected (0.00 sec) Rows matched: 4 Changed: 4 Warnings: 0

clientsテーブルの内容をもう一度クエリすると、結果セットは、4つのクライアントが同じ成功報酬を持っていることを確認します。

  1. SELECT * FROM clients;
Output
+----------+------------+------------------+-------------+ | clientID | name | routine | standardFee | +----------+------------+------------------+-------------+ | 1 | Gladys | song and dance | 140.00 | | 2 | Katherine | standup | 140.00 | | 3 | Georgeanna | standup | 140.00 | | 4 | Wanda | song and dance | 140.00 | | 5 | Ann | trained squirrel | 79.99 | +----------+------------+------------------+-------------+ 5 rows in set (0.00 sec)

テーブル内のいずれかの列に数値が含まれている場合は、SET句の算術演算を使用してそれらを更新できます。 たとえば、クライアントの成功報酬ごとに40%の増額を交渉するとします。 これをclientsテーブルに反映するには、次のようなUPDATE操作を実行できます。

  1. UPDATE clients
  2. SET standardFee = standardFee * 1.4;
Output
Query OK, 5 rows affected, 1 warning (0.00 sec) Rows matched: 5 Changed: 5 Warnings: 1

:この出力は、更新によって警告が発生したことを示していることに注意してください。 多くの場合、MySQLは、列またはテーブルの定義のためにデータに変更を加えることを余儀なくされたときに警告を発行します。

MySQLには、受信した警告の説明に役立つSHOW WARNINGSショートカットが用意されています。

  1. SHOW WARNINGS;
Output
+-------+------+--------------------------------------------------+ | Level | Code | Message | +-------+------+--------------------------------------------------+ | Note | 1265 | Data truncated for column 'standardFee' at row 5 | +-------+------+--------------------------------------------------+ 1 row in set (0.00 sec)

この出力は、データベースシステムが新しいstandardFee値の1つを切り捨てて、decimal形式に準拠する必要があるために警告を発行したことを通知します。5桁で、小数点—以前に定義されています。

clientsテーブルをもう一度クエリして、各クライアントの成功報酬が40%増加したことを確認します。

  1. SELECT * FROM clients;
Output
+----------+------------+------------------+-------------+ | clientID | name | routine | standardFee | +----------+------------+------------------+-------------+ | 1 | Gladys | song and dance | 196.00 | | 2 | Katherine | standup | 196.00 | | 3 | Georgeanna | standup | 196.00 | | 4 | Wanda | song and dance | 196.00 | | 5 | Ann | trained squirrel | 111.99 | +----------+------------+------------------+-------------+ 5 rows in set (0.00 sec)

前述のように、単一のUPDATEステートメントを使用して複数の列のデータを更新することもできます。 これを行うには、更新するすべての列を指定し、それぞれにそれぞれの値式を続けてから、各列と値式のペアをコンマで区切る必要があります。

たとえば、クライアントが演奏する会場で、GeorgeannaとWandaのすべてのショーの参加者数が誤って報告されていたことがわかったとします。 偶然にも、あなたは彼らの公演ごとに間違ったチケット価格を入力したこともありました。

showsテーブルのデータを更新する前に、次のクエリを実行して、現在そのテーブルに保持されているすべてのデータを取得します。

  1. SELECT * FROM shows;
Output
+--------+------------+----------+------------+-------------+ | showID | showDate | clientID | attendance | ticketPrice | +--------+------------+----------+------------+-------------+ | 1 | 2019-12-25 | 4 | 124 | 15.00 | | 2 | 2020-01-11 | 5 | 84 | 29.50 | | 3 | 2020-01-17 | 3 | 170 | 12.99 | | 4 | 2020-01-31 | 5 | 234 | 14.99 | | 5 | 2020-02-08 | 1 | 86 | 25.00 | | 6 | 2020-02-14 | 3 | 102 | 39.50 | | 7 | 2020-02-15 | 2 | 101 | 26.50 | | 8 | 2020-02-27 | 2 | 186 | 19.99 | | 9 | 2020-03-06 | 4 | 202 | 30.00 | | 10 | 2020-03-07 | 5 | 250 | 8.99 | +--------+------------+----------+------------+-------------+ 10 rows in set (0.01 sec)

実際の数と価格を反映するには、テーブルを更新して、各パフォーマンスに20人の参加者を追加し、各ticketPrice値を50%増やします。 次のような操作でこれを行うことができます。

  1. UPDATE shows
  2. SET attendance = attendance + 20,
  3. ticketPrice = ticketPrice * 1.5
  4. WHERE clientID IN
  5. (SELECT clientID
  6. FROM clients
  7. WHERE name = 'Georgeanna' OR name = 'Wanda');
Output
Query OK, 4 rows affected, 1 warning (0.00 sec) Rows matched: 4 Changed: 4 Warnings: 1

この例では、WHERE句でサブクエリを使用して、clientsテーブルからGeorgeannaとWandaのclientID値を返すことに注意してください。 多くの場合、識別番号などの抽象的な値は覚えにくい場合がありますが、サブクエリを使用して値を見つけるこの方法は、問題のレコードに関する特定の属性しか知らない場合に役立ちます。

showsテーブルを更新した後、もう一度クエリを実行して、変更が期待どおりに行われたことを確認します。

  1. SELECT * FROM shows;
Output
+--------+------------+----------+------------+-------------+ | showID | showDate | clientID | attendance | ticketPrice | +--------+------------+----------+------------+-------------+ | 1 | 2019-12-25 | 4 | 144 | 22.50 | | 2 | 2020-01-11 | 5 | 84 | 29.50 | | 3 | 2020-01-17 | 3 | 190 | 19.49 | | 4 | 2020-01-31 | 5 | 234 | 14.99 | | 5 | 2020-02-08 | 1 | 86 | 25.00 | | 6 | 2020-02-14 | 3 | 122 | 59.25 | | 7 | 2020-02-15 | 2 | 101 | 26.50 | | 8 | 2020-02-27 | 2 | 186 | 19.99 | | 9 | 2020-03-06 | 4 | 222 | 45.00 | | 10 | 2020-03-07 | 5 | 250 | 8.99 | +--------+------------+----------+------------+-------------+ 10 rows in set (0.00 sec)

この場合も、この出力はUPDATEステートメントが正常に完了したことを示しています。

JOIN句を使用して複数のテーブルのデータを更新する

これまで、このガイドでは、一度に1つのテーブルのデータを更新する方法のみを示してきました。 ただし、一部のSQL実装では、テーブルをJOIN句と一時的に組み合わせることにより、複数のテーブルの複数の列を更新できます。

JOIN句を使用して複数のテーブルを更新するために使用できる一般的な構文は次のとおりです。

  1. UPDATE table_1 JOIN table_2
  2. ON table_1.related_column = table_2.related_column
  3. SET table_1.column_name = value_expression,
  4. table_2.column_name = value_expression
  5. WHERE conditions_apply;

この構文例は、UPDATEキーワードで始まり、JOIN句で区切られた2つのテーブルの名前が続きます。 続いてON句があり、クエリが2つのテーブルを結合する方法を説明しています。

ほとんどの実装では、SQL標準で「JOIN適格」データ型と呼ばれる列のセット間の一致を見つけることでテーブルを結合できます。 つまり、一般に、数値データを保持する任意の列を、それぞれのデータ型に関係なく、数値データを保持する他の列と結合できます。 同様に、文字値を保持する任意の列を、文字データを保持する他の列と結合できます。

JOIN句は複数のテーブルの内容を比較するため、この構文例では、列の名前の前にテーブルの名前とピリオドを付けて、各列を選択するテーブルを指定します。 これは、完全修飾列参照として知られています。 このように、どの操作でも列を選択するテーブルを指定できますが、これは通常、複数のテーブルを操作するときの明確さを向上させるためにのみ使用されます。

前に作成したサンプルテーブルで説明するには、次のUPDATEステートメントを実行します。 これにより、clientsテーブルとshowsテーブルがそれぞれのclientID列で結合され、GladysのレコードのroutineticketPriceの値が更新されます。 clientsテーブルとshowsテーブルにリストされている彼女の各パフォーマンス:

  1. UPDATE clients JOIN shows
  2. USING (clientID)
  3. SET clients.routine = 'mime',
  4. shows.ticketPrice = 30
  5. WHERE name = 'Gladys';
Output
Query OK, 2 rows affected (0.01 sec) Rows matched: 2 Changed: 2 Warnings: 0

この例では、前の構文例で使用したONキーワードではなく、USINGキーワードを使用してテーブルを結合していることに注意してください。 これが可能なのは、両方のテーブルに同様のデータ型を共有するclientID列があるためです。

JOIN操作の詳細なチュートリアルについては、SQLでの結合の使用方法に関するガイドを参照してください。

外部キーの変更UPDATEの動作

デフォルトでは、FOREIGN KEY制約との競合を引き起こすUPDATEステートメントは失敗します。

MySQLへの接続と前提条件のサンプルデータベースセクションのセットアップから、showsテーブルのclientID列がclientID列。 つまり、showsテーブルのclientID列に入力された値は、clientsテーブルの値にすでに存在している必要があります。

showsテーブルのclientID列にも表示されるclientsテーブルのレコードのclientID値を更新しようとすると、次のようになります。エラー:

  1. UPDATE clients
  2. SET clientID = 9
  3. WHERE name = 'Ann';
Output
ERROR 1217 (23000): Cannot delete or update a parent row: a foreign key constraint fails

このエラーを回避するには、既存の外部キー制約をUPDATE操作を異なる方法で処理する制約に置き換えます。

:すべてのリレーショナルデータベース管理システムまたはエンジンで、次の段落で概説するように、既存のテーブルに制約を追加または削除できるわけではありません。 MySQL以外のRDBMSを使用している場合は、その公式ドキュメントを参照して、制約を管理するための制限を理解する必要があります。

現在の制約を置き換えるには、最初にALTER TABLEステートメントで制約を削除する必要があります。 showsCREATE TABLEステートメントで、テーブルのFOREIGN KEY制約の名前としてclient_fkを定義したことを思い出してください。

  1. ALTER TABLE shows
  2. DROP FOREIGN KEY client_fk;
Output
Query OK, 0 rows affected (0.01 sec) Records: 0 Duplicates: 0 Warnings: 0

その後、特定のユースケースに適した方法でUPDATE操作を処理するように構成された新しい外部キー制約を作成します。 外部キーに違反するUPDATEステートメントを禁止するデフォルト設定の他に、ほとんどのRDBMSで使用可能な他の2つのオプションがあります。

この例では、ON UPDATE SET NULLは意味がありません。 結局のところ、クライアントの識別番号の1つを変更しても、clientsテーブルから削除しない場合でも、showsテーブルのパフォーマンスに関連付ける必要があります。 彼らの新しい識別番号は彼らのパフォーマンスの記録に反映されるべきであるため、ON UPDATE CASCADEオプションは私たちの目的にとってより理にかなっています。

ON UPDATE CASCADEの動作に続くFOREIGN KEY制約を追加するには、次のALTER TABLEステートメントを実行します。 これにより、new_client_fkという名前の新しい制約が作成されます。これは、以前の制約定義を複製しますが、ON UPDATE CASCADEオプションが含まれています。

  1. ALTER TABLE shows
  2. ADD CONSTRAINT new_client_fk
  3. FOREIGN KEY (clientID)
  4. REFERENCES clients (clientID)
  5. ON UPDATE CASCADE;
Output
Query OK, 10 rows affected (0.02 sec) Records: 10 Duplicates: 0 Warnings: 0

この出力は、操作がshowsテーブルの10行すべてに影響を与えたことを示しています。

:外部キーがUPDATE操作を処理する方法を変更するためにテーブルの定義を変更する代わりに、次のようにCREATE TABLEステートメントでこの動作を最初から定義できます。

  1. CREATE TABLE shows
  2. (showID int PRIMARY KEY,
  3. showDate date,
  4. clientID int,
  5. attendance int,
  6. ticketPrice decimal (4,2),
  7. CONSTRAINT client_fk
  8. FOREIGN KEY (clientID)
  9. REFERENCES clients(clientID)
  10. ON UPDATE CASCADE
  11. );

その後、clientsテーブルの任意のレコードのclientID値を更新できます。これらの変更は、showsテーブルの任意の行にカスケードされます。それを参照してください:

  1. UPDATE clients
  2. SET clientID = 9
  3. WHERE name = 'Ann';
Output
Query OK, 1 row affected (0.01 sec) Rows matched: 1 Changed: 1 Warnings: 0

この出力は、1つの行にのみ影響することを示していますが、Annに関連付けられたshowsテーブルのパフォーマンスレコードのclientID値も更新されます。 これを確認するには、次のクエリを実行して、showsテーブルからすべてのデータを取得します。

  1. SELECT * FROM shows;
Output
+--------+------------+----------+------------+-------------+ | showID | showDate | clientID | attendance | ticketPrice | +--------+------------+----------+------------+-------------+ | 1 | 2019-12-25 | 4 | 144 | 22.50 | | 2 | 2020-01-11 | 9 | 84 | 29.50 | | 3 | 2020-01-17 | 3 | 190 | 19.49 | | 4 | 2020-01-31 | 9 | 234 | 14.99 | | 5 | 2020-02-08 | 1 | 86 | 30.00 | | 6 | 2020-02-14 | 3 | 122 | 59.25 | | 7 | 2020-02-15 | 2 | 101 | 26.50 | | 8 | 2020-02-27 | 2 | 186 | 19.99 | | 9 | 2020-03-06 | 4 | 222 | 45.00 | | 10 | 2020-03-07 | 9 | 250 | 8.99 | +--------+------------+----------+------------+-------------+ 10 rows in set (0.00 sec)

予想どおり、clientsテーブルのclientID列に加えられた更新は、showsテーブルの関連する行にカスケードされました。

結論

このガイドを読むことで、SQLのUPDATEステートメントを使用して複数のテーブルの既存のレコードを変更する方法を学びました。 また、SQLが外部キー制約と競合するUPDATE操作を処理する方法、およびそのデフォルトの動作を変更する方法についても学びました。

ここで概説するコマンドは、SQLを使用するすべてのデータベース管理システムで機能するはずです。 すべてのSQLデータベースは独自の言語実装を使用しているため、UPDATE操作の処理方法と使用可能なオプションの詳細については、DBMSの公式ドキュメントを参照してください。

SQLの操作について詳しく知りたい場合は、SQLの使用方法に関するこのシリーズの他のチュートリアルを確認することをお勧めします。

モバイルバージョンを終了