SQLスキルチェック - 初学者編(入門書を学習してゆく段階)
背景
私は1年前に少しSQLを使った業務に携わっていたのですが、そこからブランクがあり、再度こちらの業界に携わることになりました。そこで入社前にSQLの基本を確認したいと思い、データベースとSQLの業務スキルレベル 判別表の問題にチャレンジすることにしました。
ここでは自分なりの解答を記載しますが、何か疑問となる箇所や謝っている箇所があればコメントでご教授いただけますと幸いです。
チェック項目
CRUDとは
CRUD図とは、機能とデータに用いられるプロセス(作成:Create, 参照:Read, 更新:Create, 削除:Delete)をまとめた表のことです。(参考:CRUD図の読み方と書き方)
顧客マスタ | 商品マスタ | 注文テーブル | |
---|---|---|---|
顧客登録 | C | ||
顧客検索 | R | ||
顧客削除 | RD | ||
注文登録 | R | R | C |
注文照会 | R | R | R |
注文訂正 | R | R | RU |
注文取消 | R | R | RD |
論理名と物理名の違い
論理名は「人間向けの名前」で、物理名は「コンピュータ向けの名前」です。一般に、論理削除という場合はレコードをデータベース(DB)に残したまま削除したことにしておくという概念的なもので、物理削除は完全にDBから削除することです。例えば、ユーザーが一時的に退会した場合は論理削除でいつでも復元できる状態にし、1年以上ログインがなければ物理削除するという使い分けができます。(参考:SQLで理解するDBの物理削除と論理削除)
論理名 | 物理名 |
---|---|
顧客マスタ | mst_customer |
顧客名 | name |
年齢 | age |
性別 | sex |
プライマリキー (PK) とは
プライマリーキー (Primary Key) とは、あるテーブルの中で一意のデータを特定できるカラムのことです。例えば、社員テーブルにおいて山田太郎さんが同姓同名で2人いた場合、社員名で検索をかけても所望のレコードを取得することができません。そこでPKとして、社員番号などを付与しておくと名前の重複に関わらず一意のレコードを取得することができます。(参考:PRIMARY KEY制約)
社員番号 | 名前 | 部署 | 性別 |
---|---|---|---|
1 | 山田太郎 | 営業部 | 男性 |
2 | 鈴木花子 | 経理部 | 女性 |
3 | 近藤次郎 | 開発部 | 男性 |
4 | 工藤桃子 | 営業部 | 女性 |
5 | 山田太郎 | 開発部 | 男性 |
DDL, DML, DCLの違い
DDL (Data Defenition Language) とは、データを定義するSQLの命令のことです。
DDL | 説明 |
---|---|
CREATE | 新規テーブルやビューなどのDBオブジェクトを作成 |
DROP | 既存のDBオブジェクトを削除 |
ALTER | 既存のテーブルベースオブジェクトを削除 |
TRUNCATE | テーブル内のデータを全削除 |
DML (Data Manipulation Language) とは、データを操作するSQLの命令のことです。
DML | 説明 |
---|---|
SELECT | テーブルからレコードを抽出 |
INSERT | テーブルにレコードを新規登録 |
UPDATE | テーブルのレコードを更新 |
DELETE | テーブルのレコードを削除 |
DCL (Data Control Language) とは、データを制御するSQLの命令のことです。
DCL | 説明 |
---|---|
GRANT | テーブルに対する権限を付与 |
REVOKE | テーブルに対する権限を取消 |
(参考:DDLとDMLの違い)
WHERE句内でのNULLの指定
WHERE句でNULL値のレコードを取得する/しない場合、WHERE column_name IS [NOT] NULL
を用います。(WHERE column_name = NULL
としてはいけないことに注意)
SELECT *
FROM table_name
WHERE column1 IS NULL AND column2 IS NOT NULL
ORDER BY, LIMIT, OFFSETを使った絞り込み
まず前提として、ORDER BY column_name [ASC | DESC] [NULL FARST | NULL LAST]
はカラムを指定してソートする演算子、LIMIT [開始位置,] 取得する行数
(MySQL) または LIMIT {取得する行数 | ALL} [OFFSET 開始位置]
(PostgreSQL) は行数を絞る演算子です。(参考:SQLリファレンス)
それでは、以下で表題の件で注意すべき点などを紹介します。(参考:ORDER BYとLIMIT, OFFSETの組み合わせには注意しよう)
# 今回使用するテーブルを用意
CREATE TABLE test(id INT, col INT);
INSERT INTO test values(1,1);
INSERT INTO test values(2,1);
INSERT INTO test values(10,1);
INSERT INTO test values(3,1);
#1
SELECT + FROM test ORDER BY col LIMIT 2 OFFSET 0;
#2
SELECT + FROM test ORDER BY col LIMIT 2 OFFSET 2;
こちらが#1, #2のクエリ結果です。データを追加した順番ではなく、ランダムに取得されていることが分かります。このようにORDER BY
を指定しなかった場合、結果の順序はランダム(ORDER BY RAND()
)となってしまうのがMySQLの仕様です。(参考:MySQL)
#1 | id | col | #2 | id | col | |
---|---|---|---|---|---|---|
3 | 1 | 10 | 1 | |||
2 | 1 | 3 | 1 |
SQLのデータ型
(参考:Snowflake Documentation, SQL Server 2008のデータ型とサイズについて, 浮動小数点数型と誤差, SQLのデータ型, 文字列型の使い分け)
数値型
種別 | データ型 | 説明 | byte |
---|---|---|---|
整数 | tinyint | 0~255の範囲の数値 | 1 |
整数 | smallint | およそ-3万~+3万の範囲の数値 | 2 |
整数 | int, integer | およそ-20億~+20億の範囲の数値 | 4 |
整数 | bigint | およそ-900京~+900京の範囲の数値 | 8 |
小数(概数) | real, float(4) | 以下の(*1)参照 | 4 |
小数(概数) | float(8), double [precision] | realに比べ処理が速く正確(*2) | 8 |
小数(真数) | number, decimal, numeric | (有効桁数, 小数点以下桁数)を指定できる | 5~17 |
(※1) 概数は、仮数(小数以下の数値)と指数部分に分ける表現で、仮数の桁数を越えてしまうと数が丸められ誤差が生じます。例えば、32bitで概数を表す場合「a: 符号部(1bit)」「b: 指数部(8bit)」「c: 仮数部(23bit)」で「
(*2) 現在のコンピュータではdouble型に合わせて回路が組まれていることが多いため、float型よりもdouble型の方が計算速度が速い(かつ精度が良い)。
文字列型
種別 | データ型 | 説明 | byte |
---|---|---|---|
固定長文字列 | char, character | 以下の(*1)参照 | 1 |
固定長文字列 | char(n), character(n) | n: 文字数(*2) | 2n |
可変長文字列 | varchar(n) | 8000byteまで(*3) | byte*2 +2 |
可変長文字列 | text, string | 2GBまで | byte*2 +2 |
(*1) charはchar(1)を意味します。固定長文字列の場合、n文字ピッタリでない限り末尾の空白の分だけサイズが大きくなります。そのため処理速度の観点からもcharではなく、varcharやtextが使われることが多いです。
(*2) char(n)のnは、DBの種類によっては文字列ではなくbyteを表すものもあります。なお、数字や半角記号などが1byte, ひらがなや漢字などの全角文字が2byteです。
(*3) 目安として、だいたい200文字以内ならvarchar型、それ以外の長い文字列ならtextを利用すると良いでしょう。
論理型
種別 | データ型 | 説明 | byte |
---|---|---|---|
論理 | boolean | true, false | 1 |
日付と時刻型
種別 | データ型 | 説明 | byte |
---|---|---|---|
日付 | date | YYYY-MM-DD | 3 |
時間 | time | 00:00:00.0000000~23:59:59.9999999 | 3~5 |
日付時間 | datetime | YYYY-MM-DD hh:mm:dd[.mmm] (*1) | 8 |
日付時間 | datetime2 | YYYY-MM-DD hh:mm:dd[.nnnnnnn] | 6~8 |
(*1) datetimeの精度は3.33ミリ秒、datetime2の精度は100ナノ秒です。
3層アーキテクチャーとMVC
一般に、Webアプリケーションは「Webサーバー」「アプリケーションサーバー」「DBサーバー」の3種類からなり、中でもアプリケーションサーバーは「プレゼンテーション層・ビジネスロジック層・データアクセス層(DAO層)」に分けることができます。(参考:MVC、3 層アーキテクチャから設計を学び始めるための基礎知識, DBunitのインストール)
例えば、ユーザーが入力したキーワードに応じて画像を表示させる場合、それぞれの層は以下のような役割を果たします。
- プレゼンテーション層:入力されたキーワードをビジネスロジック層に渡したり、出力結果を表示したりします。ユーザーとやりとりを行う層です。
- ビジネスロジック層:プレゼンテーション層から渡された情報を分析し、必要な画像をDAO層に要求します。プログラムの論理が記述された層です。
- DAO層:ビジネスロジック層から渡された情報でDBを検索し、DB内の画像を取得します。DBとやりとりを行う層です。
MVCとは「Model」「View」「Controller」の頭文字をとったもので、プレゼンテーション層とビジネスロジック層での構成のことを指します。(DAO層には一切コードを書かないケースも存在します)
UPDATEとDELETE-INSERTの違い
UPDATEとDELETE-INSERTでは、(条件次第で)どちらも同じ結果を得ることができます。(参考:DELETE-INSERTとUPDATEの違いや注意点)
UPDATE tab1 SET col2 = 'A' WHERE col1 = '00001';
DELETE FROM tab1 WHERE col1 = '00001';
INSERT INTO tab1 VALUES('00001', 'A');
UPDATEを使う場合
DELETEする必要がない限り、基本はUPDATEを使うことが多いです。なぜなら、DELETEではデータを削除するというリスクが大きいほか、DELETE-INSERTでは2回処理を実行しなければならず処理に時間がかかってしまう可能性もあるからです。
DELETE-INSERTを使う場合
レコードを一度削除した方が都合が良いというときにDELETE-INSERTが用いられます。例えば、日次バッチで前日のレコードを削除して、今日分のレコードのみテーブルに登録したいという際にはこれが有効です。
マスタ(テーブル)とは
マスタとは、システムの運用上変更が少ない基本的な情報が格納されたテーブルのことです。(参考:DBで使用する一般的な用語)
例えば、ECサイトの場合「商品テーブル(商品ID, 商品名, ブランド名など)」がマスタテーブルに該当し、「注文テーブル(顧客ID, 製品名, 購入金額, 決済方法など)」がトランザクションテーブルとなります。
正規化とは
正規化とは、データの重複をなくし扱いやすくするためにテーブル構造を整えることです。大きな1つのテーブルを重複なしで複数の小さなテーブルに分割するイメージになります。(参考:DBで使用する一般的な用語)
正規化の手順
- 表内の1つのセルに1つの値のみが入っている状態にする。(i.e., セルの結合などを解除する)
- 後から集計できる情報などを削ぎ落とす。(i.e., 1人あたり売上など)
- ある変数に従属する変数郡などを独立した小テーブルとして分割する。(i.e., 会社IDと会社名, 社員IDと社員名と電話番号など)
正規化することで、データを一元管理し効率的に変更などを加えることができるため、基本的には正規化した方が良いと言われています。ただ、テーブル数が多くなることで検索SQLのパフォーマンスが悪くなることも懸念されるので、場合によってはあえて正規化を進めないということも考えられます。(参考:データベースの正規化(第1~第3正規形))
JOINの種類
種類 | 説明 |
---|---|
INNER JOIN | キーが一致するレコードのみ取得するJOIN(それ以外は切り捨て) |
LEFT JOIN | 左側テーブルを軸に右側をJOIN(キーが不一致のレコードはNULL) |
RIGHT JOIN | 右側テーブルを軸に左側をJOIN(キーが不一致のレコードはNULL) |
FULL JOIN | 全てのレコードをJOIN(キーが不一致のレコードはNULL) |
CROSS JOIN | 左側のテーブルを軸に右側の全組み合わせをJOIN |
INNER JOIN(内部結合)
今回は、以下の2つのテーブルでJOINについて復習していきます。
users
id | name | sex |
---|---|---|
1 | Tom | man |
2 | Anny | woman |
3 | John | man |
4 | Monica | woman |
personal_info
user_id | birthday | age |
---|---|---|
1 | 20001010 | 22 |
2 | 19990202 | 23 |
5 | 19550505 | 66 |
SELECT a.id, a.name, b.age
FROM users a INNER JOIN personal_info b ON a.id = b.user_id
今回は各テーブルの名前を省略するために、users, personal_infoのテーブルをそれぞれa, bという別名で登録しました。上記のINNER JOINの結果を以下で示します。
id | name | age |
---|---|---|
1 | Tom | 22 |
2 | Anny | 23 |
LEFT JOIN(左外部結合)
SELECT a.id, a.name, b.age
FROM users a LEFT JOIN personal_info b ON a.id = b.user_id
id | name | age |
---|---|---|
1 | Tom | 22 |
2 | Anny | 23 |
3 | John | null |
4 | Monica | null |
RIGHT JOIN(右外部結合)
SELECT a.id, a.name, b.age
FROM users a RIGHT JOIN personal_info b ON a.id = b.user_id
id | name | age |
---|---|---|
1 | Tom | 22 |
2 | Anny | 23 |
null | null | 66 |
FULL JOIN(完全外部結合)
SELECT a.id, a.name, b.age
FROM users a FULL JOIN personal_info b ON a.id = b.user_id
id | name | age |
---|---|---|
1 | Tom | 22 |
2 | Anny | 23 |
3 | John | null |
4 | Monica | null |
null | null | 66 |
CROSS JOIN(クロス結合)
SELECT a.id, a.name, b.age
FROM users a CROSS JOIN personal_info b
id | name | age |
---|---|---|
1 | Tom | 22 |
1 | Tom | 23 |
1 | Tom | 66 |
2 | Anny | 22 |
2 | Anny | 23 |
2 | Anny | 66 |
3 | John | 22 |
3 | John | 23 |
3 | John | 66 |
4 | Monica | null |
4 | Monica | null |
4 | Monica | null |
トランザクションとは
トランザクションとは、1つ以上のSQL文(e.g., SELECT, INSET, UPDATE)を一塊の処理単位としたもので、一連の処理の流れを中断せずに制御することを目的としています。トランザクションが成功した場合には全ての処理を反映させ、失敗した場合には全ての変更を取り消すことができます、(参考:【SQL基礎】トランザクションとは)
トランザクションは「START TRANSACTION」または「BEGIN」が開始文となり、その次に一連の処理を記述し、最後に「COMMIT」または「ROLLBACK」で締めます。COMMITはトランザクション処理の確定、ROLLBACKは処理のキャンセルを意味します。
START TRANSACTION; # BEGINでも可
UPDATE users SET name = 'Tommy' WHERE id = 1;
INSERT INTO users VALUES (5, 'Bob', 'man');
COMMIT; # ROLLBACKでも可
WHERE句で使える演算子
SQLの演算子のほとんどはWHERE句で利用することができます。(参考:SELECT構文:WHEREで検索条件を設定する)
| >, < | 大きい, 小さい |
| >=, <= | 以上, 以下 |
| !=, <> | 等しくない |
| AND | 2つの条件のうち両方が真 |
| OR | 2つの条件のうちどちらか一方が真 |
| NOT | 式の結果を反転 |
| BETWEEN a AND b | 対象フィールドがa~bの範囲 |
| IN | 対象フィールドが複数の値のいずれかに一致 |
| LIKE | 対象フィールドが指定したパターンに一致 |
| IS [NOT] NULL | 対象フィールドがNULL(またはNULLでない) |
※ LIKEでワイルドカードを指定する際、アンダースコア(_)は任意の1文字、パーセント(%)は0個以上の連続した文字を意味します。
SELECT * FROM users WHERE (id >= 2 AND sex = 'woman') OR sex = 'man'
SELECT * FROM users WHERE NOT (id >= 2 AND sex = 'woman')
SELECT * FROM users WHERE id BETWEEN 2 AND 5
SELECT * FROM users WHERE name IN ('Tom', 'John', 'Monica')
SELECT * FROM users WHERE name LIKE 'To_' OR name LIKE 'Mo%'
WHERE句とHAVING句の違い
WHEREとHAVINGはどちらも条件を絞る演算子ですが、実行される順序が異なります。以下でSQLの実行順序を示します。(参考:SELECT - PostgreSQL8.1.9文書)
# 集計前のデータを絞り込み
SELECT datetime, product_id, product_name, price
FROM sales
WHERE DATETRUNC('day', datetime) > '2022-04-01'
# 集計後のデータを絞り込み
SELECT product_id, product_name, SUM(price) as total_price
FROM sales
GROUP BY product_id
HAVING total_price >= 3000
DBにおけるインデックスとは
インデックスとは「探すレコードを識別する項目」「対象レコードの格納位置を示すポインタ」で構成された構造のことです。インデックスを設定することで、テーブルの上から順に1件ずつ探すのではなく、データの格納位置に直接アクセスすることで検索速度を上げることができます。(参考:データベース性能を向上させる「インデックス」を理解する)
SQLで利用される文字コード
文字コードとは「(人間用)文字」と「(コンピュータ用)文字に割り当てられた番号」の対応表のことです。(参考:Unicode (ユニコード))
コンピューターは「0」「1」しか理解できないので、私たちが普段使っている文字を読み込ませる場合には全て数字に変換しなければいけません。そこで例えば、「あ:00000001、い:00000010、う:00000011、え:00000100、お:00000101」のような対応表を作ることで、人間とコンピューターがやりとりできるようにしています。
そんな文字コードですが、SQLでは以下の5つがよく利用されます。(参考:使用可能(有効)な文字コードの一覧を調べる, 文字コードについて(UTF-8/SHift_JIS/EUC-JP))
文字コード | 説明 |
---|---|
utf8 | ユニコード(UTF-8) |
sjis | Shift_JIS(文字化けが起こるため非推奨) |
cp932 | 特殊文字に対応したShift_JIS |
ujis | EUC-JP(文字化けが起こるため非推奨) |
eucjpms | 特殊文字に対応したEUC-JP |
- ユニコード:世界中の文字に対応した文字コード。
- Shift_JIS:Microsoft社が開発した日本語用の文字コード。使い方によっては文字化けします。
- EUC-JP:UNIX系のOSで使われる日本語用の文字コード。テキストエディタには対応していない場合があります。
ODBCとは
ODBC (Open Database Connectivity) とは、Microsoft社が開発した「アプリケーションからDBにアクセスする仕組み」のことで、ソースコードで利用できるものや関数呼び出し時の挙動などが規定されています。(参考:今さら学ぶODBCの基礎)
ODBCのAPIを使うことで(言語を問わず)同じプログラムから、様々なDBに対して接続することができるようになります。(*1)
ODBCは以下の4つのコンポーネントで構成されており、ODBC APIはドライバーマネージャーへのリクエストやレスポンスの際に役目を果たします。
コンポーネント | 説明 |
---|---|
アプリケーション | 処理を実行しODBC関数を呼び出してSQLの命令を送信し、結果を取得します。 |
ドライバーマネージャー | アプリケーションとドライバー間の通信を管理します。 アプリからの接続情報に基づいてドライバーの選択/読み込みなどを行います。 |
ドライバー | ODBC関数の呼び出しを処理し、データソースに対してSQLを実行します。 |
データソース | ユーザーがアクセスするデータやDBMS(*2)などで構成されます。 |
(*1) Javaの場合、JavaアプリケーションからDBを操作するAPIの仕様であるJDBCを使用します。
(*2) DBMS (Database Management System) とは、コンピュータ上に蓄積されたDBにアクセスし、データの検索や更新などを行うソフトウェアのことです。(情報を蓄積するDBとDBMSをまとめて、DBと呼ぶこともあります)
接続文字列とは
接続文字列とは、DBへの接続情報を記した文字列のことで、例えば以下のように記述されます。
Provider=SQLOLEDB; Initial Catalog=testServer; Data Source=testDB; User ID=testuser; Password=testpass;
TCP/IPとは
TCP(Transmission Control Protocol)とは「送信したデータが相手に届いたかを都度確認し、正確な通信を実現する規格」のことで、IP(Internet Protocol)は「通信先を指定するための数値IPアドレスを用いてネットワーク通信を行う規格」のことです。これらの通信プロトコルが標準的に利用されることで、機器やOSが異なっている場合でも通信を成立させることができます。(参考:TCP/IPとは?通信プロトコルの階層モデルを図解で解説, まるごとわかるルーティング入門)
名称 | 主な規格(プロトコル) | 主な利用例 |
---|---|---|
アプリケーション層 | HTTP(S), SMTP, DNS | Webサイト閲覧, メール, ファイル転送, 名前解決 |
トランスポート層 | TCP, UDPなど | データを適切なアプリケーションへ振り分け |
インターネット層 | IP, ARPなど | ルーティング, end-to-end通信 |
ネットワーク インターネット層 |
Ethernet | LAN |
アプリケーション層
アプリケーションで扱うデータのフォーマットや手順を決め、「0/1」の信号データをユーザーが理解できる表現形式に変換します。HTTP(S)プロトコルはWebブラウザ、SMTPやPOP3はメール、DNSは名前解決(ドメインとIPアドレスの紐付け)に用いられます。
トランスポート層
TCPやUDPといったプロトコルで、データを適切なアプリケーションに振り分けます。私たちが普段スマホでアプリなどを利用する上で欠かせない存在です。
TCP | UDP | |
---|---|---|
特徴 | 確実性重視 | 速度重視 |
信頼性 | 高い | 低い |
利用速度 | 遅い | 速い |
利用例 | Webサイト閲覧, メールなど | 映像配信, Web会議など |
インターネット層
ルーターを経由して異なるネットワークにIPバケット(データ)を転送する「ルーティング」や、ルーターを介さずに端末と端末で直接データを送信する「end-to-end通信」などが行われます。
ネットワークインターフェイス層
Ethernet(有線LAN)や無線LANなどのプロトコルで、同一ネットワーク内におけるデータ転送を実現します。例えば、同一ネットワーク内のサーバーやDBなどの通信プロトコルを定めることで、デジタルデータなどを電気信号に変換して伝送媒体で伝えることができます。
DBの種類
ここでのDBとは、行列形式のDBであるRDB (Relational Database) のことであり、階層型DB・ネットワーク型DB・NoSQLなどについては言及しないものとします。
DB名 | 説明 |
---|---|
MySQL | Oracle社が管理するオープンソース型のDBMS(無料)。大容量データを高速に処理でき、検索エンジンやレンタルサーバーなどでも利用されています。 |
Oracle Database | Oracle社が管理する商用DB(有料)。高い堅牢性を持つため障害などにも強く、サポートも受けることができます。 |
Microsoft SQL Server | Microsoft社が提供するRDB(有料)。高い堅牢性をもち、Windows製品との親和性が高いです。 |
Microsoft Access | Office製品に含まれるRDB(有料)。他のDBに比べ操作は簡単ですが、複雑な処理や高速な処理には不向きです。 |
PostgreSQL | Unix系のOSにも対応するオープンソース型のRDB(無料)。ある程度複雑な処理にもでき、様々な機能や関数にも対応できるバランス型です。 |
SQLite | オープンソース型のDBMS(無料)。手軽な設定と軽い動作が特徴で、アプリケーションに組み込まれて運用されます。 |
Amazon Aurora | Amazon社が提供するRDB(有料)。処理能力はMySQLの5倍、PostgreSQLの3倍高く、ストレージも最大64TBまで拡張でき、DB保護のセキュリティも複数段階用意されています。 |
Discussion