CREATE TABLE等で出てくる'PRIMARY KEY'と'UNIQUE()'の違いが分かりません。
どちらも他の行と同じ値を登録させないためのものと認識しています。
どのように使い分けるのでしょうか。

あとINDEX()について教えてください。
これは挿入や更新のたびに、INDEXにした列の値の順に整列され、探索が高速になるものと認識しています。
これは'PRIMARY KEY'や'UNIQUE()'の列に対してもやらないといけないのですか。
テーブルは'PRIMARY KEY'や'UNIQUE()'に設定した列の値を基に随時整列されていると思っていたのですが・・・。

あと複数の列へINDEX()を設定することはできるのでしょうか。
その場合、どの列の値が優先的に整列されるのでしょうか。
複数列へINDEX()を設定するCREATE TABLEの書き方を、よろしければ教えてください。

このQ&Aに関連する最新のQ&A

A 回答 (4件)

>自分で調べるのと、人に聞くのと、どっちが早いかは、人によって違うと思います。

それは私が判断します。

ここは、「自分なりに調べて、分からない部分を具体的に示して質問する」ことがルールになっています。
他人に調べてもらいたいなら、「はてな」の人力検索などを利用してみては?

>しかしINDEXについては色んな列に個別に設定できるのでまだ意味不明です
>CREATE TABLE test4(a INT, b INT, c INT, INDEX(a), INDEX(b, c));
>例えばこのようなテーブルを作成した場合、テーブル全体がどのように整列されるのか

テーブル自体は、整列なんてされませんよ?インデクス上で、キー値が整列されるだけです。
RDBMSによっては、primary keyにクラスタリングといった機能を持たせたりして、なるべくその近傍にデータを格納するといった機能を実装しているものもありますけど。

例えば、学生なり、社員などを管理するテーブルを考えてみましょう。
学生idや社員idは、一人に1個、その人を識別するためのものだから、primary keyにするでしょう。
また、それ以外に各人で一意にしたい情報があれば、uniqueを定義することになります。
また、氏名などは同姓同名がいる可能性があるので、もしそういったインデクスを定義する場合は、create table文のindex句、あるいはcreate index文で定義することになります。

なお、インデクスは、検索条件によるデータの絞込み、order by、group by、distinctなどで必要になるソートで「作業メモリやファイルを使用したソート抑止」などで活用できると、大きな性能向上ができます。その一方で、追加、削除、キー値の更新などでは、性能劣化になるため、無闇にインデクスを作成することは避ける必要があります。

次のリンクは、インデクスの構造、どういう操作で有効かについて、Oracleを例にした記事です。
http://itpro.nikkeibp.co.jp/article/COLUMN/20060 …

次のリンクは、MySQLでのインデクスの有効利用方法などについて、マニュアル記載箇所です。
http://dev.mysql.com/doc/refman/5.1/ja/query-spe …

参考URL:http://dev.mysql.com/doc/refman/5.1/ja/optimizat …
    • good
    • 0
この回答へのお礼

サイトのルールをざっと見直したけどそんなルールは見あたりませんでしたよ。
多分そんな面倒臭いルールにはなってないと思いますよ・・・。
だって、日常の、ふと気になったこととかでも質問できますもん。
ちなみに、質問者の過ちをいろいろ指摘して傷つけることは禁止されてました
\(^o^)/

まあ文句を言うのはここまでにして、
chukenkenkouさん、再返信ありがとうございます。
テーブル自体は、整列なんてされないとのことですが、これについては
No.2のchukenkenkouさんの回答文を読んだ時点でなんとなく話がかみ合わない気はしておりました。。。
とにかくINDEXを設定した列をWHEREやORDER BYで使えば早くなるということは理解できました。
逆に追加、削除などを行うと性能劣化につながることもなんとなく理解できました。
あとはテストを重ねて、どっちを取るかですね!

ご紹介いただいたリンクについては・・・
ごめんなさい・・・また集中力が上がったときに・・・

お礼日時:2009/05/17 02:19

追記です。



>CREATE TABLE test4(a INT, b INT, c INT, INDEX(a), INDEX(b, c));
>例えばこのようなテーブルを作成した場合、テーブル全体がどのように整列されるのか

テーブルの行データ自体は、どのような格納位置になるかは、RDBMSにより保証されません。検索時に、order by指定がなければ、検索時の並びも保証されません。
一方、a列単独と、(b,c)列には、それぞれ重複可のインデクスが定義されているので、それぞれのインデクス上では、キー値が整列された形で管理されています。

a単独のインデクスは、例えば次のような検索で、利用されます。
select * from test4 where a=100
select * from test4 where a between 101 and 200
select * from test4 where a between 101 and 200 order by a

(b,c)のインデクスは、例えば次のような検索で、利用されます。
select * from test4 where b=100
select * from test4 where b=100 and c between 1 and 10
select * from test4 where b=100 order by b,c

なお、母体データ件数が少ない場合や、重複値が多量に発生している場合は、RDBMS側が行データから探した方が早いと判断され、インデクスを使わない場合もあります。
この辺は、EXPLAINなどで確認しながら、チューニングすることになります。
    • good
    • 0
この回答へのお礼

ORDER BYがないときは主キーの順に整列されると思っていました!!!
これからはORDER BYを使う癖をつけないとダメですね!
それぞれのインデクスがどのような場面で利用されるかも理解できました!
最後の興味深い話題については、時と場合によっては、インデクスを使用せずに検索されるということですね!
しかし、まあ、そんな事は気にせず、検索条件でよく使う列についてはINDEXを設定するのが吉だと思いました!

お礼日時:2009/05/17 02:36

すぐに自分でも、調べられる内容だと思うのですが?



>CREATE TABLE等で出てくる'PRIMARY KEY'と'UNIQUE()'の違い

primary keyは、表に0~1個しか定義できず、null値は許されません。
uniqueは、表に0個以上で複数定義でき、nullを許すかどうかはnot null指定をするかどうかにより異なります。

どちらも重複チェックを効率的に行うため、主要なRDBMSでは内部的にインデクスが作成されます。

unique指定時、「null値は、重複値とは扱われない」というのが主流なのですが、SQL Serverでは、重複値と扱うといった例もあります。

また、参照制約(外部キー制約)を定義する場合、被参照表(親)にはprimary keyを定義し、参照表(子)にはforeign keyを定義します。しかし、primary keyがなくても、uniqueでnot nullの定義があれば、それで代用してくれるといった形でRDBMSで実装されていたります。

>あとINDEX()について教えてください。

重複可能なインデクスであり、create index文と意味合いとしては同じであり、create table文内で行うか、create index文内で行うかといった違いがあります。

>これは挿入や更新のたびに、INDEXにした列の値の順に整列され、探索が高速になるものと認識

何を意味しているのか分かりませんが、インデクス定義時にインデクス情報が主にB-TREE構造で作成されます。追加、更新、削除などはB-TREE構造を維持した状態で行われます。そのため、インデクスを有効利用した検索での性能は一定に保たれます。一方で、キーの追加に備えた空き領域があるため、中間キー値や同じキー値の削除&追加といった操作が殆どないような場合では、その領域はずっと使用されないことになります。また、キー値が頻繁に更新されるような場合も、無駄な領域が多くなります。
そのため、定期的にインデクスを再作成する必要があります。
    • good
    • 0
この回答へのお礼

chukenkenkouさん、ご回答ありがとうございます。
お2人のご回答を参考にしつつ自分なりに調査し、色々知ることができました。
今の私の認識はNo.1のtest001さんのお礼欄へ記載したとおりです。
INDEXについてはもうちょっと情報を収集していく必要があります。

しかしそんなことよりも、あなたに特別に言いたいのは、

>すぐに自分でも、調べられる内容だと思うのですが?

このような発言はちょっと馬鹿にされた感じがして、傷つくのでやめてほしいということです。
自分で調べるのと、人に聞くのと、どっちが早いかは、人によって違うと思います。
それは私が判断します。

お礼日時:2009/05/16 13:20

マニュアルが日本語訳されているので参照してください。



CREATE TABLE 構文
http://dev.mysql.com/doc/refman/5.1/ja/create-ta …

以下、引用
************************************************************
PRIMARY KEY は、全てのキー カラムが NOT NULL として定義されなければいけないユニーク インデックスです。もしそれらが NOT NULL として明示的に宣言されなければ、MySQL はそれらを暗示的に(そして静かに)宣言します。1つのテーブルは1つの PRIMARY KEY しか持つ事ができません。もし PRIMARY KEY が無いのにアプリケーションがテーブル内で PRIMARY KEY を要求したら、MySQL は PRIMARY KEY として NULL カラムを持たない最初の UNIQUE インデックスを返します。
************************************************************

INDEX の作成は CREATE INDEX 文です。

CREATE INDEX 構文
http://dev.mysql.com/doc/refman/5.1/ja/create-in …

複数列への INDEX も作成可能です。
複合INDEXについて調べてみてください。
カラム指定の順番がキモです。
http://dev.mysql.com/doc/refman/5.1/ja/mysql-ind …

参考URL:http://dev.mysql.com/doc/refman/5.1/ja/create-table.html,http://dev.mysql.com/doc/refman/5.1/ja/mysql-ind …
    • good
    • 0
この回答へのお礼

test001さん、ご回答ありがとうございます。
PRIMARY KEYにすればNOT NULLとしなくても自動的にNOT NULLになるのですね!

あと実験よりPRIMARY KEYやUNIQUEは自動的にインデックスになることを知りました。
ですので次の3つのCREATE文はどれもインデックスがつきます。

CREATE TABLE test1(a INT, b INT, c INT, PRIMARY KEY(a, b, c));
CREATE TABLE test2(a INT, b INT, c INT, UNIQUE(a, b, c));
CREATE TABLE test3(a INT, b INT, c INT, INDEX(a, b, c));

この例ではtest1、2、3の順で制御が厳しく、test3については特に制御はなく、どんな値でも入る
test1とtest2の違いはNULLがOKかどうか
さらにUNIQUEは1テーブルでいくつも定義できる
といったところでしょうか

しかしINDEXについては色んな列に個別に設定できるのでまだ意味不明です

CREATE TABLE test4(a INT, b INT, c INT, INDEX(a), INDEX(b, c));
例えばこのようなテーブルを作成した場合、テーブル全体がどのように整列されるのか、ちんぷんかんです・・・

お礼日時:2009/05/16 13:02

このQ&Aに関連する人気のQ&A

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています

関連するカテゴリからQ&Aを探す

このQ&Aを見た人が検索しているワード

このQ&Aと関連する良く見られている質問

QInner join と Left joinの明確な違いは?

Inner join と Left joinの違いがよくわかりません。
教えてください。

Aベストアンサー

出てくる結果が違います。

テーブル1のフィールド1に、






が、

テーブル2のフィールド1に、






が入力されている場合、

SELECT [テーブル1].[フィールド1], [テーブル2].[フィールド1]
FROM テーブル1 LEFT JOIN テーブル2 ON [テーブル1].[フィールド1]=[テーブル2].[フィールド1];
では、結果は、
テーブル1.フィールド1 テーブル2.フィールド1
1               1
2               2
3               3
4               NULL
5               NULL
6               NULL
の6レコードが出力されますが、

SELECT [テーブル1].[フィールド1], [テーブル2].[フィールド1]
FROM テーブル1 INNER JOIN テーブル2 ON [テーブル1].[フィールド1]=[テーブル2].[フィールド1];
では、結果は、
テーブル1.フィールド1 テーブル2.フィールド1
1               1
2               2
3               3
の3レコードしか出力されません。

出てくる結果が違います。

テーブル1のフィールド1に、






が、

テーブル2のフィールド1に、






が入力されている場合、

SELECT [テーブル1].[フィールド1], [テーブル2].[フィールド1]
FROM テーブル1 LEFT JOIN テーブル2 ON [テーブル1].[フィールド1]=[テーブル2].[フィールド1];
では、結果は、
テーブル1.フィールド1 テーブル2.フィールド1
1               1
2               2
3           ...続きを読む

Qmysqlのindexとprimary keyについて

indexキーとprimary keyについてですが、違いというのは、NULLが許可されるか、されないかの違いでしょうか?

データベースから検索する際に、indexキーがある方が検索スピードが速いということですが、あるHPに《PRIMARY KEY が宣言されたカラムは自動で Index Key と Unique Key が適応されます》とありました。
ですので、検索スピードを上げるには、PRIMARY KEYを設定すれば、indexキーが設定されたのと同じ事になるのでしょうか?

Aベストアンサー

単純な違いはというと、Primaryキーは一意性があり重複が許されないものです。よってそのテーブルの検索キーワードになりますから通常Indexが張られます。

Uniqueは一意性を意味します。
なので Primaryキー = Uniqueキー + Indexキー ですね。

検索スピードを上げるためには条件となる項目がPrimaryかIndexであれば早くはなりますが、Primaryはむしろテーブル設計に拠るところが大きくて、一般的に用いられるのはIndexです。
また、条件全ての項目にIndexを張る必要はありません。
条件となる項目にIndexがあり、条件文の書き方(条件文の並び順とか)によっては少ないIndexで済みます。
たくさんIndexを張るとDBが大きくなってしまいますので。

QMySQLで改行を含む文の登録のしかた(改行コード

MySQLで改行を含む文を登録したいんですが、改行を改行コードに書き換えて登録したいです。
改行コードはどのように書けばいいですか?

登録したい文:
あいうえお
かきくけこ
さしすせそ

Aベストアンサー

改行コードは¥nで登録すれば良いです。

Qsyntax error, unexpected '}' というエラーの対処法

PHPを習い始めて三日目になるのですがParse error: syntax error, unexpected '}' in C:\Program Files\Apache Group\Apache2\htdocs\****\****\game.php on line 33
というエラーがでるのですが33行目前後のどこをなおせばいいのでしょうか?
・game.php
<html>
<head>
<title>数当てゲーム</title>
</head>
<body>
<h1 style="background:#cccccc">数当てゲーム</h1>
<form method="POST" action="game.php">
1~100までの数を入力してください
<input type="text" name="answer" size="5" maxlength="3" />
<input type="sbumit" value=回答" />
</form>
<hr />
<?php
session_start();
if(is_null($_SESSION['answer'])){
mt_stand(microtime()*1000000);
$_SESSION['answer']=mt_rand(1,100);
$_SESSION['game_cnt']=0;
}
if($_POST['answer']!=""){
$_SESSION['game_cnt']++;
if($_session['answer']==$_POST['answer']){
print("おめでとうございます".
$_SESSION['game_cnt']."回で正解しました!");
session_destroy();
}else{
if($_SESSION['answer']>$_POST['answer']){
print("もう少し大きいです。");
}else
print("もう少し小さいです。");
}
}
}
?>
</body>
</html>
それとこの間違えたところをなおしたあとはいつもコンピュータを再起動しないと修正したところが適用されないのですがほかに方法はないですか?基本的な質問ですいません。

PHPを習い始めて三日目になるのですがParse error: syntax error, unexpected '}' in C:\Program Files\Apache Group\Apache2\htdocs\****\****\game.php on line 33
というエラーがでるのですが33行目前後のどこをなおせばいいのでしょうか?
・game.php
<html>
<head>
<title>数当てゲーム</title>
</head>
<body>
<h1 style="background:#cccccc">数当てゲーム</h1>
<form method="POST" action="game.php">
1~100までの数を入力してください
<input type="text" name="answer" size="5" max...続きを読む

Aベストアンサー

print("もう少し大きいです。");
}else
print("もう少し小さいです。");
のelseの後に{がないようですが、大丈夫でしょうか?

Qシングルクォーテーションとダブルクォーテーション

いつも楽しく拝見させて頂いています。
初心者ですが宜しくお願いします。
シングルクォーテーションとダブルクォーテーションの使用方法について質問させて頂きます。
select文でテーブル名を指定するときはそのまま(たとえば'名前'じゃなく名前)しないとエラーになります。そういう風なシングルクォーテーション(又はダブルクォーテーション)を使ってはいけないところ、またシングルクォーテーションにしないといけないところ、ダブルクォーテーションにしないといけないところを教えて頂けますでしょうか?もし両方OKならその違い等も教えていただけるとうれしいです。
以上宜しくお願いします。

Aベストアンサー

文字定数は、「'」で囲む必要があります。

例)SELECT 'ABC' →文字定数の'ABC'と解釈される
SELECT ABC →ABCは、表名や列名と解釈される

数値定数は、多くのRDBMSでは「'」で囲みませんが、MySQLでは独自仕様として囲むことが可能です。

例)SELECT 123 →数値定数の123
SELECT '123' →一般的なRDBMSでは文字として扱われる。MySQLでは数値としても扱える

殆どのRDBMSには予約語があり、RDBMSでは予約語を頼りに構文解析します。表名や列名に英単語やその組み合わせを使おうとすると、予約語とぶつかってしまうことがあります。

例)SELECT FROM FROM →予約語のSELECT FROMの間に「*」や列名が指定されておらず、RDBMSは構文誤りと認識する

それを回避するために、標準SQLでは「"」で表名や列名を囲みます。MySQLでは、文字コードにANSIを使う場合は、「"」で、それ以外には独自仕様で「`」(バッククォーテーション)を使います。

例)SELECT "FROM " FROM →多くのRDBMSでは「"」で囲むことで、RDBMSに最初の「FROM」は、列などの名前であることを知らせる
SELECT `FROM` FROM →ANSI以外のMySQLでは、「`」(バッククォーテション)で囲む

また、「-」(ハイフォン)を表名や列名に使う場合、「"」で囲まないと、SQLでは減算と解釈されます。このように、「"」で囲むことで、記号なども名前に使用することができます。

例)SELECT ABC-DEF →列ABCと列DEFの減算と解釈される
  SELECT "ABC-DEF" →列「ABC-DEF」と解釈される
  SELECT `ABC-DEF' →ANSI以外のMySQLでは、「"」でなく「`」(バッククォーテション)を使用

文字定数は、「'」で囲む必要があります。

例)SELECT 'ABC' →文字定数の'ABC'と解釈される
SELECT ABC →ABCは、表名や列名と解釈される

数値定数は、多くのRDBMSでは「'」で囲みませんが、MySQLでは独自仕様として囲むことが可能です。

例)SELECT 123 →数値定数の123
SELECT '123' →一般的なRDBMSでは文字として扱われる。MySQLでは数値としても扱える

殆どのRDBMSには予約語があり、RDBMSでは予約語を頼りに構文解析します。表名や列名に英単語やその組み合わせを使おうとすると、予...続きを読む

Q3つの表の外部結合

表A、B、Cの3つがあり、Aのすべての行を出力したいと考えています。
外部結合を用いるのだとは思うのですが、3つの表に対して行う場合の
書き方がわからず困っています。
ご教授いただけないでしょうか?
select * from a,b,c
where a.商品ID =b.商品ID (+) and b.商品ID (+) =c.商品ID (+)
としてみましたが、うまくいきませんでした。

Aベストアンサー

ansi構文の趣旨からいえば、結合条件と絞り込み条件は分けて書くので・・

select *
from a
left join b on (a.商品ID =b.商品ID)
left join c on (b.商品ID =c.商品ID)
where a.年月 = 任意の値

と書くのが一般的でしょうね。

QデータベースのINT型項目にNULLはNG?

以前、知り合いからデータベースのINT型の項目には出来ればNULLを許可しない(NOT NULL)方がいいと聞いたことがあるのですが、本当でしょうか?

現在不動産の物件データを登録するためのシステムを作成しており、
データベースの設計を行なっている最中なのですが、
例えば金額や面積など数字しか入力されない項目はINT型にしたいと考えています。
※データベースはMySQLになります。

ただし、
物件データ登録時に数字項目に何も入力されなければ「NULL」、
0以上の数値を入力されている場合にはそのままその数値をデータベースに登録したいと考えています。
※0を入力されている場合には「0」をそのまま入れたいです。

INT型の項目にはNULLを入れるのを避けた方がいい場合には、0を入れるような仕様に変更しようと考えているのですが、その辺のことについて教えて頂けると助かります。

ざっくりとした質問で申し訳ございませんが、宜しくお願い致します。

Aベストアンサー

物件データ登録時に数字項目に何も入力されなければ「NULL」、0を入力されている場合には「0」
本来の意図としては正しいはずです。
Nullは本来、どの値を入れればいいのかわからない値ということなので、
数字がわからない=何も入力していない ということで、Nullを指定するのは正しいはずです。
しかし、
実際に使うときには、Nullは実に不自由なので、
Nullは使うなという話がでてきます。
## 私なら、入力区分 0=未入力、1=入力 と 数値(未入力は0)と別々に持つかもしれません。

というのは例えば、
金額 100万以上の物件は何件?
というSQLに対して、100件と答えがでて、
金額 100万未満の物件は何件?
というSQLに対して、50件と答えがでたとします。
じゃあ、全物件は?・・・172件だったりします。
何故?⇒Nullが22件だったためです。
(Nullは0とは違い、どちらの検索条件にも含まれません。)
・・・この不自由さを回避するために数値項目に、Not Null制約をつけることが多いです。

Qテーブルに主キーを作らないデメリットは?

アクセスのテーブルを作るにおいて
主キーのフィールドを作らなかった場合、
どのようなデメリットや不都合がありますか?

既にいくつか主キーのないテーブルを作ってしまいました。
このまま運用しようか主キーを作るべきか悩んでいます。

SQLサーバーに移行する場合などにエラーになるのでしょうか?

Aベストアンサー

主キーがないとレコードを特定できません
この場合 ShowMeHow様の仰るようにユニークなフィールドを
設定しますと特段問題なさそうです。

自分はレコード抽出用のテンポラリーテーブルとして
積極的に主キーなしのテーブルも使用しています。

Q日付型カラムへのデータINSERT

お世話になります。ひとつご教授ください。

オラクル10g, ojdbc14でjdk1.4.2から接続です。

INSERT命令を使ってテーブルにレコードを追加する際に、DATE型のカラムに対して

INSERT TABLE_A (DATE1, ...) VALUES ('2006-4-27 12:00:00', ...);

を実行するとエラーORA-01861が出ます。そこで

INSERT TABLE_A (DATE1, ...) VALUES ('2006-4-27', ...);

このように記述して再度実行すると通ります。

このようなとき、時間の部分まで設定した値をカラムに格納したいときはどうしたらよろしいでしょうか?

よろしくお願いします。

Aベストアンサー

ごめんなさい。
説明と文例が違ってしまいました。
正しくはこちらです。

INSERT TABLE_A (DATE1, ...) VALUES (to_date('2006-4-27 12:00:00','yyyy/mm/dd hh24:mi:ss'), ...);
というように、to_date関数を使うのが一般的かと思います。

Qillegal string offset

php5.3では動いていたプログラムをphp 5.4 で動かしたらwarning illegal string offsetが出て困っています。以下のプログラムでwarningが出ないようにするにはどのようにコーディングすればよいのでしょうか?


$a = array('exists' => 'foo');
if ($a['exists']['non_existent']) {
print 1;
}
print 2;
exit;

Aベストアンサー

isset()を使えばいいと思います


このQ&Aを見た人がよく見るQ&A

人気Q&Aランキング

おすすめ情報