技術とか戦略とか

IT技術者が技術や戦略について書くブログです。

テーブル結合のキーはテーブル間で同一の値を用いること

当たり前のことなのですが、テーブル結合の際には、結合に必要なキーはテーブル間で同一の値を用いて、結び付けができるようにする必要があります。
プログラムでキーとなる値を順次生成する場合、テーブルへのinsertの際にテーブル毎に別々の値を生成してしまうというミスをしないようにする必要があります。
 
--------------------
 
例えば、以下のようなテーブルが存在するとします。
 
・利用料金テーブル
create table usagefee
(
usage_id CHAR(10) NOT NULL, --利用番号
use_date CHAR(8) NOT NULL, --利用日
shop_name CHAR(40) NOT NULL, --店名
fee DECIMAL(10) NOT NULL, --利用料金
PRIMARY KEY (usage_id)
);
 
・利用料金明細テーブル
create table usagefee_detail
(
usage_id CHAR(10) NOT NULL, --利用番号
detail_id CHAR(3) NOT NULL, --枝版
item_name CHAR(40) NOT NULL, --商品名
fee DECIMAL(10) NOT NULL, --利用料金
PRIMARY KEY (usage_id,detail_id)
);
 
--------------------
 
結合する時に指定するキーは利用番号になるため、以下のように利用番号には同一の値を使用する必要があります。
 
insert into usagefee values("0000000001","20201201","Shop_A",10000);
insert into usagefee_detail values("0000000001","001","Item_A",5000);
insert into usagefee_detail values("0000000001","002","Item_B",5000);
select *
from  usagefee p
join  usagefee_detail c
on   p.usage_id = c.usage_id;
 
Query OK, 1 row affected (0.01 sec)
Query OK, 1 row affected (0.01 sec)
Query OK, 1 row affected (0.00 sec)
+----------+--------+---------+-----+----------+---------+---------+----+
|usage_id |use_date|shop_name|fee |usage_id |detail_id|item_name|fee |
+----------+--------+---------+-----+----------+---------+---------+----+
|0000000001|20201201|Shop_A  |10000|0000000001|001   |Item_A  |5000|
|0000000001|20201201|Shop_A  |10000|0000000001|002   |Item_B  |5000|
+----------+--------+---------+-----+----------+---------+---------+----+
2 rows in set (0.00 sec)
 
--------------------
 
しかし、利用番号がプログラム中で生成する連番であり、かつプログラム中で利用料金テーブルと利用料金明細テーブルで別々に連番を付与していた場合、利用番号で結びつかなくなってしまいます。
 
insert into usagefee values("0000000001","20201201","Shop_A",10000);
insert into usagefee_detail values("0000000002","001","Item_A",5000);
insert into usagefee_detail values("0000000002","002","Item_B",5000);
select *
from  usagefee p
join  usagefee_detail c
on   p.usage_id = c.usage_id;
 
Query OK, 1 row affected (0.01 sec)
Query OK, 1 row affected (0.01 sec)
Query OK, 1 row affected (0.00 sec)
Empty set (0.00 sec)
 
こうなると、利用料金テーブルと利用料金明細テーブルを結合するという使い方ができなくなり、後で困ることになります。
更に、既にサービスイン後であり過去データの補正が必要になった場合、その補正も困難になる場合があります。