• ベストアンサー

数値をNUMBER型にするかCHAR型にするか。

テーブルのカラムで、2005という文字を格納したい場合、 属性として、NUMBER型、CHAR型の選択ができると思います。 ●テーブル名 TABLE1 カラム名 A B 属性 ??? char データ 2005 XXXX ●テーブル名 TABLE2 カラム名 A C 属性 ??? char データ 2005 XXXX このカラムAが、TABLE2のAの2005という値と結合させる (結合させるためのキーとなっている場合) ということがある場合、NUMBER型での定義とchar型での定義に 速度的な観点やその他の観点で、なにか差異みたいなものはありますでしょうか? 下記のように、値を指定するところでは、シングルコーテーションが必要か不必要かというのは、あるかと思いますが、 結合自体で、差異はありますでしょうか? ■CHAR型にした場合。 select * form TABLE1,TABLE2 where A='2005' and TABLE1.A=TABLE2.A ■NUMBER型 select * form TABLE1,TABLE2 where A=2005 and TABLE1.A=TABLE2.A

質問者が選んだベストアンサー

  • ベストアンサー
noname#87380
noname#87380
回答No.3

No.2への回答です。 > 片一方は、CHAR型、もう片方は、VARCHAR2であるというのは、 > 避けたほうが良いということでしょうか? 型違いはできるだけ避けた方が良いかと。 CHARとVARCHAR2は固定長か可変長かの違いがありますので 比較条件に指定した場合、意図しない結果となる場合があります。 例えばCHAR(3)の列とVARCHAR2(3)の列に'A'という文字が 格納されていて、それらを比較しようとした場合ですね。 CHAR型は'A 'という文字列に、VARCHAR2型は'A'という文字列になり これらを比較した結果、一致ぜず…という事になります。 片方がNUMBER型、もう片方がCHAR型もしくはVARCHAR2型である場合は 比較を行うと一致はしますが、No.2で書いた通り型変換が行われる分だけ 性能面で影響がでてきます。

takokko
質問者

お礼

詳細なご回答本当にありがとうございます。

全文を見る
すると、全ての回答が全文表示されます。

その他の回答 (3)

  • mitoneko
  • ベストアンサー率58% (469/798)
回答No.4

 型違いのデータを結合・比較・その他の処理をするときには、当然、どちらかの型に他方を「変換」するわけです。  今回のcharとvarcharの事例ですと、固定長の文字列と可変長の文字列間の変換となります。  OLACLE上でどちらがどちらに変換され、どのように扱われるかは、No3の方も一部事例をかかれていますように、厳密に定義されています。  さて、この規約をちゃんと正確に覚えているプログラマーは立派です。少なくとも、私は自信がありません。必要なときには、必ずマニュアルの該当箇所を確認します。(これがましてや、NUMBERとVARCHAR(または、CHAR)となったら、徹底したテストもしたい(苦笑))  つまり、とっても面倒です。  世の中、どうしても、その必要があり、必要に迫られて型変換をせざるを得ないことは往々にしてありますが、今から設計するシステムでその必要がないなら、そんなモノはしないのが一番です。プログラムを作成し、修正していく課程で他に考えなくてはいけないことはたくさんあります。なにも、よけいな心配を増やす必然性はさらさらありません。というか、よけいな心配事を一つでも減らしていけるように、データ型というのは設計していくべきでしょう。  ですから、結論としては、どうしても型違いでなければならない理由が無いのであれば、型は同じにしておくべき。となるでしょうね。  ちなみに、NUMBERとCHAR(VARCHAR)の選択に関しては、利用用途によっては、まだ他にも考慮点が思いつきます。  もし、その列でソートするとき、2005と305は、どちらが大きいですか?といった話がプログラム作成に負荷をかける可能性があります。当然、数値としては2005ですが、文字列として考えると、桁あわせをどうするか等いろいろと考える必要があります。本当に、この数字が文字列なら、どちらが大きいかは、「業務の定義による」というのが正解ですし…。  基本的には、その項目で計算をするかどうかと言うよりは、業務としての定義上、その項目が数・数値なのか、それとも、0~9までの文字を使用した文字列(符号)なのか、そのどちらかによって決定するのが、経験上、プログラムもシンプルになるように思います。  蛇足ですが、業務上の定義によっては、それは、DATE型ではありませんか?というのも一つの選択肢としてあり得るかと。

takokko
質問者

お礼

ご回答本当にありがとうございます。

全文を見る
すると、全ての回答が全文表示されます。
noname#87380
noname#87380
回答No.2

こんにちは。 私も No.1 PCFREAK様と同意見です。 (なのでポイント辞退。 同じ意見の人が同じ事を書いてるな…くらいに考えてくださいな^^;) 結合時、TABLE1のカラムAとTABLE2のカラムAの型が それぞれ違った場合は、暗黙の型変換が生じますので影響があります。 しかし今回の場合は同じ型という事で差異がありません。 型の違いによる差異ですが  固定長より可変長の方がサイズが小さい    ↓  全体的にレコードを格納するブロック数が少なくなる    ↓  読み取り時のブロック数が少なくなり、読み取り性能に差が出る という考えです。 今回はデータサイズにほどんど差がないため影響がない程度と思います。 あと… キー項目には、連番以外の目的でNUMBER型を使うとアプリ開発者側に 色々と誤解を生じさせてしまう事があるので、私も使わないようにしてます。

takokko
質問者

お礼

回答ありがとうございます。 型の違いによる差異について、もう少しお教え願えますでしょうか? 片一方は、CHAR型、もう片方は、VARCHAR2であるというのは、 避けたほうが良いということでしょうか?

全文を見る
すると、全ての回答が全文表示されます。
  • PCFREAK
  • ベストアンサー率51% (417/805)
回答No.1

結合自体には差がありません。 速度的には、若干NUMBERの方が速いのではと予想出来ますが、ほぼ無視できる差だと思われます。 どちらを採用するかは設計思想に依存しますね。 数値として取り扱うのであればNUMBER型ですが、文字として扱うのであればCHAR型を使うのが正でしょう。 私個人的にはキーにNUMBER型を使うのは極力好ましくない(特別な理由があるのであれば別ですが。)と考えている為、CHAR型(厳密にはVARCHAR2型)を採用する事が多いです。

takokko
質問者

お礼

回答ありがとうございます。 その値を使って計算させるわけではないので、CHAR型にしようと思います。 PCFREAK様は、キーにNUMBER型を使うのは極力好ましくないとありますが、 それは、なんでなのでしょうか? また、「厳密にはVARCHAR2」とおっしゃってますが、 それは、なにか意図があるのでしょうか? 知識不足で申し訳ありませんが、よろしくお願いいたします。

全文を見る
すると、全ての回答が全文表示されます。

関連するQ&A

  • SQL文について

    テーブルの結合について教えてください。 (DBはオラクルです) select * from table1,table2 where table1.カラム名=table2.カラム名; で、結合が出来ることは分かりました。 やりたいことはテーブルの結合と、ある期間のデータを持ってきたいのです。 select カラム名 from table1 where カラム名 between '20020213' and '20020218'; で期間を決めて引き出すやり方も分かっています。 一度に結合と期間を決めて引き出すやりかたってどうすればよいですか? それとも不可能ですか? 教えてください。

  • Oracleのupdate文について

    OracleでテーブルB、Cを結合し取得できた項目で、テーブルAを更新したいのですがSQLがわかりません。結合結果とテーブルAは1:1にはなりません。 件数が結合結果>テーブルAの時もあれば、その逆の場合もあります。また、複数項目を更新したいです。実行して考えてみたいのですが、明朝客先ですぐに実行しなければならず(テスト環境はあるので明日そこで一旦確認後、すぐに本番環境で実行)、現在移動中→ホテル泊のため余裕がありません。 ネットで下記を見つけたのですが、更新する項目に更新日時を追加したいのと、テーブルAとの紐付けやEXISTSのWHEREはテーブルBとC両方の項目に紐づけたいです。 また、テーブルAの更新条件に、テーブルB、Cにはないcolumn③に対する条件も追加したいです。 UPDATE [TABLE①] A SET (COLUMN①, COLUMN②) = ( SELECT B.COLUMN, C.COLUMN FROM [TABLE②] B, [TABLE③] C WHERE B.COLUMN = C.COLUMN AND B.COLUMN = A.COLUMN ) WHERE EXISTS ( SELECT 1 FROM [TABLE②] B2 WHERE B2.COLUMN = A.COLUMN) もろもろとわかりづらい説明&他力本願で心苦しいのですが、どなたか教えていただけないでしょうか?

  • Select文で結合した時に、重複カラムが存在するのでテーブル名を先頭

    Select文で結合した時に、重複カラムが存在するのでテーブル名を先頭か末尾に自動でカラム名に付与して表示したいのですが、いい方法はないでしょうか? (asで1個1個変えるのではなく・・・) SELECT TABLE_A.*,TABLE_B.* FROM TABLE_A LEFT JOIN TABLE_B ON TABLE_B.ID = TABLE_A.ID 表示 : TABLE_A_ID | TABLE_B_ID みたいのを考えています。

    • ベストアンサー
    • MySQL
  • 複数テーブルからデータを取り、updateする

    http://oshiete1.goo.ne.jp/kotaeru.php3?q=1211685 にも同じような質問があったのですが、同様の処理でうまくupdateされません。分かる方がいらっしゃいましたら教えてください。 今、テーブルが2つ(table1、table2)があり、それぞれ2つのカラム(column1、column2)を持っています。ここで、それぞれのカラム2が等しく、カラム1が指定した値のレコードのみ値をupdateしたいです。 update table1 set column1 = 'AAA' from table1,table2 where table1.column2 = table2.column2 and table1.column1 = 'BBB' and table2.column1 = 'CCC' としたところ、「from table1,table2 where 」の辺りに間違いがあると表示されます。 上の例とどう違うのか分かりません。 よろしくお願いします。m(__)m

  • SQLServer T-SQL テーブルのJOIN

    こんにちは。 テーブル"TABLE_A"、"TABLE_B"があり、 各々のテーブルにカラム"COL"があります。 カラム"COL"にインデックスを作成しています。 テーブル"TABLE_A"、"TABLE_B"をカラム"COL"で結合 する際の演算子にLIKE文を用いています。"TABLE_B"の カラム"COL"に"%"を付加していますが、これが原因で "COL"のインデックスが効きません。どのようにすれば LIKE検索でインデックスを有効にすることができるの でしょうか? SELECT * FROM TABLE_A INNER JOIN TABLE_B ON TABLE_A.COL LIKE TABLE_B.COL+'%'

  • distinct をexistsに変換する

    distinctをexistsに変換した方がパフォーマンスが良いようで、 例えば以下の例があるとします ---------------------------------- (前)SELECT DISTINCT a.ID1, a.NAME1 FROM TABLE1 a, TABLE2 b WHERE a.ID1 = b.ID2 (後)SELECT a.ID1, a.NAME1 FROM TABLE1 a    WHERE EXISTS ( SELECT 'X' FROM TABLE2 b WHERE a.ID1 = b.ID2) ---------------------------------- もっと複雑なSQLの場合、EXISTSに変換できるのでしょうか?。複雑なSQLとは、 「複数のテーブルからカラムを取得」「テーブル結合が2つ以上」「外部結合」 などのSQLで、以下に例を示します。 (例)SELECT DISTINCT a.ID1,a.NAME1,b.ID2,b.NAME2,c.ID3,c.NAME3    FROM TABLE1 a,TABLE2 b,TABLE3 c    WHERE a.ID1 = b.ID1(+)      AND a.ID1 = c.ID1(+)

  • javaにてデータ取得

    JAVAカテゴリーで質問しようかこちらにしようか迷ったのですが。。。 あるテーブルを以下の様に内部結合しています。 select * from t_table a, t_table b where a.id=b.id and a.no=0 and b.no=1 この時、t_tableのあるカラムtestcolを取得したいとおもっております。 言語はjavaで、データベースはpostgreSQLです。 rs.getString("testcol"); rsはResultSetオブジェクトです。 これで、データは取得できるのですが、条件のt_tableの別名aのデータ が取得されます。別名bの方を取得したいと思い、単純に rs.getString("b.testcol"); 等としたら、「カラム名がありません」というエラーになりました。 getStringのパラメータとして、カラムインデックス(数値)も 指定できるので、それで行うと取得可能でした。 カラムインデックス指定ですと、プログラムのメンテナンス上支障をきたす ので、なんとか、カラム名の指定で行いたいと思っておりますが、 どうすればいいのでしょうか?

  • カラムの存在チェック

    あるテーブルに、あるカラム(列)が存在するかどうかを調べる方法はあるのでしょうか? ・あるテーブル(TABLE_A)に、あるカラム(COLUMN_A)が存在しない場合はALTER TABLE ~ ADD でカラム(COLUMN_A)を追加する ・COLUMN_Aがある場合は何もしない というSQL文を作成したいのですが… 宜しくお願いします。

  • テーブルの結合時に空のカラムに『NULL』を入れない方法について

    宜しくお願いします。 MySQLでleft joinでテーブルの結合を行った際に、表示に必要なカラムのみを定義した場合に、空のカラムに『NULL』が入ってしまい、絞込みで検索時にこの『NULL』が邪魔になり、きちんと検索できません。left joinでテーブルを結合する場合に空のカラムに『NULL』が入らない様にする方法はありますか? クエリ文 select a.column1,b.column2 from a left join b on a.column3 = b.column3 where column2 like '%%'; 上記の様に検索した場合、likeで曖昧検索の上、検索内容を指定していないので、全データが検索されるかと思ったのですが、テーブルbのcolumn2が空のカラムは検索されず、HIT数が減ります。このwhereは必須で、どうしても入れなければならない状況なので、空のカラムも検索する方法があると助かります。 何卒、ご教授の程、宜しくお願いします。

    • ベストアンサー
    • MySQL
  • インラインビューの更新権限について

    UPDATE句をインラインビューを使って実施しようと思い UPDATE ( SELECT A.FLD1,B.FLD2 FROM TBL1 A,TBL2 B WHERE A.KEY1=B.KEY1 AND CONCAT(A.KEY2,A.KEY3)=B.KEY2 AND B.KEY2='12345') C SET C.FLD1=C.FLD2 のようにSQLを書きました。 ORA-01779: キー保存されていない表にマップする列は変更できません のメッセージが出力されました。 CREATE VIEW TEST AS SELECT A.FLD1,B.FLD2 FROM TBL1 A,TBL2 B WHERE A.KEY1=B.KEY1 AND CONCAT(A.KEY2,A.KEY3)=B.KEY2 AND B.KEY2='12345' でビューを作って確認したら select * from user_updatable_columns where table_name='TEST'; OWNER TABLE_NAME COLUMN_NAME UPDATA INSERT DELETA ---------- ----------- --------------- ------ ------ ------ TEST TEST FLD1 NO NO NO TEST TEST FLD2 NO NO NO 確かにUPDATEできないようです。 テーブルはこんな感じです。 TBL1 ------------------------------------------- KEY1 NUMBER 4 PK KEY2 NUMBER 5 PK KEY3 NUMBER 1 PK FLD1 CHAR 6 TBL2 ------------------------------------------- KEY1 NUMBER 4 PK KEY2 NUMBER 6 PK FLD2 CHAR 6 同じように TBL3 ------------------------------------------- KEY1 NUMBER 2 PK KEY2 NUMBER 4 PK KEY3 CHAR 6 PK KEY4 NUMBER 4 PK FLD3 CHAR 6 TBL4 ------------------------------------------- KEY1 NUMBER 4 PK KEY2 CHAR 6 PK FLD4 CHAR 6 でビューを作ったら CREATE VIEW TEST2 AS SELECT A.FLD3,B.FLD4 FROM TBL3 A,TBL4 B WHERE A.KEY2=B.KEY2 AND A.KEY3=B.KEY3 AND A.KEY1='12' AND A.KEY4='1234' OWNER TABLE_NAME COLUMN_NAME UPDATA INSERT DELETA ---------- ----------- --------------- ------ ------ ------ TEST TEST2 FLD3 YES YES YES TEST TEST2 FLD4 NO NO NO 更新可能なようです。 ビューを作ったとき、UPDATEやINSERT文が有効・無効になる違いは何でしょうか? 毎回一旦ビューを作って select * from user_updatable_columns where table_name='TEST'; のような確認しかできないのでしょうか? よろしくお願いいたします。