MySQL データベース - マルチテーブル操作

ここに画像の説明を挿入

序文

データベースを日常的に使用する場合、処理するデータは単一のテーブルだけではなく、複数のテーブルのデータを同時に処理する必要があるため、今日は MySQL のマルチテーブル操作について説明します。

複数テーブルの関係

複数テーブルの操作を学ぶ前に、複数テーブルのリレーションシップ (1 対 1 のリレーションシップ、1 対多のリレーションシップ/多対 1 のリレーションシップ、多対多のリレーションシップ) とは何かを知る必要があります。

一対一の関係

1 対 1 の関係とは、あるテーブルの 1 つのレコードが別のテーブルの 1 つのレコードにのみ対応し、共通の主キーまたは一意のキーを介して関連付けられることを意味します。

ここに画像の説明を挿入

1対多/多対1の関係

マルチテーブルの 1 対多または多対 1 の関係とは、1 つのテーブルの 1 つのレコードが別のテーブルの複数のレコードに対応でき、それらのレコードは共通の主キーまたは外部キーを通じて関連付けられることを意味します。
ここに画像の説明を挿入

多対多の関係

マルチテーブルの多対多の関係とは、2 つ以上のテーブルが相互に関連しており、各テーブルのレコードが他のテーブルの複数のレコードに対応できることを意味します。複数テーブルの多対多のリレーションシップを処理する一般的な方法は、中間テーブル (関連付けテーブル) を使用してリレーションシップを結合することです。

ここに画像の説明を挿入

外部キー制約

MySQL 外部キー制約は、テーブル間の関係の整合性を確保するために使用されるデータベース制約です。これは、あるテーブルのフィールドまたはフィールドのグループの値が、別のテーブルの値と一致するか、特定の条件を満たす必要があることを定義します。

外部キー制約は、外部キー関係を指定することによって、あるテーブルのフィールド (外部キーと呼ばれます) を別のテーブルの主キーまたは一意キー (参照キーと呼ばれます) に関連付けます。このようにして、テーブル内の外部キー値が変更された場合、MySQL はデータの一貫性を維持するために、参照テーブル内に一致するキー値があるかどうかを自動的にチェックします。

外部キー制約には次の機能があります。

  1. 参照整合性の強制: 外部キー制約により、テーブル内のデータが参照時に関連付けられたテーブルに存在することが保証されます。
  2. データの一貫性を維持する: 外部キー制約により、関連テーブルでデータが削除または変更されたときに結果の不一致が防止されます。
  3. クエリの最適化を提供します。MySQL オプティマイザーは、外部キー関係を使用してクエリ操作を高速化できます。
  4. カスケード操作: 外部キー制約によりカスケード操作を定義できます。参照テーブルのデータが更新または削除されると、関連するテーブルのデータに対して対応する操作が自動的に実行されます。

MySQL の外部キー制約には次の特徴があります。

  1. 参照整合性の強制: 外部キー制約により、参照テーブルのデータが参照テーブルに存在することが保証され、無効な参照が防止されます。これにより、データの一貫性と完全性が保証されます。

  2. 関係を自動的に検証および維持する: MySQL は、関連付けられたデータが正しく更新、挿入、または削除されることを保証するために、外部キー制約を自動的に検証および維持します。外部キー制約に違反すると、MySQL はエラーを報告し、操作の実行を拒否します。

  3. カスケード操作のサポート: 外部キー制約によりカスケード操作を定義できます。参照テーブルで操作を削除または更新すると、関連するテーブルの関連データに対して対応する操作が自動的に実行されます。例えば、カスケード削除を実現することができ、参照テーブルのデータを削除すると、関連テーブルの関連データも同時に削除される。

  4. クエリ パフォーマンスの最適化: MySQL オプティマイザは、外部キー制約を使用してクエリ操作を最適化できます。外部キー関係を正しく設定することにより、MySQL は JOIN 操作をより効率的に実行し、クエリのパフォーマンスを向上させることができます。

  5. 無効化および有効化可能: 必要に応じて、外部キー制約を無効化または有効化して、外部キー制約の一時的な違反を必要とする特定の操作を許可できます。この機能は状況によっては便利ですが、データの不整合を防ぐために注意して使用する必要があります。

  6. データの整合性への依存: 外部キー制約を使用すると、アプリケーションに依存するのではなく、データベース レベルでデータの整合性を維持できます。これにより、エラーやデータの不一致の可能性が減り、データベースの信頼性が高まります。

外部キー制約を作成する

MySQL で外部キー制約を作成するには 2 つの方法があります。 1. テーブルの作成時に外部キー制約を作成します。create table 表名(列名1 类型,列名2 类型,constraint 外键名 foreign key(列名) references 主表(主表列名);2. テーブルの作成後に外部キー制約を作成します。alter table 表名 add constraint 外键名 foreign key(列名) referrnces 主表(主表列名);

テーブルの作成後に外部キー制約を追加する前提は、セカンダリ テーブルの外部キー列のデータがメイン テーブルの主キー列のデータと一致している必要があり、そうでない場合はデータがありません。

テーブル作成時に外部キー制約を作成する

create table class(class_id int primary key,name varchar(10)); -- 主表
insert into class values(1,'高三1班'), 
						(2,'高三2班'),
						(3,'高三3班');
												
create table student
			(class_id int,student_id int,name varchar(20),gender varchar(10),
			constraint student_fk foreign key(class_id) 
			references class(class_id));

ここに画像の説明を挿入

テーブル作成後に外部キー制約を追加する

create table class(class_id int primary key,name varchar(10)); -- 主表
insert into class values(1,'高三1班'), 
						(2,'高三2班'),
						(3,'高三3班');

create table student
	(class_id int,student_id int,name varchar(20),gender varchar(10));
	
alter table student 
add constraint student_fk 
foreign key(class_id) references class(class_id);

ここに画像の説明を挿入

データを挿入する

データを挿入する際、メインテーブルに先にデータを挿入する場合は特に注意する必要はありませんが、スレーブテーブルにデータを挿入する場合は注意が必要です。挿入されたレコードはメインテーブルにあります。 テーブルの主キー列が存在するかどうか。存在する場合、挿入は成功します。存在しない場合、挿入は失敗します。そこで次のように提案してください。データを挿入する場合は、まずマスターテーブルにデータを挿入し、次にスレーブテーブルにデータを挿入します。

insert into student values(1,2301,'张三','男');

ここに画像の説明を挿入

insert into student values(4,2302,'王五','男');

ここに画像の説明を挿入

新しい外部キー制約を作成するときに、テーブルにデータがすでに存在している場合はどうなるでしょうか?

create table student
	(class_id int,student_id int,name varchar(20),gender varchar(10));
	
insert into student values(1,2301,'张三','男'),
						(3,2302,'王五','男');
-- 我们插入的数据都是与主键列中的数据相对应
	
alter table student 
add constraint student_fk 
foreign key(class_id) references class(class_id);

ここに画像の説明を挿入
上記のデータの外部キー列は主キー列のデータに対応しているため、挿入は成功します。

create table student
	(class_id int,student_id int,name varchar(20),gender varchar(10));
	
insert into student values(1,2301,'张三','男'),
						(4,2302,'王五','男');
-- 这里class_id 4 在主键列中并不存在,我们看看是否能
alter table student 
add constraint student_fk 
foreign key(class_id) references class(class_id);

ここに画像の説明を挿入
ここでは、class_id 4 が主キー列に存在しないため、挿入は失敗します。

外部キー制約のあるテーブルからデータを削除する

外部キー制約のあるテーブルのデータを削除する必要がある場合はどうすればよいでしょうか?

  • テーブルからのデータ削除は任意に削除可能
  • メインテーブルのデータを削除するときは注意が必要です。削除したレコードの主キー列が外部キー列に依存している場合は削除できません。

ここに画像の説明を挿入
ここに画像の説明を挿入
この時点では、主キーカラム 1 がまだ外部キーカラムに依存しているため、削除してみます。

delete from class where class_id = 1;

ここに画像の説明を挿入
削除に失敗したため、メインテーブルのデータを削除するときに、レコードの主キー列がまだ外部キー列に依存しているかどうかを考慮する必要があります。データを削除するときは、最初にセカンダリ テーブルのデータを削除し、次にメイン テーブルの非依存データを削除することをお勧めします。

外部キー制約を削除する

ただし、外部キー制約が必要ない場合は、外部キー制約を削除することもできます。alter table 表名 drop foreign key 外键名;

ここに画像の説明を挿入
この時点で、外部キー制約は削除されました。

複数テーブルの結合クエリ

マルチテーブルクエリはMySQL操作において最も重要で最も使用される操作であるため、MySQLマルチテーブルクエリ操作をよく学ぶ必要があります。

MySQLのマルチテーブルクエリとは、複数のテーブルを含むテーブル間の接続条件(関連付け条件)を1つのクエリ文で指定して結合データを取得する処理のことを指します。マルチテーブル クエリを使用すると、複数のテーブルからデータを取得、フィルタリング、結合できます。

MySQL のマルチテーブル操作には主に次のものが含まれます。

  • クロス結合クエリ
  • 内部結合クエリ
    • 暗黙的な内部結合 (SQL92 標準)
    • 明示的な内部結合 (SQL99 標準)
  • 外部結合
    • 左外部結合
    • 右外部結合
    • 完全外部結合
  • サブクエリ
  • 自己関連付けクエリ

また、クエリ操作を実装しているため、外部キー制約は複数テーブルのクエリには影響しません。

データの準備

後続の複数テーブル クエリ用にデータを準備します。

use mydb3;
-- 创建部门表
create table if not exists dept3(
  deptno varchar(20) primary key ,  -- 部门号
  name varchar(20) -- 部门名字
);

-- 创建员工表
create table if not exists emp3(
  eid varchar(20) primary key , -- 员工编号
  ename varchar(20), -- 员工名字
  age int,  -- 员工年龄
  dept_id varchar(20)  -- 员工所属部门
);

-- 给dept3表添加数据
insert into dept3 values('1001','研发部');
insert into dept3 values('1002','销售部');
insert into dept3 values('1003','财务部');
insert into dept3 values('1004','人事部');

-- 给emp3表添加数据
insert into emp3 values('1','乔峰',20, '1001');
insert into emp3 values('2','段誉',21, '1001');
insert into emp3 values('3','虚竹',23, '1001');
insert into emp3 values('4','阿紫',18, '1001');
insert into emp3 values('5','扫地僧',85, '1002');
insert into emp3 values('6','李秋水',33, '1002');
insert into emp3 values('7','鸠摩智',50, '1002'); 
insert into emp3 values('8','天山童姥',60, '1003');
insert into emp3 values('9','慕容博',58, '1003');
insert into emp3 values('10','丁春秋',71, '1005');

ここに画像の説明を挿入
ここに画像の説明を挿入

クロス結合クエリ

MySQL クロス結合クエリ (Cross
Join) は、2 つ以上のテーブルから可能なすべての組み合わせを返すために使用されるクエリ方法です。結合条件を使用せずに、左側のテーブルの各行と右側のテーブルの各行のすべての組み合わせを返します。したがって、クロス結合クエリは、左側のテーブルの行数と右側のテーブルの行数を掛けた行数を含む結果セットを生成します。

select * from 表1,表2
ここに画像の説明を挿入
クロス結合クエリは実際には複数のテーブル間で実行されますデカルト積

ここに画像の説明を挿入
それぞれ m および n 個のレコードを持つ 2 つのテーブルのデカルト積を計算すると、m*n 個のレコードが存在します。

select * from dept3,emp3;

ここに画像の説明を挿入
ただし、デカルト積後のテーブルのデータを見ると、不適切なレコードが多数あることがわかります。そのため、デカルト積で生成されたテーブルにもフィルターをかける必要があります。

内部結合クエリ

MySQL の内部結合クエリ (Inner Join) は、2 つ以上のテーブルから結合条件を満たすレコードセットを返すために使用されるクエリメソッドです。内部結合は、指定された結合条件に基づいて 2 つのテーブルの行を照合し、一致する行を返します。

内部結合は最も一般的に使用される接続タイプであり、複数のテーブル間の関連付け関係を確立し、関連データを取得するのに役立ちます。内部結合の結果セットには一致する行のみが含まれるため、結合条件に基づいてデータを関連付け、フィルター処理して、より具体的で意味のある結果を得ることができます。

暗黙的な内部接続:select * from 表A,表B where 条件;
明示的な内部接続: select * from 表A inner join B on 条件;inner は省略できます。

MySQL は、マルチテーブル操作用に 3 つ以上のテーブルもサポートしています。select * from 表A join B on 条件 join C on 条件...;

ここに画像の説明を挿入
ここに画像の説明を挿入

暗黙的な内部結合

select * from dept3,emp3 where dept3.deptno = emp3.dept_id;
-- 如果两张表的列相同,可使用 表名.列名 来区分

ここに画像の説明を挿入
明示的な内部結合

select * from dept3 inner join emp3 on dept3.deptno = emp3.dept_id;

ここに画像の説明を挿入

外部結合クエリ

MySQL のアウター ジョイン (アウター
ジョイン) は、2 つ以上のテーブルから結合条件を満たすレコードと、結合条件を満たさないレコードの一部またはすべてを返すために使用されるクエリ メソッドです。外部結合は、メインテーブルと結合テーブル間の関係を取得し、一致しない行を含めるのに役立ちます。

外部結合クエリは次のように分類されます。

  • 左外部結合クエリ
  • 右外部結合クエリ
  • 完全外部結合クエリ

左外部結合クエリ

MySQLの左外部結合クエリ(LeftOuterJoin
)は、左側のテーブル(メインテーブル)からすべての行を返し、右側のテーブル(結合テーブル)の結合条件を満たす行を一致させることで、テーブル間の関連データを取得するクエリメソッドです。左外部結合では、右側のテーブルに一致する行がない場合でも、左側のテーブルのすべての行が保持されます。

左外部結合は、左側のテーブルの各行を右側のテーブルの一致する行と結合し、一致する結果セットを返します。右側のテーブルに一致する行がない場合は、NULL 値を返します。

select * from 表A left outer join 表B on 条件;
ここに画像の説明を挿入

select * from dept3 left outer join emp3 on dept3.deptno = emp3.dept_id;

ここに画像の説明を挿入

ここでは、人事部には従業員がいませんが、左外部接続なので左のテーブルのデータがすべて表示されるはずなので、人事部のデータにはNULLを入れています。

右外部結合クエリ

MySQLの右外部結合クエリ(RightOuterJoin)は、結合条件を満たす右側のテーブル(結合テーブル)の行と、左側のテーブル(メインテーブル)の一致する行をすべて返すことで、テーブル間の関連データを取得するクエリメソッドです。右外部結合では、左側のテーブルに一致する行がない場合でも、右側のテーブルのすべての行が保持されます。

右外部結合は、右側のテーブルの各行を左側のテーブルの一致する行と結合し、一致する結果セットを返します。左側のテーブルに一致する行がない場合は NULL を返します。

select * from 表A right outer join 表B on 条件;

ここに画像の説明を挿入

select * from dept3 right outer join emp3 on dept3.deptno = emp3.dept_id;

ここに画像の説明を挿入
1005には該当する部署がないためNULLを入力してください。

左外部結合は、位置を交換することで 2 つのテーブル間の変換を実現できます。

select * from emp3 left outer join dept3 on dept3.deptno = emp3.dept_id;

完全外部結合クエリ

完全外部結合は、左側のテーブルと右側のテーブルのすべての行を同時に返し、結合条件を満たす一致する行を返すクエリ メソッドです。左右のテーブルからすべてのデータを取得し、それらを関連付けることができます。

完全外部結合は、実際には、右外部結合のデータを左外部結合のデータの下にスプライスするか、左外部結合のデータを右外部結合のデータの下にスプライスします。

ただし、MySQL は完全外部結合をサポートしていませんfull outer join。これを使用しunionて完全外部結合を実現できます。また、完全外部接続には、完全外部接続を削除する方法と、完全外部接続を削除しないunion方法の 2 つがあります。左外连接 union 右外连接;左外连接 union all 右外连接;

ここに画像の説明を挿入
ここに画像の説明を挿入

重複排除された完全外部結合

select * from dept3 left outer join emp3 on dept3.deptno = emp3.dept_id
union
select * from dept3 right outer join emp3 on dept3.deptno = emp3.dept_id;

ここに画像の説明を挿入
外部結合を重複排除しないでください

select * from dept3 left outer join emp3 on dept3.deptno = emp3.dept_id
union all
select * from dept3 right outer join emp3 on dept3.deptno = emp3.dept_id;

ここに画像の説明を挿入

サブクエリ

MySQL サブクエリ (Subquery) は、1 つの SQL クエリ内に別の完全な SQL クエリをネストすることを指します。サブクエリには、通常のクエリと同様に、SELECT、FROM、WHERE などの句を含めることができ、外部クエリで直接使用できる結果セットを返すことができます。

サブクエリは、複雑なクエリをより小さく管理しやすいクエリ ブロックに分解し、ネストを通じてより柔軟で正確なクエリの目的を達成するためによく使用されます。SELECT、FROM、WHERE などの句にネストして、データのフィルタリング、並べ替え、計算、結合を行うことができます。

サブクエリによって返されるデータには次の 4 種類があります。

  1. 単一列と単一行: 単一値データとして理解できる、特定の列の内容を返します。
  2. 単一行と複数列: データ行の複数列の内容を返します。
  3. 複数行と複数列: レコードの複数行の同じ列の内容を返します。これは、操作範囲を指定するのと同じです。
  4. 複数の行と複数の列: クエリによって返される結果は一時テーブルです。

特定の部門に誰がいるかを知る必要がある場合、最初にこの部門が表す部門番号を知る必要がありますか。部門番号は従業員情報テーブルに格納されており、部門がわかればそこに誰がいるかを知ることができるからです。番号。

-- 查询销售部有哪些人
select deptno from dept3 where name = '销售部';

ここに画像の説明を挿入
部門番号がわかったら、従業員テーブルから部門番号 1002 の人の情報を見つけます。

select ename from emp3 where dept_id = 1002;

ここに画像の説明を挿入
select deptno from dept3 where name = '销售部';の結果は 1002 であるため、このクエリを に直接ネストできますselect ename from emp3 where dept_id = 1002;select ename from emp3 where dept_id = (select deptno from dept3 where name = '销售部');

select ename from emp3 
where dept_id = (select deptno from dept3 where name = '销售部'); -- 返回单行单列

ここに画像の説明を挿入

研究開発担当者および営業担当者の情報を照会します。

select eid,ename from emp3 
where dept_id 
in (select deptno from dept3 where name in ('研发部','销售部'));

ここに画像の説明を挿入

-- 查询研发部30岁以下的员工信息,包括员工号,员工名字,部门名字
select eid,ename,name from (select * from emp3 where age < 30) t1
join (select * from dept3 where name = '研发部') t2
on t1.dept_id = t2.deptno;

最終的には社員番号、社員名、部署名を表示する必要があるため、これらのデータが2つのテーブルに分かれているため、2つのテーブルを組み合わせてそれぞれのテーブルのデータを判断する必要があります。

ここに画像の説明を挿入

サブクエリキーワード

サブクエリでよく使用される論理キーワードがいくつかあります。

  • すべてのキーワード
  • 任意のキーワード
  • いくつかのキーワード
  • INキーワード
  • EXISTS キーワード

すべてのキーワード

MySQL では、キーワード ALL をサブクエリで使用して、サブクエリによって返された結果を外部クエリ条件と比較できます。

キーワード ALL がサブクエリと組み合わせて使用​​される場合、外側のクエリ条件がサブクエリによって返されるすべての値と比較され、外側のクエリ条件がすべての値より大きいか小さい場合にのみ比較される必要があることを意味します。サブクエリでは、条件が満たされたとみなされます。

select ... from ... where c > all(查询语句);

-- 查询员工表中年龄大于1003部门所有员工的年龄的信息
select * from emp3 where age > all(select age from emp3 where dept_id = 1003);

ここに画像の説明を挿入

-- 查询不属于任何部门的员工的信息
select * from emp3 where dept_id != all(select deptno from dept3);

ここに画像の説明を挿入

任意のキーワードといくつかのキーワード

MySQL では、ANY および SOME キーワードをサブクエリで使用して、外側のクエリ条件をサブクエリによって返された結果セット内の任意の値と比較できます。

これら 2 つのキーワードの機能は似ており、両方とも、条件が満たされたと判断するには、外部クエリ条件がサブクエリによって返された結果セット内の任意の値と一致するだけでよいことを示します。

select ... from ... where c > any/some(查询语句);

-- 查询年龄大于1003部门任何一个员工的员工信息
select * from emp3 where age > any(select age from emp3 where dept_id = 1003);

ここに画像の説明を挿入

INキーワード

IN キーワードは、外部クエリ条件がサブクエリ結果セット内の値と一致するかどうかを確認するために使用されます。外部クエリ条件は、サブクエリ結果セット内の値と一致する場合に満たされたとみなされます。

select ... from ... where c in(查询语句);

-- 查询部门为研发部和销售部的员工的信息
select * from emp3 
where dept_id 
in (select deptno from dept3 where name = '研发部' or name = '销售部');

ここに画像の説明を挿入

EXISTS キーワード

EXISTS キーワードは、サブクエリに結果があるかどうかを判断するために使用されます。結果がある場合は、条件を満たしているとみなされ、前のクエリ ステートメントが実行されます。サブクエリに結果がない場合は、条件を満たしていないとみなされます。条件が一致すると、前のクエリは実行されません。

select ... from ... where exists(查询语句);

年齢が 60 歳以上の従業員の情報をクエリするとします。

-- 查询年龄大于60岁的员工信息
select * from emp3 where exists (select * from emp3 where age > 60);

ここに画像の説明を挿入
ここには全従業員の情報が表示されていますが、これはなぜでしょうか? EXISTS の背後にあるサブクエリでは、検索オブジェクトは emp3 のテーブル全体であるため、各クエリには結果があり、emp3 内のすべての情報が出力されるため、どうすればよいでしょうか。

MySQL のクエリ プロセスをレコードごとのスクリーニングとして視覚化できるため、テーブル エイリアスを使用して、各レコードの従業員の年齢が 60 歳を超えているかどうかを判断できます。

-- 查询年龄大于60岁的员工信息
select * from emp3 t where exists (select * from emp3 where t.age > 60);

ここに画像の説明を挿入

ほとんどの状況では、where assigns も使用できますが、MySQL の基礎となる Exist が最適化されており、クエリ効率が高いため、exists を使用することをお勧めします。

自己関連付けクエリ

MySQL 自己関連付けクエリとは、クエリ内の結合操作に同じテーブルを使用して仮想関連付けを作成することを指します。自己関連付けクエリでは、テーブルを 2 つ以上の別個のテーブルとして扱い、クエリ内でそれらを参照できます。

自己関連付けクエリでは通常、クエリ内でテーブル エイリアスを使用して、同じテーブルの異なるインスタンスを参照できるようにします。このように、列をそれ自体と比較することにより、関連関係を確立できます。

自己関連付けクエリは、階層構造やリレーションシップ チェーンなどを含むデータを処理する場合に非常に役立ちます。一般的なアプリケーション シナリオには、管理階層関係の取得、関連レコードの検索、親族関係の取得などが含まれます。

MySQL セルフクエリではエイリアスを使用する必要があります。エイリアスを使用しないとエラーが発生します。

自己相関用にいくつかのデータを準備します。

create table t_sanguo(
	eid int primary key,
	ename varchar(20),
	manager_id int,
	foreign key (manager_id) references t_sanguo (eid));
	
	insert into t_sanguo values(1,'刘协',NULL),
								(2,'刘备',1),
								(3,'关羽',2),
								(4,'张飞',2),
								(5,'曹操',1),
								(6,'许褚',5),
								(7,'典韦',1),
								(8,'孙权',1),
								(9,'周瑜',8),
								(10,'鲁肃',8);

一人ひとりに応じた優れた情報を表示する必要がある。

select t1.ename,t2.ename manager 
from t_sanguo t1 join t_sanguo t2 
on t1.manager_id = t2.eid; 

ここに画像の説明を挿入
Liu Xie の優れた情報も表示する必要があるため、左外部結合を使用します。

select t1.ename,t2.ename manager 
from t_sanguo t1 left join t_sanguo t2 
on t1.manager_id = t2.eid; 

ここに画像の説明を挿入

おすすめ

転載: blog.csdn.net/m0_73888323/article/details/131967773