SQL コマンドは、プログラミングをせずにデータベースを操作できるため急速に広まりました。
本記事では、よく利用する SQL コマンドを上から順にコピペして実行することで、SQL を理解できる構成にしています。
関連記事:データベースの基礎知識 | |||
---|---|---|---|
DDL (Data Definition Language/データ定義言語)
DDL には主に、以下の 3 種類の SQL コマンドが存在します。
CREATE 文 (作成)
CREATE DATABASE データベース名;
+--------------------+
| Database |
+--------------------+
| db |
| information_schema |
| mysql |
| performance_schema |
| sys |
+--------------------+
PostgreSQL でデータベースを確認する場合
List of databases Name | Owner | Encoding | Collate | Ctype | Access privileges -----------+----------+----------+-------------+-------------+----------------------- db | postgres | UTF8 | ja_JP.UTF-8 | ja_JP.UTF-8 | postgres | postgres | UTF8 | ja_JP.UTF-8 | ja_JP.UTF-8 |
データベース (db) が作成できていることが確認できます。
以降、データベース (db) を使用するために、MySQL では次のコマンドを実行します。
CREATE TABLE テーブル名(列名1 データ型1, 列名2 データ型2...)
+--------------+ | Tables_in_db | +--------------+ | tbl | +--------------+
tbl という名前のテーブルが作成できています。
+----------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------+-------------+------+-----+---------+-------+ | id | int | YES | | NULL | | | str | varchar(10) | YES | | NULL | | +-------+-------------+------+-----+---------+-------+
PostgreSQL でテーブルの存在と構造を確認
List of relations Schema | Name | Type | Owner --------+------+-------+---------- public | tbl | table | postgres
tbl という名前のテーブルが作成できています。
Table "public.tbl" Column | Type | Modifiers --------+-----------------------+----------- id | integer | str | character varying(10) |
CREATE USER 'ユーザー名'@'ホスト名' IDENTIFIED BY 'パスワード'
Postgres でユーザーを作成する場合
List of roles
Role name | Attributes | Member of
-----------+------------------------------------------------+-----------
hogetech | | {}
postgres | Superuser, Create role, Create DB, Replication | {}
+----------+-----------+ | user | host | +----------+-----------+ | hogetech | localhost | | mysql.sys| localhost | +----------+-----------+
ユーザーが作成されていることを確認できます。
ALTER 文 (変更)
ALTER TABLE テーブル名 ADD COLUMN 列名;
※MySQL では、8.0 からの機能 (詳しくはここ)
+------------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+------------+-------------+------+-----+---------+-------+
| id | int(11) | YES | | NULL | |
| str | varchar(10) | YES | | NULL | |
| add_column | char(5) | YES | | NULL | |
+------------+-------------+------+-----+---------+-------+
PostgreSQL でテーブルの構造を確認
Table "public.tbl"
Column | Type | Modifiers
------------+-----------------------+-----------
id | integer |
str | character varying(10) |
add_column | character(5) |
テーブル (tbl) に、列 (add_column) を追加したことが確認できます。
ALTER TABLE テーブル名 RENAME COLUMN 変更前の列名 TO 変更後の列名;
+------------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+---------------+-------------+------+-----+---------+-------+
| id | int(11) | YES | | NULL | |
| str | varchar(10) | YES | | NULL | |
| rename_column | char(5) | YES | | NULL | |
+------------+-------------+------+-----+---------+-------+
PostgreSQL でテーブルの構造を確認
Table "public.tbl"
Column | Type | Modifiers
------------+-----------------------+-----------
id | integer |
str | character varying(10) |
rename_column | character(5) |
ALTER TABLE テーブル名 DROP COLUMN 列名;
+------------+-------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +------------+-------------+------+-----+---------+-------+ | id | int(11) | YES | | NULL | | | str | varchar(10) | YES | | NULL | | +------------+-------------+------+-----+---------+-------+
PostgreSQL でテーブルの構造を確認
Table "public.tbl" Column | Type | Modifiers ------------+-----------------------+----------- id | integer | str | character varying(10) |
テーブルから rename_column が削除されたことを確認できます。
DROP 文 (削除)
DROP TABLE テーブル名;
Empty set (0.00 sec)
PostgreSQL でテーブルの構造を確認
No relations found.
テーブル(tbl) が削除されたことを確認できます。
DROP DATABASE データベース名;
+--------------------+ | Database | +--------------------+ | information_schema | | mysql | | performance_schema | | sys | +--------------------+
PostgreSQL でテーブルの構造を確認
Name | Owner | Encoding | Collate | Ctype | Access privileges -----------+----------+----------+-------------+-------------+----------------------- postgres | postgres | UTF8 | ja_JP.UTF-8 | ja_JP.UTF-8 | template0 | postgres | UTF8 | ja_JP.UTF-8 | ja_JP.UTF-8 | =c/postgres + | | | | | postgres=CTc/postgres template1 | postgres | UTF8 | ja_JP.UTF-8 | ja_JP.UTF-8 | =c/postgres + | | | | | postgres=CTc/postgres
データベース (db) が削除されたことを確認できます。
DROP USER 'ユーザー名'@'ホスト名';
PostgreSQL でユーザーを削除する場合
Role name | (中略)
-----------+-------
postgres | (中略)
hogetech | (中略)
Role name | (中略) -----------+------- postgres | (中略)
DML (Data Manipulation Language/データ操作言語)
DML には主に、以下の 4 種類の SQL コマンドが存在します。
以降の説明で利用するテーブル
※ USE db は MySQL のみ。PostgreSQL では不要
INSERT 文 (挿入)
INSERT INTO テーブル名 VALUES(列の値1, 列の値2...)
挿入した結果は、次に紹介する SELECT 文で確認できます。
「ERROR 1146 (42S02): Table 'db.tbl' doesn't exist」が発生した場合
「ERROR: リレーション"tbl"は存在しません」が発生した場合
テーブル (tbl) が存在しません。テーブルの作成をしてください。
SELECT 文 (取得)
SELECT 列名 FROM テーブル名
全ての列を取得する場合は * を使います。
+------+------+ | id | str | +------+------+ | 1 | hoge | +------+------+
SELECT 列名 FROM テーブル名 WHERE 条件
+------+------+
| id | str |
+------+------+
| 1 | hoge |
+------+------+
+------+------+ | id | str | +------+------+ | 1 | hoge | | 2 | foo | +------+------+
WHERE 句で、id = 1 の行のみを取得できました。
SELECT DISTINCT 列名 FROM テーブル名
+------+------+
| id | str |
+------+------+
| 1 | hoge |
| 2 | foo |
+------+------+
+------+------+ | id | str | +------+------+ | 1 | hoge | | 2 | foo | | 2 | foo | +------+------+
重複している行が削除されていいます。
SELECT 列名 FROM テーブル名 GROUP BY 集約条件
+------+------+
| id | str |
+------+------+
| 1 | hoge |
| 2 | foo |
+------+------+
+------+------+ | id | str | +------+------+ | 1 | hoge | | 2 | foo | | 2 | foo | +------+------+
重複する行を集約していることが確認できます。
DISTINCT と GROUP BY の違い
DISTINCT と GROUP BY の違いは以下のとおりです。
DISTINCT | GROUP BY | |
---|---|---|
句の説明 | 取得した行から、重複を削除 | 取得した行を、グループ化して集計 |
重複削除 | ◯ | △ (できるが、全ての列を書く必要があり面倒) |
集計関数 | × | ◯ |
今回は合計を求める集計関数 SUM() を例に説明します。(集計関数の一覧はこちら)
+------+---------+
| str | SUM(id) |
+------+---------+
| foo | 4 |
| hoge | 1 |
+------+---------+
+------+------+ | id | str | +------+------+ | 1 | hoge | | 2 | foo | | 2 | foo | +------+------+
同じ str を持つ id の合計が表示されます。
SELECT 列名 FROM テーブル名 GROUP BY 集約条件 HAVING 表示条件
+------+------+
| id | str |
+------+------+
| 2 | foo |
+------+------+
+------+------+
| id | str |
+------+------+
| 1 | hoge |
| 2 | foo |
+------+------+
HAVING で指定した id = 2 のみを取得できます。
HAVING と WHERE の違い
HAVING と WHERE は式の評価順が異なります。
句の式の評価順は以下のとおりです。
- WHERE
- GROUP BY (集計関数)
- HAVING
そのため、GROUP BY を使う場合は HAVING、それ以外は WHEREを使います。
SELECT 列名 FROM テーブル名 ORDER BY 条件
+------+------+ | id | str | +------+------+ | 1 | hoge | | 2 | foo | | 2 | foo | +------+------+
+------+------+ | id | str | +------+------+ | 2 | foo | | 2 | foo | | 1 | hoge | +------+------+
WINDOW 関数 (分析関数)
Window 関数は各行に対して計算を実行する関数で、MySQL 8.0 では以下の関数を指します。
名前 | 説明 |
---|---|
CUME_DIST() | 累積分布値 |
DENSE_RANK() | パーティション内の現在の行のランク (ギャップなし) |
FIRST_VALUE() | ウィンドウフレームの最初の行からの引数の値 |
LAG() | パーティション内の現在行より遅れている行の引数の値 |
LAST_VALUE() | ウィンドウフレームの最後の行からの引数の値 |
LEAD() | パーティション内の現在の行の先頭行からの引数の値 |
NTH_VALUE() | ウィンドウフレームの N 番目の行からの引数の値 |
NTILE() | パーティション内の現在の行のバケット番号。 |
PERCENT_RANK() | パーセントランク値 |
RANK() | パーティション内の現在の行のランク (ギャップあり) |
ROW_NUMBER() | パーティション内の現在の行数 |
Window 関数で計算した結果の表示方法は、OVER 句を利用して指定する必要があります。
■ 今回は、1行前の行を表示する LAG() Window 関数を例に説明します。
+------+---------------------------+ | id | LAG(id) OVER(ORDER by id) | +------+---------------------------+ | 1 | NULL | | 2 | 1 | | 2 | 2 | +------+---------------------------+
「LAG(id)」は、id の1行前の値を表示していることがわかります。
■ Window 関数を複数利用すると、毎回同じ OVER 句を記載する必要があります。
+------+----------------------------+------+-----------------------------+ | id | LAG(id) OVER (ORDER BY id) | str | LAG(str) OVER (ORDER BY id) | +------+----------------------------+------+-----------------------------+ | 1 | NULL | hoge | NULL | | 2 | 1 | foo | hoge | | 2 | 2 | foo | foo | +------+----------------------------+------+-----------------------------+
この Window 関数で何度も同じ OVER 句の記載を避けるために、定義した条件を使い回す方法が「名前付きウィンドウ(WINDOW 句)」です。
■ 名前付きウィンドウは「SELECT <Window 関数> OVER <名前付きウィンドウで定義した名前> FROM <テーブル> WINDOW <名前付きウィンドウ>」で利用できます。
+------+----------------+------+-----------------+ | id | LAG(id) OVER w | str | LAG(str) OVER w | +------+----------------+------+-----------------+ | 1 | NULL | hoge | NULL | | 2 | 1 | foo | hoge | | 2 | 2 | foo | foo | +------+----------------+------+-----------------+
SELECT 列名 FROM テーブル名 LIMIT 行数
+------+------+ | id | str | +------+------+ | 1 | hoge | | 2 | foo | +------+------+
+------+------+ | id | str | +------+------+ | 1 | hoge | | 2 | foo | | 2 | foo | +------+------+
2行しか表示されなくなりました。
INSERT INTO 挿入先テーブル名 SELECT 列名 FROM ソーステーブル名
+------+------+ | id | str | +------+------+ | 1 | hoge | | 2 | foo | | 2 | foo | +------+------+
SELECT 列名 FROM テーブル名1 JOIN テーブル名2
JOIN には次の 5 種類が存在し、SELECT, UPDATE, DELETE 文で利用できます。
以降の JOIN の説明では、以下のテーブルを使います。
+------+------+------+----------+ | id | str | id | str | +------+------+------+----------+ | 1 | hoge | 1 | 1another | | 2 | foo | 1 | 1another | | 2 | foo | 1 | 1another | | 1 | hoge | 2 | 2another | | 2 | foo | 2 | 2another | | 2 | foo | 2 | 2another | | 1 | hoge | 3 | 3another | | 2 | foo | 3 | 3another | | 2 | foo | 3 | 3another | +------+------+------+----------+
+------+------+
| id | str |
+------+------+
| 1 | hoge |
| 2 | foo |
| 2 | foo |
+------+------+
+------+----------+
| id | str |
+------+----------+
| 1 | 1another |
| 2 | 2another |
| 3 | 3another |
+------+----------+
+------+------+------+----------+ | id | str |id | str | +------+------+------+----------+ | 1 | hoge | 1 | 1another | | 2 | foo | 2 | 2another | | 2 | foo | 2 | 2another | +------+------+------+----------+
+------+------+
| id | str |
+------+------+
| 1 | hoge |
| 2 | foo |
| 2 | foo |
+------+------+
+------+----------+
| id | str |
+------+----------+
| 1 | 1another |
| 2 | 2another |
| 3 | 3another |
+------+----------+
+------+------+------+----------+ | id | str | id | str | +------+------+------+----------+ | 1 | hoge | 1 | 1another | | 2 | foo | 2 | 2another | | 2 | foo | 2 | 2another | +------+------+------+----------+
+------+------+
| id | str |
+------+------+
| 1 | hoge |
| 2 | foo |
| 2 | foo |
+------+------+
+------+----------+
| id | str |
+------+----------+
| 1 | 1another |
| 2 | 2another |
| 3 | 3another |
+------+----------+
+------+------+------+----------+ | id | str | id | str | +------+------+------+----------+ | 1 | hoge | 1 | 1another | | 2 | foo | 2 | 2another | | 2 | foo | 2 | 2another | | NULL | NULL | 3 | 3another | +------+------+------+----------+
+------+------+
| id | str |
+------+------+
| 1 | hoge |
| 2 | foo |
| 2 | foo |
+------+------+
+------+----------+
| id | str |
+------+----------+
| 1 | 1another |
| 2 | 2another |
| 3 | 3another |
+------+----------+
※MySQL では、現時点で FULL OUTER JOIN がサポートされていません。
id | str | id | str
----+------+----+----------
1 | hoge | 1 | 1another
2 | foo | 2 | 2another
2 | foo | 2 | 2another
| | 3 | 3another
+------+------+
| id | str |
+------+------+
| 1 | hoge |
| 2 | foo |
| 2 | foo |
+------+------+
+------+----------+
| id | str |
+------+----------+
| 1 | 1another |
| 2 | 2another |
| 3 | 3another |
+------+----------+
SELECT 列名1 FROM テーブル名1 UNION SELECT 列名2 FROM テーブル名2
+------+----------+ | id | str | +------+----------+ | 1 | hoge | | 2 | foo | | 1 | 1another | | 2 | 2another | | 3 | 3another | +------+----------+
+------+------+
| id | str |
+------+------+
| 1 | hoge |
| 2 | foo |
| 2 | foo |
+------+------+
+------+----------+
| id | str |
+------+----------+
| 1 | 1another |
| 2 | 2another |
| 3 | 3another |
+------+----------+
UNION は重複が排除されます。重複を含む場合は、UNION ALL を利用します。
+------+----------+ | id | str | +------+----------+ | 1 | hoge | | 2 | foo | | 2 | foo | | 1 | 1another | | 2 | 2another | | 3 | 3another | +------+----------+
SELECT 列名1 FROM テーブル名1 WHERE 列名1 = (SELECT 列名2 FROM テーブル名2);
A query is a synonym for a SELECT statement.
https://stackoverflow.com/questions/4735856/difference-between-a-statement-and-a-query-in-sql
A statement is any SQL command such as SELECT, INSERT, UPDATE, DELETE.
Queries, which retrieve data based on specific criteria.
Statements, which may have a persistent effect on schemas and data, or which may control transactions, program flow, connections, sessions, or diagnostics.
クエリー
SQL で、1 つ以上のテーブルから情報を読み取る操作。歴史的な理由から、ステートメントの内部処理のディスカッションでは、DDL ステートメントや DML ステートメントなどの他のタイプの MySQL ステートメントを含む、より広範な意味で 「query」 が使用される場合があります。
https://dev.mysql.com/doc/refman/8.0/ja/glossary.html#glos_query
+------+------+
| id | str |
+------+------+
| 1 | hoge |
+------+------+
+------+------+
| id | str |
+------+------+
| 1 | hoge |
| 2 | foo |
| 2 | foo |
+------+------+
+------+----------+
| id | str |
+------+----------+
| 1 | 1another |
| 2 | 2another |
| 3 | 3another |
+------+----------+
UPDATE テーブル名 SET 列名=値 WHERE 条件
+------+------+
| id | str |
+------+------+
| 1 | hoge |
| 2 | foo |
| 2 | foo |
+------+------+
+------+--------+
| id | str |
+------+--------+
| 1 | update |
| 2 | foo |
| 2 | foo |
+------+--------+
DELETE FROM テーブル名 WHERE 行の条件
+------+--------+ | id | str | +------+--------+ | 1 | update | | 2 | foo | | 2 | foo | +------+--------+
+------+--------+ | id | str | +------+--------+ | 1 | update | +------+--------+
DCL (Data Control Language/データ制御言語)
DCL に相当する SQL コマンドの例は以下のとおりです。
- GRANT (ユーザーに権限を与える)
- REVOKE (ユーザーから権限を取り消す)
GRANT 権限 ON 権限レベル TO 'ユーザー'@'ホスト'
Postgres で権限を割り当てる場合
ERROR: ロール"hogetech"は存在しません が発生した場合
ユーザーが存在しない可能性があります。ユーザーを作成してください。
postgres=# \dp
Access privileges
Schema | Name | Type | Access privileges | Column access privileges
--------+---------+-------+---------------------------+--------------------------
public | another | table | |
public | tbl | table | postgres=arwdDxt/postgres+|
| | | hogetech=r/postgres |
public | tbl2 | table | |
別の端末から作成したユーザーでログインし、GRANT の動作確認をしてみます。
ERROR: リレーション tbl への権限がありません
+------+--------+ | id | str | +------+--------+ | 1 | update | +------+--------+
ERROR 1819 (HY000): Your password does not satisfy the current policy requirements が発生した場合
ユーザーが存在しない可能性があります。ユーザーを作成してください。
+------------------------------------------------------+ | Grants for hogetech@localhost | +------------------------------------------------------+ | GRANT USAGE ON *.* TO `hogetech`@`localhost` | | GRANT SELECT ON `db`.`tbl` TO `hogetech`@`localhost` | +------------------------------------------------------+
別の端末から作成したユーザーでログインし、GRANT の動作確認をしてみます。
ERROR 1142 (42000): SELECT command denied to user 'hogetech'@'localhost' for table 'tbl'
+------+--------+ | id | str | +------+--------+ | 1 | update | +------+--------+
権限を付与していないテーブルに対する操作は、DENIED となることを確認できました。
REVOKE 権限 ON 権限レベル FROM 'ユーザー'@'ホスト'
Postgres から権限を取り消す場合
[ RECORD 2 ]------------+--------------------------
Schema | public
Name | tbl
Type | table
Access privileges| postgres=arwdDxt/postgres
| hogetech=r/postgres
[ RECORD 2 ]------------+-------------------------- Schema | public Name | tbl Type | table Access privileges| postgres=arwdDxt/postgres
+------------------------------------------------------+ | Grants for hogetech@localhost | +------------------------------------------------------+ | GRANT USAGE ON *.* TO `hogetech`@`localhost` | | GRANT SELECT ON `db`.`tbl` TO `hogetech`@`localhost` | +------------------------------------------------------+
TCL(TransactionControlLanguage/トランザクション制御言語)
- BEGIN (トランザクションの開始)
- COMMIT (トランザクションの確定)
- ROLLBACK (トランザクションの取り消し)
- SAVEPOINT (任意にロールバック地点を設定する)
- LOCK (テーブルなどの資源を占有する)
BEGIN
トランザクションを使う利点は、以下の記事にまとめています。
トランザクション分離レベルに応じて、他のトランザクションに影響を分離します。
例えば、トランザクション分離レベルが READ-COMMITTED の場合、2つのトランザクションは以下のとおりとなります。
+------+--------+ | id | str | +------+--------+ | 1 | update | | 2 | test | +------+--------+
+------+--------+ | id | str | +------+--------+ | 1 | update | | 2 | test | | 3 | foo | +------+--------+
この状態で2つ目の端末(トランザクション2)でログインし、テーブルを確認します。
+------+--------+ | id | str | +------+--------+ | 1 | update | | 2 | test | +------+--------+
トランザクション2※では、トランザクション1の INSERT の結果がまだ反映されていません。
※BEGIN をしてない場合、1行ごとにトランザクション(BEGIN = START TRANSACTION)が実行される扱いとなります。
デフォルトでは、MySQL は自動コミットモードが有効になった状態で動作します。 つまり、特にトランザクション内にない場合、各ステートメントは
https://dev.mysql.com/doc/refman/8.0/ja/commit.htmlSTART TRANSACTION
およびCOMMIT
で囲まれているかのようにアトミックです。
GRANT 権限 ON 権限レベル TO 'ユーザー'@'ホスト'
COMMIT
COMMIT は、現在のトランザクションの変更を永続的なものにします。
これにより、Atomicity (原始性) と Durability (永続性) を実現します。
なお、Atomicity (原始性) と Durability (永続性) については以下の記事で紹介しています。
先程の BEGIN で行ったトランザクションの続きから開始します。
端末2(トランザクション2)でテーブルを確認します。
+------+--------+ | id | str | +------+--------+ | 1 | update | | 2 | test | +------+--------+
端末1(トランザクション1)で COMMITしてみます。
次に端末2(トランザクション2)でテーブルを確認します。
+------+--------+ | id | str | +------+--------+ | 1 | update | | 2 | test | | 3 | foo | +------+--------+
トランザクション1で INSERT した結果がトランザクション2に反映されました。
ROLLBACK (トランザクションの取り消し)
ROLLBACK
ROLLBACK は、現在のトランザクションの変更を取り消します。
これにより、Atomicity (原始性) を実現します。
なお、Atomicity (原始性) については以下の記事で紹介しています。
ロールバックの動作を確認するために、まずトランザクションで変更処理を行います。
+------+--------+ | id | str | +------+--------+ | 1 | update | | 2 | test | | 3 | foo | +------+--------+
+------+--------+ | id | str | +------+--------+ | 1 | update | | 2 | test | | 3 | foo | | 4 | bar | +------+--------+
トランザクションで変更したこの状態でロールバックします。
+------+--------+ | id | str | +------+--------+ | 1 | update | | 2 | test | | 3 | foo | +------+--------+
4行目の「4, bar」が消え、トランザクション開始時のテーブルにロールバックしていることを確認しました。
SET TRANSACTION (トランザクション分離レベルの設定)
SET <スコープ> TRANSACTION ISOLATION LEVEL <トランザクション分離レベル>
SET TRANSACTION ISOLATION LEVEL で、トランザクション分離レベルを指定できます。
トランザクション分離レベル (Isolation = トランザクションの分離性) については、以下の記事で説明しています。
+---------------------------------+ | @@SESSION.transaction_isolation | +---------------------------------+ | REPEATABLE-READ | +---------------------------------+
+---------------------------------+ | @@SESSION.transaction_isolation | +---------------------------------+ | READ-COMMITTED | +---------------------------------+
セッションのトランザクション分離レベルが READ-COMMITTED に変更できたことを確認しました。
SAVEPOINT (トランザクションセーブポイントの設定)
SAVEPOINT <セーブポイント名>
SAVEPOINT はトランザクションのセーブポイントを設定します。ロールバックした場合は(トランザクションの開始地点ではなく)、セーブポイントまで戻ります。
セーブポイントの動作を確認するために、まずトランザクションで変更処理を行います。
+------+--------+ | id | str | +------+--------+ | 1 | update | | 2 | test | | 3 | foo | +------+--------+
+------+--------+ | id | str | +------+--------+ | 1 | update | | 2 | test | | 3 | foo | | 4 | bar | +------+--------+
ここでセーブポイント save1 を設定します。
+------+--------+ | id | str | +------+--------+ | 1 | update | | 2 | test | | 3 | foo | | 4 | bar | | 5 | save | +------+--------+
セーブポイント save1 までロールバックします。
+------+--------+ | id | str | +------+--------+ | 1 | update | | 2 | test | | 3 | foo | | 4 | bar | +------+--------+
セーブポイントまでロールバックしていることを確認できました。
(トランザクション開始時まで戻っていません)
+------+--------+ | id | str | +------+--------+ | 1 | update | | 2 | test | | 3 | foo | +------+--------+
通常のロールバックにより、トランザクション開始時点まで戻りました。
LOCK TABLES (ロック取得)
LOCK TABLES <テーブル> <ロックタイプ>
LOCK TABLES は、テーブルロックを取得します。
ロックタイプが READ の場合、テーブルロックの動作は以下のとおりです。
ここから端末2で操作を行います。
+------+--------+ | id | str | +------+--------+ | 1 | update | | 2 | test | | 3 | foo | +------+--------+
ロックタイプが READ なので、読み込みは成功します。
次に書き込みを行います。
テーブルが端末1にロックされているので、いつまで経っても端末2の INSERT は完了しません。
UNLOCK TABLES (ロック解除)
UNLOCK TABLES
UNLOCK TABLES は、テーブルロックを解除します。
この作業は先程の LOCK 操作の続きです。
端末1の全てのテーブルのロックが解除されたため、端末2でロックされていた INSERT 処理が完了していることが確認できます。
関連記事
関連記事:データベースの基礎知識 | |||
---|---|---|---|