ITの教科書検索
入門読了 約10分

GRANT文・REVOKE文とは ― データベースの権限

GRANT文はデータベースの利用者に権限を与え、REVOKE文は取り消すSQL文です。権限を人に渡せるWITH GRANT OPTIONとCASCADEの連鎖、ビューで見せる列を絞る方法が分かります。

目次
  1. GRANT文・REVOKE文とは
  2. GRANT文の書き方と権限の種類
  3. REVOKE文で取り消す
  4. WITH GRANT OPTIONとCASCADE
  5. ビューで見せる列を絞る
  6. ロールと最小権限の原則
  7. DDL・DML・DCLの分類
  8. 練習問題

GRANT文は権限を与え、REVOKE文は権限を取り消すSQL文

GRANT文は、データベースの利用者に、表を読む・書き換えるなどの権限を与えるSQL文です。REVOKE文は、GRANT文で与えた権限を取り消すSQL文です。「社員の表は人事部だけが書き換えられる」「給与の列は一般の社員に見せない」といった決まりを、この2つの文とビューで設定します。

多くの利用者が同じ表を使うデータベースでは、利用者ごとに、どの表にどの操作を許すかを決めておく必要があります。この仕組みをアクセス制御と呼びます。GRANT文とREVOKE文は、その設定をSQLで書く文です。

PostgreSQLでは、表を作った利用者が所有者になり、所有者は最初からすべての権限を持ちます。管理者であるスーパーユーザーを除き、ほかの利用者は権限を与えられるまでその表を操作できません。SELECT文も、権限が無ければ拒否されます。

GRANT文の書き方は「GRANT 権限 ON 表 TO 利用者」

GRANT文には、与える権限・対象の表・相手の利用者の3つを書きます。次の文は、利用者Aに社員テーブルを読み出す権限を与えます。

GRANT SELECT ON 社員 TO A;

表を読み書きする権限の名前は、その権限で実行できるSQL文の名前と同じです。日本語では、これらを参照権限・挿入権限のように呼ぶこともあります。

日本語での呼び方とSQLの権限の対応
日本語での呼び方SQLの権限許す操作
参照権限SELECT行を読み出す
挿入権限INSERT行を追加する
データを更新する権限UPDATE行の値を書き換える
削除権限DELETE行を削除する

権限はカンマで区切って一度に複数を与えられ、相手も複数書けます。PostgreSQLでは、PUBLICを相手にすると、すべての利用者に与えます。PostgreSQLとMySQLは、列名を括弧で書いて、列ごとに権限を与えることもできます。

GRANT INSERT, UPDATE ON 社員 TO A, B;
GRANT SELECT ON 社員 TO PUBLIC;
GRANT SELECT (社員ID, 氏名) ON 社員 TO C;

表の権限をまとめて与えるときは、権限の名前の代わりにALL PRIVILEGESと書きます。PostgreSQLでは、SELECT・INSERT・UPDATE・DELETEを含め、表に付けられる権限がすべて付きます。PostgreSQLではPRIVILEGESを省いてALLとも書けますが、標準SQLではPRIVILEGESが必要です。

GRANT ALL PRIVILEGES ON 社員 TO A;
REVOKE ALL PRIVILEGES ON 社員 FROM A;

MySQLの文書では、ALL PRIVILEGESは指定した範囲の権限のうち、GRANT OPTIONとPROXYを除くすべてを指します。まとめて与えると、仕事に必要のない権限まで付くので注意が必要です。

PostgreSQLでは、WHERE句で列を読むUPDATE文やDELETE文を実行するには、SELECT権限も必要です。データベースに接続する権限は、PostgreSQLではCONNECTという権限で表します。利用者の指定のしかたなど、細かな書き方は製品によって違います。

REVOKE文は「REVOKE 権限 ON 表 FROM 利用者」で取り消す

REVOKE文の形はGRANT文とほぼ同じで、相手を書く語がTOからFROMに変わります。与えるときは利用者「へ」、取り消すときは利用者「から」と読むと区別できます。

REVOKE UPDATE ON 社員 FROM A;

取り消すのは指定した権限だけで、同じ利用者のほかの権限は残ります。次の図で、所有者がGRANT文とREVOKE文を順に実行したときの変化を確かめられます。

A・B・Cが試す4つの文

SELECT * FROM 社員;
INSERT INTO 社員 VALUES (104, '江藤', '営業', 260000);
UPDATE 社員 SET 部署 = '営業' WHERE 社員ID = 101;
DELETE FROM 社員 WHERE 社員ID = 103;

所有者が実行した文

-- まだGRANT文を実行していない
この時点で、A・B・Cが4つの文を実行した結果
文利用者A利用者B利用者C
SELECT参照× 拒否× 拒否× 拒否
INSERT挿入× 拒否× 拒否× 拒否
UPDATE更新× 拒否× 拒否× 拒否
DELETE削除× 拒否× 拒否× 拒否

表を作った所有者だけが操作できます。A・B・Cの文はすべて拒否されます。

枠の付いたマスは、1つ前の段から結果が変わったところです。拒否された文は、PostgreSQLでは「permission denied for table 社員」のエラーになります。

WITH GRANT OPTIONを付けると、受け取った権限をほかの利用者に渡せる

ふつうのGRANT文で権限を受け取った利用者は、その権限をほかの利用者に渡せません。GRANT文の最後にWITH GRANT OPTIONを付けると、受け取った利用者も同じ権限を与えられるようになります。PostgreSQLの文書は、PUBLICにはこの権利を与えられないと書いています。

-- 所有者が実行
GRANT SELECT ON 社員 TO A WITH GRANT OPTION;
-- Aが実行
GRANT SELECT ON 社員 TO B WITH GRANT OPTION;
-- Bが実行
GRANT SELECT ON 社員 TO C;

こうして渡した権限を取り消すとき、渡った先をどう扱うかをREVOKE文の最後で指定します。CASCADEは渡った先の権限もまとめて取り消し、RESTRICTは渡った先があれば取り消しを拒みます。

REVOKE SELECT ON 社員 FROM A CASCADE;
付与の連鎖CASCADEの後所有者変わらない利用者ASELECTなし利用者BSELECTなし利用者CSELECTなし再付与も可再付与も可付与のみ
左は、所有者からA、AからB、BからCへSELECT権限を渡した状態です。所有者がAからCASCADEで取り消すと、Aを通って渡ったB・Cの権限も消えます。

同じ状態でRESTRICTを指定すると、REVOKE文はエラーになり、A・B・Cの権限は残ります。標準SQLではどちらかの指定が必要ですが、PostgreSQLは省略するとRESTRICTとして扱います。MySQLのREVOKE文の構文には、CASCADEとRESTRICTがありません。

CASCADEで消えるのは、取り消した利用者を通って渡った権限だけです。たとえばCが所有者からも直接SELECT権限を受けていれば、Cはその権限で表を読み続けられます。

PostgreSQLでは、REVOKE文で取り消せるのは、自分が直接与えた権限だけです。前の例のCの権限はBが与えたものなので、所有者がCから取り消しても、エラーにならずに何も変わりません。Cから外すには、Bが自分で取り消すか、所有者がAの権限をCASCADEで取り消します。

-- 所有者が実行:Cの権限はBが与えたものなので残る
REVOKE SELECT ON 社員 FROM C;
-- Bが実行:Cの権限が消える
REVOKE SELECT ON 社員 FROM C;

権限は残して再付与の権利だけを取り上げるときは、PostgreSQLでは次のように書きます。

REVOKE GRANT OPTION FOR SELECT ON 社員 FROM A CASCADE;

このとき、Aから渡ったB・Cの権限はCASCADEで消えます。

ビューにだけ権限を与えると、見せる列や行を絞れる

GRANT文の対象には、表だけでなくビューも書けます。給与の列を除いたビューを作り、利用者Dにはそのビューを読む権限だけを与えます。

CREATE VIEW 社員一覧 AS
SELECT 社員ID, 氏名, 部署
FROM 社員;

GRANT SELECT ON 社員一覧 TO D;

するとDは、社員一覧からは氏名や部署を読めますが、社員テーブルを直接読むと拒否されます。ビューのWHERE句で行を絞れば、見せる行も限れます。列ごとの権限でも列は絞れますが、GRANT文の権限では行を選べません。行を絞るときは、ビューが役立ちます。

ロールで権限をまとめ、仕事に必要な権限だけを与える

利用者が増えると、同じ権限を一人ずつ与えるのは手間がかかり、与え忘れや取り消し忘れも起きます。そこで、権限の組をロールという単位にまとめ、ロールを利用者に与えます。

CREATE ROLE 人事部;
GRANT SELECT, UPDATE ON 社員 TO 人事部;
GRANT 人事部 TO B;

PostgreSQLでは、BはロールをとおしてSELECTとUPDATEを実行できるようになります。REVOKE 人事部 FROM B; を実行すれば、これらの権限はまとめて外れます。MySQLも同じ形でロールを与えられますが、与えたロールを有効にする設定が別に必要です。

PostgreSQLでは、ロールを通して受けた権限を、本人から直接は取り消せません。利用者の権限は、直接受けた権限とロールの権限とPUBLICの権限を合わせたものだからです。そのため、所有者がREVOKE SELECT, UPDATE ON 社員 FROM B; を実行しても、Bは人事部ロールを通して表を読めます。

Bに読ませないようにするには、REVOKE 人事部 FROM B; でロールそのものを外します。MySQLの文書も、ロールを外したとき、同じ権限を直接や別のロールで受けていれば、その権限は残ると書いています。

どの権限を与えるかは、最小権限の原則で決めます。仕事に必要な権限だけを与え、不要な権限は与えない考え方です。AWSのIAMでも、同じ原則で権限を決めます。

GRANT文・REVOKE文をDCLと呼ぶ資料と、DDLに含める資料がある

SQL文は、表を定義するDDLと、データを読み書きするDMLに大きく分けられます。GRANT文とREVOKE文は、権限を扱うDCLとして3つ目の分類にまとめられることがあります。DCLはData Control Languageの略で、データ制御言語と訳されます。

ただし、分け方は資料によって違います。Huawei CloudのGaussDB(DWS)の文書はDCLと呼び、OracleのSQLリファレンスはDDLの一覧に入れています。表の定義はCREATE TABLEと制約の記事で説明しています。

参考にした資料

練習問題(全5問)

Q1利用者Aに、社員テーブルを読み出す権限だけを与えるSQL文はどれ?
Q2日本語の用語で「挿入権限」に当たるSQLの権限はどれ?
Q3所有者がAにWITH GRANT OPTION付きでSELECT権限を与え、AがBに同じ権限を与えた。所有者がREVOKE SELECT ON 社員 FROM A CASCADE; を実行すると、どうなる?
Q4前の問題と同じ状態で、CASCADEの代わりにRESTRICTを指定したときの結果はどれ?
Q5社員テーブルの給与の列を利用者Cに見せずに、残りの列だけを参照させたい。適切な方法はどれ?

選んでから「採点する」を押すと、解説つきで答え合わせができます。

関連記事

おすすめの本 PR

セキュリティとデータベースは、基本情報技術者試験の対策本でまとめて学べます。

目的別の本の選び方を見る

データベースの記事を続けて読む

データベース 全36本中22本目