一 SQL#
全称はStructured query Language
:構造化クエリ言語。各データベースの文にはそれぞれの方言
があるが、基本的なコマンドは変わらない。
mysql の文は大文字と小文字を区別しないが、
キーワードは大文字で書くことを推奨する
- DDL:データベース、テーブルの操作
- DML:テーブルのデータの追加、削除、更新
- DQL:テーブルのデータのクエリ
- DCL:権限付与
二 データ型#
データ型は全体で三つの大きなカテゴリに分かれ、数値型、文字列型、日付型
1 数値型:
型 | サイズ (バイト) | 説明 |
---|---|---|
int/integer | 4 | 数字 |
bigint | 8 | 数字 |
smallint | 2 | 数字 |
tinyint | 1 | ブール値 |
double | 8 | 近似ストレージ |
double(M,D) | 8 | 近似ストレージ |
decimal(M,D) | 8 | 精密ストレージ |
ここで M は最大桁数、D は小数点以下の桁数を示す
2 文字列型:
型 | サイズ (バイト) | |
---|---|---|
char | 0-155 | 固定長文字列、短すぎる場合は空白で補完される。 利点:クエリ速度が速い、欠点:スペースを浪費する |
varchar | 0-65535 | 可変長文字列 利点:スペースを節約、欠点:少し遅い |
blob | 0-65535 | バイナリデータを保存 |
mediumblob | 16M | バイナリデータを保存 |
longblob | 4G | バイナリデータを保存 |
text | 0-65535 | 長文 |
mediumtext | 16M | 長文 |
longtext | 4G | 長文 |
MYSQL では == 各レコード == の最大バイト数は 64k(数字、文字列)、テキスト、バイナリファイルは含まれない
この各レコードは一行のデータを示し、例えば id+name+age+address を合わせたもの
3 日付型:
型 | 長さ (バイト) | フォーマット | 用途 |
---|---|---|---|
date | 3 | YYYY-MM-DD | 日付値 |
time | 3 | HH:MM | 時間値 |
year | 1 | YYYY | 年 |
datetime | 8 | YYYY-MM-DD HH:MM | 日時 |
timestamp | 4 | YYYYMMDDHHMMSS | タイムスタンプ |
三 DDL 文法#
データベースおよびテーブルの操作
1 データベースの操作#
- データベースの作成:
# データベースの作成
create database データベース名;
# データベースが存在しない場合は作成し、存在する場合は作成しない
create database if not exists データベース名;
# 作成し、文字セットを設定
create database データベース名 character set 文字セット名;
- データベースのクエリ:
show databases;
# 表示し、作成
show create database データベース名;
- データベースの文字セットを変更:
# データベースの文字セットを変更
alter database データベース名 character set 文字セット名;
- データベースの削除
drop database データベース名;
# 存在する場合は削除
drop database if exists データベース名;
- 現在使用中のデータベース名をクエリ:
select database();
- データベースを使用:
use データベース名;
2 テーブルの操作#
- テーブルの作成
create table テーブル名(
列名1 データ型1,
列名2 データ型2,
列名2 データ型2,
......
列名n データ型n # 最後の列の後にセミコロンはない
);
- テーブルのコピー:
create table 新テーブル名 like テーブル名;
- すべてのテーブルをクエリ:
# すべてのテーブルをクエリ
show tables;
# テーブル構造をクエリ
desc テーブル名;
- テーブルの変更:
# テーブル名を変更
alter table テーブル名 rename to 新テーブル名;
# テーブルの文字セットを変更
alter table テーブル名 character set 文字セット名;
# 列を追加
alter table テーブル名 add 列名 データ型;
# 列を変更
alter table テーブル名 change 列名 新列名 新データ型; [[名前と型を変更]]
alter table テーブル名 modify 列名 新データ型 [[列のデータ型のみを変更]]
- 削除:
# 列を削除
alter table テーブル名 drop 列名;
# テーブルを削除
drop table テーブル名;
[[テーブルを削除する前に確認]]
drop table if exists テーブル名;
四 DML 文法#
テーブル内の内容の操作で、最もよく使われる文
1 データの追加#
データを追加:
# すべての列を追加
insert into stu(列名1,列名2....列名n) values (データ1,データ2...データn);
# すべてのデータを追加する場合、列名は書かなくてもよい
insert into stu values (データ1,データ2...データn);
# どの行を追加しない場合は書かなくてもよい
# デフォルト値を設定したい場合はdefaultと書くことができる
2 データの削除#
# データを削除
delete from テーブル名 where 条件;
# テーブルを空にする
delete from テーブル名;
# テーブルを直接削除し、同名のテーブルを作成する方が速い
truncate table テーブル名;
3 データの変更#
# データを変更
update テーブル名 set 列名1 = 値1,列名2 = 値2, .... where 条件
# where条件を加えない場合は、テーブル内のすべての指定されたデータを変更することを意味する
update テーブル名 set 列名1 = 値1,列名2 = 値2, ....
五 DQL 文法#
テーブル内のデータをクエリし、書き方の順序は以下の通り:
select フィールドリスト
from テーブルリスト
where 条件リスト
group by グループ条件
having ソートされたデータをフィルタリング
order by ソートする列
limit ページングを行う、limitはmysqlの方言
1 基本クエリ#
# すべてをクエリ
select * from テーブル名;
# 指定された列をクエリ
select 列名1,列名2... from テーブル名;
# クエリし、重複を除去
select distinct 列名1,列名2... from テーブル名;
# 二つの列を計算
select 列1+列2.... from テーブル名;
# 上記にnull値がある場合は正常に計算できないため、if nullキーワードを使用できる
select math + if null(english,0) from テーブル名;
# 別名をクエリ
select 列1 as 別名, 列2 as 別名..... from テーブル名;
[[asを省略することもできる]]
select 列1 別名, 列2 別名....... from テーブル名;
2 条件クエリ#
つまり文の後にwhere
フィールドを追加し、クエリの条件を書く
比較演算子 | 説明 |
---|---|
>、<、<=、>=、=、<> | <> は不等を示し、mysql では!= も使用できる |
between...and | 範囲内にあること、例えば:between 100 and 200 は **[100,200]** を示す |
in (集合) | 集合は複数の値を示し、カンマで区切る |
like ' 張 %' | プレースホルダー:_ は任意の単一文字を示し、% は任意の複数文字を示す;あいまい検索 |
is NULL | 特定の列が null の値をクエリする、注意:=null とは書かないこと |
is not NULL | null でない値をクエリ |
論理演算子 | 説明 |
---|---|
and または && | かつ、SQL では前者を推奨し、後者は一般的ではない |
**or または | |
not または ! | 否定 |
3 ソートクエリ#
つまりorder by
の後にソートを追加
キーワード | 説明 |
---|---|
指定しない場合、デフォルトは昇順 | |
ASC | 昇順 |
DESC | 降順 |
文:
複数条件のソート、つまり最初の条件が同じ場合、第二のソートを行う
select * from student order by 数学成績, 英語成績;
4 集約関数#
集約関数:一列のデータを全体として扱い、縦の計算を行う、つまり列を計算する
キーワード | 説明 |
---|---|
count(列名): | 個数を計算 |
max(列名): | 最大値を計算 |
min(列名): | 最小値を計算 |
sum(列名): | 合計を計算 |
avg(列名): | 平均値を計算 |
注意:集約関数はnull
値を除外する、個数を統計する場合、空の列を使用しないことを推奨
使用例:
全人数を計算:
select count(name) from student;
5 グループクエリ#
つまりgroup by
の後にグループを追加
グループを行う場合、select
で得られる結果は必ず全体であるため、特定の列を指定することはできず、したがって、グループ自体のフィールド、集約関数のみを書くことができる
例えば、男子と女子それぞれの数学の平均点と人数を調べる必要がある場合:
select sex,avg(math) ,count(id) from studnet group by sex;
グループ後に制限をかける必要がある場合は、having
でフィルタリングする必要がある
例えば、クエリ後に人数が 3 人を超えるグループをフィルタリングする必要がある場合:
select sex,avg(math) ,count(id) from studnet group by sex having count(id)>3;
6 ページングクエリ#
ページングクエリ:クエリの結果が非常に多い場合、ページングで表示したい場合、これがページングクエリで、limit
フィールドに条件を書く
limit 開始のインデックス,ページごとのクエリの件数
最初の三人をクエリし、かつ最初のページに 3 件表示する場合:
select * from student limit 0,3; [[第1ページ]]
select * from student limit 3,3; [[第2ページ]]
select * from student limit 6,3; [[第3ページ]]
*したがって、我々は一つの規則を見つける:開始のインデックス =(ページ数 - 1)ページごとの表示件数
7 複数テーブルクエリ#
その文法は単一テーブルクエリと基本的に一致するが、意味は異なる。まず、デカルト積を紹介する
- デカルト積:いくつかのもののすべての組み合わせの状況、データベース内で複数のテーブルをクエリすると、複数のテーブルのデータをデカルト積で求めることになり、すべての組み合わせの状況を印刷することになる
仮に A、B の二つのテーブルがあり、A に x 個のデータ、B に y 個のデータがある場合、クエリするとx*y
個のデータが得られる
select * from A, B;
注意:このように直接クエリすると、多くの無駄なデータが得られるため、無駄なデカルト積を排除する方法を以下に紹介する
1 内部結合クエリ
- 暗黙の内部結合:
where
条件文で二つのテーブルの関連フィールドが等しいことを指定するだけ
select * from テーブル1,テーブル2 where テーブル1.id = テーブル2.id;
- 明示的内部結合:
select クエリフィールド from テーブル名1 inner join テーブル名2 on テーブル1.id = テーブル2.id;
select クエリフィールド from テーブル名1 join テーブル名2 on テーブル1.id = テーブル2.id; [[innerは省略可能]]
2 外部結合クエリ
- 左外部結合:左テーブルのすべてのデータと、その交差部分をクエリする(一般的には左外部結合を使用)
select クエリフィールド from テーブル名1 lift join テーブル名2 on 条件;
- 右外部結合:右テーブルのすべてのデータと、その交差部分をクエリする
select クエリフィールド from テーブル名1 right join テーブル名2 on 条件;
3 サブクエリ
概念:クエリのネスト、ネストされたクエリは外側のクエリのサブクエリと呼ばれる
- 1 サブクエリの結果は単行単列である
演算子を使用して判断するのはこのタイプで、例えば、最高得点を持つ人の情報をクエリする場合は単一の結果である
# 最高得点を持つ人の情報をクエリ
-- 1 最高得点はいくつか
select max (salary) from emp; -- 90点
-- 2 最高得点を持つ人の情報をクエリ
select * from emp where salary = 90
# 実際にはネストして書くこともできる
select * from emp where salary =(select max (salary) from emp);
- 2 サブクエリは多行単列である
演算子in
を使用して受け取る
# 2班と3班のすべての学生情報をクエリ
-- 1 2班と3班に対応するクラス番号をクエリ
select id
from dept
where name= 1班 or name = 2班; -- 1 ,2
-- 2 クラス番号に対応する学生情報をクエリ、orまたはin
select *
from emp
where dept_id = 1 or dept_id = 2;
select *
from emp
where dept_id in (1,2);
# ネストして書くこともできる
select *
from emp
where dept_id
in(select id from dept where name= 1班 or name = 2班);
- 3 サブクエリは多行多列である
多行多列は仮想のテーブル
に相当する
# すべての学生の入学日が2020年1月1日以降の情報とクラス情報をクエリ
# 通常のクエリ
select *
from emp t1, dept t2
where t1.id = t2.id and t1.date>2020-1-1;
# ネストクエリ
select *
from dept t1, (select * from emp where emp.date >2020-1-1) t2
where t1.id = t2.id
六 DCL ユーザー管理#
1 ユーザー管理#
1 ユーザーの追加
create user ユーザー名 identified by パスワード
create user ユーザー名 @ ホスト名 identified by パスワード
# ホスト名はこのユーザーがこのホストからのみログインできることを示す
# 書かない場合はデフォルトで以下の形式になり、どのマシンからでもログインできる
create user 'ユーザー名' @ '%' identified by パスワード
2 ユーザーパスワードの変更
# 方法1
update user set password = password('新しいパスワード') where user = 'ユーザー名';
# 方法2
set password for 'ユーザー名'@ 'ホスト名' = password('新しいパスワード');
3 root ユーザーのパスワードを忘れた場合
# cmdで以下のコマンドを実行し、mysqlサービスを停止
net stop mysql
# 認証なしでmysqlサービスを起動
mysqld --skip -grant -tables
# 新しいウィンドウを開き、以下のコマンドを入力すれば、認証なしで入ることができ、パスワードを変更できる
mysql
4 ユーザーの削除
drop user 'ユーザー名' @ 'ホスト名'
drop user 'ユーザー名'
5 ユーザーをクエリ
mysql
をダウンロードしたとき、システムに自動的に付属するデータベースはmysqlと呼ばれ、その中にuserというテーブルがあり、ユーザー情報が保存されているため、クエリは以下の通り:
use mysql;
select * from user;
2 権限管理#
1 権限をクエリ
show grants for 'ユーザー名' @ 'ホスト名';
show grants for 'ユーザー名' @ '%';
2 権限を付与
# 一つずつ権限を付与
grant 権限リスト on データベース名.テーブル名 to 'ユーザー名' @ 'ホスト名';
# 権限リスト:select,update,delete,inseat
# 一度にすべての権限を付与
grant all on *.* to 'ユーザー名' @ 'ホスト名';
3 権限を撤回
# 一つずつ権限を撤回
revoke 権限リスト on データベース名.テーブル名 from 'ユーザー名' @ 'ホスト名';
# 一度にすべて撤回
revoke all on *.* from 'ユーザー名' @ 'ホスト名';
七 制約#
言うまでもなく、保存されるデータの規範。何を保存でき、何を保存できないか、以下の三つの大きなカテゴリがある:
1 エンティティ完全性制約:
制約 | 説明 |
---|---|
primary key | 主キー制約 |
unique | 一意制約、一意だが null を許可 |
auto_increment | 自動増分、主キー制約と併用 |
2 ドメイン完全性制約
制約 | 説明 |
---|---|
not null | 非空 |
default | デフォルト値制約 |
型 | 型制約 |
3 参照完全性制約:
外部キー制約
とも呼ばれ、データベースの完全性を保証する利点があるが、速度が遅く、性能が低い。文法:
# テーブル作成時に追加
constraint foreign key (外部キー字段) references 另一张表名称(另一张表の主キー)
# テーブル作成後に外部キーを追加
alter table テーブル名 add constraint FK_ID foreign key(あなたの外部キー字段名) REFERENCES 外表表名(対応する表の主キー字段名);
4 制約を削除:
- 非空制約を削除:
# 名前、型、制約を変更
alter table テーブル名 change 列名 新列名 新データ型 新しい制約;
# 列のデータ型のみを変更
alter table テーブル名 modify 列名 新データ型 新しい制約
# 列の属性を再指定し、制約を削除
alter table stu modify id int;
- 一意制約を削除:
alter table stu drop index 列名;
- 主キー制約を削除:
alter table stu drop primary key;
八 正規化#
正規化:正規化とは、データベース設計に従うべき規範を指す
1 正規化の分類
正規化 | 説明 |
---|---|
第一正規化(1NF) | 各列は分割できない原子データ項である |
第二正規化(2NF) | 1NF の基礎の上で、非主属性が主キーに対する部分関数依存を排除 |
第三正規化(3NF) | 2NF の基礎の上で、推移的依存を排除 |
第四正規化(4NF) | 3NF の基礎の上で、 |
第五正規化(5NF) | 4NF の基礎の上で、 |
第六正規化(6NF) | 5NF の基礎の上で、 |
2 関数依存
- 完全関数依存:前者が後者を一意に決定できる場合の
A-->B
または(A,B)-->C
- 部分関数依存:
(A,B)-->C
だがA-->C
であるため、部分関数依存である - 推移関数依存:
A-->B
かつB-->C
であるためA-->C
、これが推移依存である - キー:もし一つの属性、または属性グループが他のすべての属性に完全に依存している場合、その属性はその表のキーと呼ばれる
- 主属性:キー属性グループ内のすべての属性
- 非主属性:キー属性グループ以外の他の属性
九 データベースのバックアップと復元#
データベースを sql ファイルとして保存し、sql ファイルをインポートする
# バックアップ:
mysql dump -uユーザー名 -pパスワード データベース名 > D:\\xxx.sql;
# 復元、データベースが必要
create database xxx;
use xxx;
source D:\\xxx.sql
十 トランザクション#
トランザクションとは、これらの操作を一つの全体
に統合し、すべてを実行するか、すべてを実行しないか、トランザクションの期間中に異常が発生した場合はロールバック
し、トランザクションの開始地点に戻り、問題がなければトランザクションをコミットする。
SQL 文を実行するたびに、デフォルトでトランザクションが開始される。自分でトランザクションを開始する理由は、このデフォルトの単一行文トランザクションを打破し、複数行文を原子操作にするためである。
トランザクションを開始
説明 | コマンド |
---|---|
トランザクションを開始 | start transaction,begin,set uncommit = 0 この三つの方法 |
ロールバック | rollback |
コミット | commit |
自動コミットの確認、設定:
# 自動コミットかどうかを確認
select @@autocommit ;
# 結果が1-----自動コミット、mysqlデフォルト
# 結果が0-----手動コミット、oracleデフォルト
# 自動コミットを設定
set @@autocommit;
トランザクションの四つの特性
1 原子性:トランザクションは分割できない最小単位であり、全体である。すべてが同時に成功するか、すべてが同時に失敗する。トランザクションは全体で実行される
2 一貫性:トランザクションの一貫性、トランザクション操作の前後で、トランザクションの総量は変わらない。例えば、振込の場合、振込前後の金額の総量は変わらない
3 隔離性:複数のトランザクションは相互に独立しているが、いくつかの相互影響があり、トランザクションの隔離レベルで制限する必要がある
4 永続性:トランザクションがコミットまたはロールバックされた後、データは永続的に保存される
トランザクションの隔離レベル
複数のトランザクションは隔離されており、相互に独立しているが、複数のトランザクションが同じデータを操作するといくつかの問題が発生するため、異なる隔離レベルを設定してこれらの問題を解決する:
1. ダーティリード:一つのトランザクションが、別のトランザクションがコミットしていないデータを読み取る
2. 不可再現性(仮想読):同じトランザクション内で、二回読み取ったデータが異なる。読み取っている間に、誰かがデータを変更したためである。
3. ファントムリード:一つのトランザクションが(DML:追加、削除、変更)データテーブル内のすべてのレコードを操作し、別のトランザクションが一つのデータを追加すると、最初のトランザクションは自分の操作の結果を確認できず、まるで幻のように見えるが、mysql は処理を行い、ファントムリードは発生しない。
隔離レベル
隔離レベル | 説明 | ダーティリード | 不可再現性 | ファントムリード |
---|---|---|---|---|
read uncommited | 未コミットの読み取り | √ | √ | √ |
read commited | コミット済みの読み取り (Oracle デフォルト) | √ | √ | |
repeatable read | 再現可能な読み取り (MySql デフォルト) | √ | ||
serializable | 直列化 |
隔離レベルは小さいほど安全性が高まるが、効率は低下する
隔離レベルをクエリ
select @@tx_isolation
# 結果は以下の通り:mysqlデフォルト
# +-----------------+
# | @@tx_isolation |
# +-----------------+
# | REPEATABLE-READ |
# +-----------------+
隔離レベルを設定
# グローバル設定
set global transaction isolation level 隔離レベル文字列;
# セッション設定
set session transaction isolation level 隔離レベル文字列;
十二 ビュー#
仮想テーブルだが、実際のテーブルと同じ
利点:シンプルで、安全性が高く、ユーザーはビュー内のデータのみを見ることができる
欠点:
- ビューのデータはデータベースから来ており、データベースのデータが変わるとそれに従って変わる
- クエリ性能を最適化しない
- ビューに以下の内容が含まれている場合は更新されない
- 集約関数の結果
- distinct 重複の結果
- group by グループの結果
- having フィルタリングの結果
- union、union all 結合の結果
ビューの作成:
create view 自分のビュー名 as データベースクエリ文
# この名前のビューがあれば置き換え、変更文として使用できる
create or replace view 自分のビュー名 as データベースクエリ文
# ビューを変更
alter view ビュー名 as クエリ文;
# ビューを削除、ビューの削除は元のテーブルに影響を与えない
drop view ビュー名;
ビューへの操作もデータベースに更新できるが、一般的にはそうしない。例えば、ビューのデータソースが一つのテーブルのすべての内容である場合、結合クエリの結果をビューのデータソースとする場合は変更できない。非常に理解しやすい。