この文章は、ある程度プログラム等の知識があるが、データベースについてはあまり知らないというひとを対象に書かれています。
SQLとは、Structured Query Language の略で、構造化問い合わせ言語という意味になります。
SQLを覚えるメリットは、これさえ覚えておけば、どんなデータベースにも同様の方法でアクセスできることです。
まあ、データベースのシステムによって、多少の方言はありますが、基本は同じです。
ここでは、データベースの管理よりも、データベースの使用、あるいはデータベースを利用したアプリケーションの開発等の際に、重要になってくるであろうSQLを中心に、例を多用して解説します。
必要と思われるもの、重要と思われるものだけを抜粋して解説していますので、下記で解説されるのは、SQLの『一部』でしかないことを了承ください。
データベースが存在し、そこには、ash_tableという名前のテーブル(表)が存在するとします。
id | name | yomi | lv | hp | mp | 1 | hasimoto | はしもと | 15 | 49 | 25 | 2 | yanagi | やなぎ | 12 | 38 | 25 | 3 | joe | じょう | 26 | 85 | 76 | 4 | hon | ほんどう | 23 | 45 | 55 |
---|
それぞれの意味は、連番、名前、読み(平仮名)、あと、データ項目が3項目あります。
(レベルとヒットポイントとマジックポイントだと思われます)
名前と読みは文字列型、他は数値(整数)型データです。
データベースの作り方は、ここでは解説しません。
テーブルの作成については後述しますが、とりあえず、このようなテーブルがあるとして、解説をしていきます。
また、以下の解説は、psql(PostgreSQL付属ツール)などのCUIツールでのアクセスを前提に考えていますが、プログラム等からのアクセス時にも基本は同じです。
まず、SQLの使い方の基本について説明します。
SQLのキーワードは、大文字小文字は気にしません。 !?ただし、項目名や、実際のデータについては、区別します。 文字列等はシングルクォートで囲みます。 半角スペースで区切ります。 スペースはどれだけ入れても基本的に無視されます。 タブも改行も無視されます。 セミコロンで終わります。 |
テーブルのデータを検索します。 これさえ知っとけばとりあえずデータベースを『利用』することはできます、これがないと、どんなデータベースも意味がありません。
select 項目名 from テーブル名 [where 検索条件] [order by ソート方法]; |
という形式で使います。
これによって、
テーブル名で指定されるテーブルから、検索条件にマッチするレコード(1行分のデータ)を選び、項目名で指定された項目を、ソート方法に従ってソートして返す。
ということになります。
『where 検索条件』を省略すると、全件検索になります。 『order by ソート方法』を省略すると、レコードの並びが決まりません。
テーブルの項目の名前です。 テーブルを作成する際に決定された名前を指定します。 * を指定すると、全項目が返ってきます。
例: select # select * from ash_table; id | name | yomi | lv | hp | mp ----+----------+----------+----+----+---- 1 | hasimoto | はしもと | 15 | 49 | 25 2 | yanagi | やなぎ | 12 | 38 | 25 3 | joe | じょう | 26 | 85 | 76 4 | hon | ほんどう | 23 | 45 | 55 (4 rows) 例: 特定項目のみselect # select name, yomi from ash_table; name | yomi ----------+---------- hasimoto | はしもと yanagi | やなぎ joe | じょう hon | ほんどう (4 rows) |
項目名の前にdistinctをつけると、重複レコードを返さないようになります。 allをつけると、全件返ってきます。通常は、allと同様の動作です。 項目にどのようなデータが含まれるか調べたい場合などに使います。
例: all # select all mp from ash_table; mp ---- 25 25 76 55 (4 rows) 例: distinct # select distinct mp from ash_table; mp ---- 25 76 55 (3 rows) |
項目名として、計算式を書くことができます。
例: 特殊な項目名 # select yomi, lv, lv*2 from ash_table; yomi | lv | ?column? ----------+----+---------- はしもと | 15 | 30 やなぎ | 12 | 24 じょう | 26 | 52 ほんどう | 23 | 46 (4 rows) |
また、このようなときに、表示用の項目名をつけることができます。もちろん、通常の項目名にも別名をつけることができます。
例: 項目名の別名 # select yomi as kana, lv as level, lv*2 as lv2x from ash_table; kana | level | lv2x ----------+-------+------ はしもと | 15 | 30 やなぎ | 12 | 24 じょう | 26 | 52 ほんどう | 23 | 46 (4 rows) |
テーブル名を指定するだけです。あまり考えることはありません。
代表的なものは、
where 項目名 = 値 |
の形式です。 あとは、それのバリエーションだと思っても問題はありません。
データの値を比較して、条件に一致する行だけを検索します。
例: =を使う # select * from ash_table where mp = 25; id | name | yomi | lv | hp | mp ----+----------+----------+----+----+---- 1 | hasimoto | はしもと | 15 | 49 | 25 2 | yanagi | やなぎ | 12 | 38 | 25 (2 rows) |
mpが25であるレコードが返ってきます。
例: 文字列で=を使う # select * from ash_table name = 'hasimoto'; id | name | yomi | lv | hp | mp ----+----------+----------+----+----+---- 1 | hasimoto | はしもと | 15 | 49 | 25 (1 row) |
nameがhasimotoであるレコードが返ってきます。文字列にはシングルクォートを忘れないようにしましょう。
演算子は=以外にも<= >= < > などがあります。これらは主に数値型や日付型のデータに用います。
(文字列型のデータに対して用いると、文字コードの大小による検索を行います)
例: >を使う # select * from ash_table hp > 40; id | name | yomi | lv | hp | mp ----+----------+----------+----+----+---- 1 | hasimoto | はしもと | 15 | 49 | 25 3 | joe | じょう | 26 | 85 | 76 4 | hon | ほんどう | 23 | 45 | 55 (3 rows) |
hpが40より大きいレコードが返ってきます。
where 項目名 = '文字列' |
の形式を使うと、特定の文字列と一致するデータを持つレコードが返ってきます。
完全に一致するものではなく、部分的に一致するものを検索したい場合には、LIKEとワイルドカードを使います。
ワイルドカードには、%と_があり、%は0文字以上の任意の文字列、_は1文字に対応します。
(データベースの文字コード設定などによって、思ったように動作しない可能性もあります)
例: likeで%を使う # select * from ash_table where name like 'h%'; id | name | yomi | lv | hp | mp ----+----------+----------+----+----+---- 1 | hasimoto | はしもと | 15 | 49 | 25 4 | hon | ほんどう | 23 | 45 | 55 (2 rows) |
nameがhで始まるデータを持ったレコードが返ってきます。
例: likeで_を使う # select * from ash_table where name like 'h_'; id | name | yomi | lv | hp | mp ----+----------+----------+----+----+---- (0 rows) |
_は1文字に相当するため、この場合はhで始まる2文字の文字列を検索します。よって、そのようなレコードはありません。
例: likeで%と_を使う # select * from ash_table where name like '_a%'; id | name | yomi | lv | hp | mp ----+----------+----------+----+----+---- 1 | hasimoto | はしもと | 15 | 49 | 25 2 | yanagi | やなぎ | 12 | 38 | 25 (2 rows) |
_と%を組み合わせて使うこともできます。
例: %は0文字にもマッチする # select * from ash_table where name like '%i%'; id | name | yomi | lv | hp | mp ----+----------+----------+----+----+---- 1 | hasimoto | はしもと | 15 | 49 | 25 2 | yanagi | やなぎ | 12 | 38 | 25 (2 rows) |
nameにiを含むデータを持ったレコードが返ってきます。 %は0文字にもマッチするため、文字列の最後にiがある場合でも'%i%'という書き方でヒットします。
論理演算子には、and、or、notの3種類があります。
例: andを使う # select * from ash_table where lv <= 20 and hp >= 40; id | name | yomi | lv | hp | mp ----+----------+----------+----+----+---- 1 | hasimoto | はしもと | 15 | 49 | 25 (1 row) |
lvが20以下、hpが40以上、の両方の条件に適合したレコードが返ってきます。
例: orを使う # select * from ash_table where lv <= 20 or hp >= 40; id | name | yomi | lv | hp | mp ----+----------+----------+----+----+---- 1 | hasimoto | はしもと | 15 | 49 | 25 2 | yanagi | やなぎ | 12 | 38 | 25 3 | joe | じょう | 26 | 85 | 76 4 | hon | ほんどう | 23 | 45 | 55 (3 rows) |
lvが20以下、hpが40以上、のどちらかの条件に適合したレコードが返ってきます。
例: notを使う # select * from ash_table where not mp = 25; id | name | yomi | lv | hp | mp ----+----------+----------+----+----+---- 3 | joe | じょう | 26 | 85 | 76 4 | hon | ほんどう | 23 | 45 | 55 (2 rows) |
mpが25でないデータが返ってきます。
inとbetweenは、ちょっと変わった条件の指定方法です。基本的に論理演算子を使って表現できますが、inやbetweenを使えば、より簡潔に書くことができます。
例: inを使う # select * from ash_table where id in (1,3,4); id | name | yomi | lv | hp | mp ----+----------+----------+----+----+---- 1 | hasimoto | はしもと | 15 | 49 | 25 3 | joe | じょう | 26 | 85 | 76 4 | hon | ほんどう | 23 | 45 | 55 (3 rows) |
idが、1、3、4の場合のレコードが返ってきます。 これは、
select * from ash_table where id = 1 or id = 3 or id = 4; |
と同じ意味になりますが、INを使うことで、SQL文がすっきりと見やすくなります。
例: 文字列でinを使う # select * from ash_table where yomi in ('はしもと','じょう'); id | name | yomi | lv | hp | mp ----+----------+----------+----+----+---- 1 | hasimoto | はしもと | 15 | 49 | 25 3 | joe | じょう | 26 | 85 | 76 (2 rows) |
文字列型の項目に対しても、inを使うことができます。
例: betweenを使う # select * from ash_table where lv between 15 and 25; id | name | yomi | lv | hp | mp ----+----------+----------+----+----+---- 1 | hasimoto | はしもと | 15 | 49 | 25 4 | hon | ほんどう | 23 | 45 | 55 (4 rows) |
lvが15以上25以下のレコードが返ってきます。 select * from ash_table where lv >= 15 and lv <= 25; と同じ意味です。
データが、どのような順番で返ってくるかは基本的には不明です。 特定の順番で並んでいて欲しい場合は、order by を使います。
例: order byを使う # select * from ash_table order by lv; id | name | yomi | lv | hp | mp ----+----------+----------+----+----+---- 2 | yanagi | やなぎ | 12 | 38 | 25 1 | hasimoto | はしもと | 15 | 49 | 25 4 | hon | ほんどう | 23 | 45 | 55 3 | joe | じょう | 26 | 85 | 76 (4 rows) |
lvの順にデータが返ってきます。基本的には昇順(小さい順)になります。
例: order byでdescを使う # select * from ash_table order by lv desc; id | name | yomi | lv | hp | mp ----+----------+----------+----+----+---- 3 | joe | じょう | 26 | 85 | 76 4 | hon | ほんどう | 23 | 45 | 55 1 | hasimoto | はしもと | 15 | 49 | 25 2 | yanagi | やなぎ | 12 | 38 | 25 (4 rows) |
descという言葉をつけると、降順(大きい順)になります。
例: order byで複数項目を指定 # select * from ash_table order by mp, hp; id | name | yomi | lv | hp | mp ----+----------+----------+----+----+---- 2 | yanagi | やなぎ | 12 | 38 | 25 1 | hasimoto | はしもと | 15 | 49 | 25 4 | hon | ほんどう | 23 | 45 | 55 3 | joe | じょう | 26 | 85 | 76 (4 rows) |
mpの昇順ですが、mpが同じもの同士ではhpの昇順になります。
例: order byで複数項目を指定、descも使う # select * from ash_table order by mp desc, hp; id | name | yomi | lv | hp | mp ----+----------+----------+----+----+---- 3 | joe | じょう | 26 | 85 | 76 4 | hon | ほんどう | 23 | 45 | 55 2 | yanagi | やなぎ | 12 | 38 | 25 1 | hasimoto | はしもと | 15 | 49 | 25 (4 rows) |
mpの降順で並べ替え、mpが同じもの同士ではhpの昇順になります。
サブクエリーとは、select文(本体のクエリー)で使う検索条件を、別のselect文(サブクエリー)の検索結果で指定する方法です。 複数回の検索が必要な複雑な問い合わせが、1回の問い合わせで行えるため、高速化などが期待できます。
例: サブクエリーを使う # select * from ash_table where lv > (select lv from ash_table where name = 'hasimoto'); id | name | yomi | lv | hp | mp ----+----------+----------+----+----+---- 3 | joe | じょう | 26 | 85 | 76 4 | hon | ほんどう | 23 | 45 | 55 (2 rows) |
まず、サブクエリーが実行され、それを検索条件にして、最終的なデータを返しています。 これは、以下に書く2つの検索と同様の意味を持ちます。
例: サブクエリーの検索 # select lv from ash_table where name = 'hasimoto'; lv ---- 15 (1 row) 例: 本体クエリーの検索 # select * from ash_table where lv > 15; id | name | yomi | lv | hp | mp ----+----------+----------+----+----+---- 3 | joe | じょう | 26 | 85 | 76 4 | hon | ほんどう | 23 | 45 | 55 (2 rows) |
サブクエリーを使う場合には、サブクエリーと本体のクエリーが別のテーブルを参照していてもかまいません。
サブクエリーには、exists any all などのキーワードがあり、もっと複雑で便利な使い方ができます。
データベースには、 null という値が設定できます。 nullとは、そこにデータが入っていないということで、通常の演算子ではチェックできません。 nullであるかどうかを調べるためには、
where 項目名 is null |
などの、特殊なものを使います。
例: nullの検索 # select * from ash_table where lv is null; id | name | yomi | lv | hp | mp ----+----------+----------+----+----+---- (0 rows) |
このテーブルには、nullは存在しないため、データは返ってきません。
nullは、『データが空である』ということを示すもので、 『0という数値』 『空白(スペース)』 『長さが0の文字列』 『'null'という文字列』 などとは違います。間違えないように注意してください。 (なお、データベースによっては、長さ0の文字列に対応していない場合もあります。)
集合関数、集計関数などと呼ばれるものです。 データそのものではなく、データからの計算結果などを返します。
select 関数 from テーブル名 [where 検索条件]; |
のような形式で用い、
count():行数 sum():合計値 avg():平均値 max():最大値 min():最小値 |
などがあります。 ()内には、項目名を指定しますが、countでは通常*(全項目)を指定します。 検索条件の指定はselectのときと同様です。
例: count # select count(*) from ash_table; count ------- 4 (1 row) |
全レコード数である4を返します。
例: 条件つきcount # select count(*) from ash_table where lv > 15; count ------- 2 (1 row) |
lvが15のレコードは2つしかないので、2を返します。
例: sum # select sum(lv) from ash_table; sum ----- 76 (1 row) |
lvの値の合計値、76を返します。
既に存在するテーブルに対して、データを、登録したり、更新したり、削除したりするときに使用します。 データベースのデータを操作する場合にはこれらが必須になります。
insertは、テーブルにデータを登録する際に使います。 1件ずつデータを登録するinsert ... values 別のテーブルからselectで選んだデータを登録するinsert ... select の2つのパターンがあります。
データを1行登録するために使います。
insert into テーブル名 (項目名1,項目名2,項目名3, ...) values (データ1,データ2,データ3, ...); |
の形式で用います。 文字列はシングルクォートで囲んでください。項目名とデータは、全て指定する必要はありませんが、形式と数は必ず合わせる必要があります。 また、登録された新規レコードにおいて、データが登録されなかった項目にはnullが登録されます。
insert into テーブル名 values (データ1,データ2,データ3, ...); |
のように、項目名を省略することもできます。
例:insert ... values # insert into ash_table (id,name,yomi,lv,hp,mp) values (5,'new','しんじん',1,12,6); INSERT 1 |
登録を確認してみます。
# select * from ash_table; id | name | yomi | lv | hp | mp ----+----------+----------+----+----+---- 1 | hasimoto | はしもと | 15 | 49 | 25 2 | yanagi | やなぎ | 12 | 38 | 25 3 | joe | じょう | 26 | 85 | 76 4 | hon | ほんどう | 23 | 45 | 55 5 | new | しんじん | 1 | 12 | 6 (5 rows) |
新たなレコードが追加されました。
selectで返ってきた行をそのまま登録します。
主に、表をコピーする場合などに使います。
ash_tableと同じ項目を持ったash_table2があるとして、
例:insert ... select # insert into ash_table2 (id,name,yomi,lv,hp,mp) select * from ash_table where id < 3; INSERT 3 |
ash_tableのうちで、idが3以下のレコードだけを、ash_table2に登録します。 selectで返ってくる形式と、項目名で指定する形式が同じでなければなりません。
updateは、既にあるレコードのデータを更新するために使います。
update テーブル名 set 項目名1 = データ1 [, 項目名2 = データ2] ... where 検索条件; |
の形式で用います。
検索条件にマッチするレコードの、項目名で指定される項目を、新しいデータに置きかえます。検索条件の指定はselectのときと同様です。
項目名とデータは複数指定できます。なお、指定しなかった項目については更新されません。当然、文字列はシングルクォートで囲みます。
whereを省略すると、全部のレコードを同じ値で更新することになります。また、whereの条件を間違えると、無関係のデータを更新してしまうことにもなります。
最初に、同じwhere条件でselectを行うなどの安全策をおすすめします。
例:update # update ash_table set lv = 3, hp = 22, mp = 15 where id = 5; UPDATE 1 |
idが5であるレコードのlv、hp、mp のデータを更新しました。 更新を確認してみます。
# select * from ash_table; id | name | yomi | lv | hp | mp ----+----------+----------+----+----+---- 1 | hasimoto | はしもと | 15 | 49 | 25 2 | yanagi | やなぎ | 12 | 38 | 25 3 | joe | じょう | 26 | 85 | 76 4 | hon | ほんどう | 23 | 45 | 55 5 | new | しんじん | 3 | 22 | 15 (5 rows) |
データが更新されています。
updateでは、登録する値の代わりに計算式を書くことができます。
例:update # update ash_table set lv = lv * 2; UPDATE 5 |
lvの値が全て倍になります。
deleteは、テーブルからレコードを削除する場合に使います。
delete from テーブル名 where 検索条件; |
の形式で用います。
検索条件の指定は、selectの場合と同様です。
whereを省略すると、全部のレコードを削除することになります。また、whereの条件を間違えると、無関係のデータを削除してしまうことにもなります。
最初に、同じwhere条件でselectを行うなどの安全策をおすすめします。
例:delete # delete from ash_table where id = 5; DELETE 1 |
idが5であるレコードを削除しました。 削除を確認してみます。
# select * from ash_table; id | name | yomi | lv | hp | mp ----+----------+----------+----+----+---- 1 | hasimoto | はしもと | 15 | 49 | 25 2 | yanagi | やなぎ | 12 | 38 | 25 3 | joe | じょう | 26 | 85 | 76 4 | hon | ほんどう | 23 | 45 | 55 (4 rows) |
削除されました。
その他、覚えておくべき部分としては、テーブルの作成、削除があります。 テーブル設計はDB運用にあたって非常に重要な部分です。いいかげんにしないようにしましょう。
テーブルを作る場合に使います。
create table テーブル名 (項目名1 データ型1 [制約], 項目名2 データ型2, 項目名3 データ型3 ....); |
の形式で用います。 データ型には、整数型、文字列型、浮動小数点数型、日付型などがあり、データベースによって異なっていることも多いです。 制約としては、 not null:nullを認めない unique:異なるレコードに同じ値を認めない などがあります。
例:今回のテーブルを、PostgreSQLで作った場合。 # create table ash_table (id integer, name text, yomi text, lv integer, hp integer, mp integer); CREATE |
テーブルができました。
テーブルを消します。
drop table テーブル名 |
の形式で使います。