お疲れ様です!
はるさらでございます。
oracleでテーブルを結合したかったが
「レコードが選択されませんでした。」が
表示されてしまう。
レコード自体はしっかり登録しているのになぜ!?
と悩んでしまった方へ向けての記事になります。
「こんな失敗パターンもあるのか~」
くらいで見ていただければ幸いです。
実行したSQL
【create文】
create table SHOP(SHOP_NAME VARCHAR2(10),
ID VARCHAR2(4));
create table FRUIT(FRUIT_NAME VARCHAR2(10),
ID CHAR(4),
PRICE NUMBER(6));
【select文】
SELECT SHOP_NAME,FRUIT_NAME,PRICE
FROM SHOP S, FRUIT F
WHERE S.ID = F.ID;
↓select文の実行結果
「レコードが選択されませんでした。」が
表示されてしまっています・・・。
SQL自体に誤りはありません。
では、なぜレコードが選択されなかったのでしょう?
原因
今回登録したテーブル定義に注目です!
・SHOPテーブル.ID→VARCHAR2(4)
・FRUITテーブル.ID→CHAR(4)
の様に、結合条件に指定したカラムに型の違いがあります。
CHAR型とVARCHAR型では
指定した最大文字数に達しなかった場合の
値の保持の仕方が変わります。
最大文字数4文字のカラムに1文字のレコードを登録した場合
VARCHAR型
・「1」が登録される
CHAR型
・「1___」が登録される。
※_は空白行だと思ってください。
最大桁数に満たなかった分は、空白で補われてしまいます。
その為、空白を除去してあげないと
正しい結合が出来ないのです。
かつ、格納されたデータを取得しようとすると
末尾についている空白は削除されて取得されるため
SELECTの結果では違いが分からないのですよ・・・
でも、結合の時は意識しないと
紐づかなくなってしまいます・・・。
うーん。ややこしい。
改めてテーブル結合!
結合の際は
trim関数を使用して
空白を取り除きましょう!!
✕-ダメなパターン
SELECT SHOP_NAME,FRUIT_NAME,PRICE
FROM SHOP S, FRUIT F
WHERE S.ID = F.ID;
○-良いパターン
SELECT SHOP_NAME,FRUIT_NAME,PRICE
FROM SHOP S, FRUIT F
WHERE S.ID = trim(F.ID);
これにより、想定通りの結果が表示されることが
確認できました!!