2.1。はじめに
この章では、SQLを使用して簡単な操作を実行する方法の概要を説明します。このチュートリアルの目的は、完全なSQLチュートリアルではなく、紹介を提供することだけです。新しいSQLの理解やSQL標準のガイドなど、SQLに関する本はたくさんあります。知っておく必要があるのは、一部のPostgreSQL言語機能は標準の拡張機能であるということです。
次の例では、前の章で説明したようにmydbという名前のデータベースを作成し、psqlを開始したと想定しています。
このマニュアルの例は、PostgreSQLソースコードディストリビューションのsrc / tutorial /ディレクトリにもあります(PostgreSQLのバイナリディストリビューションではこれらのファイルをコンパイルできない場合があります)。これらのファイルを使用するには、最初にディレクトリに入り、次にmakeを実行します。
$ cd ..../src/tutorial
$ make
これにより、スクリプトが作成され、ユーザー定義の関数と型を含むCファイルがコンパイルされます。このチュートリアルを開始するには、次の手順に従います。
$ cd ..../src/tutorial
$ psql -s mydb
...
mydb=> \i basics.sql
\ iコマンドは、指定されたファイルからコマンドを読み取ります。psqlの-sオプションを使用すると、シングルステップモードになり、各ステートメントをサーバーに送信する前に一時停止します。このセクションで使用されるコマンドは、basics.sqlファイルにあります。
2.2。コンセプト
PostgreSQLはリレーショナルデータベース管理システム(RDBMS)です。これは、リレーショナル形式で保存されているデータを管理するためのシステムであることを意味します。関係は、実際にはテーブルの数学用語です。今日、データをテーブルに格納するという概念は本質的な常識になっていますが、データベースを編成する方法は他にもあります。Unixライクなオペレーティングシステム上のファイルとディレクトリは、階層型データベースの例を形成します。より現代的な開発は、オブジェクト指向データベースです。
各テーブルは名前付き行のセットであり、特定のテーブルの各行は、同一の名前付きフィールドのセットで構成されます。また、各フィールドは特定のデータ型です。各行の各フィールドの位置は固定されていますが、SQLはテーブル内の行の順序を保証しないことを覚えておくことが重要です(ただし、表示は明確に並べ替えることができます)。
テーブルはデータベースを形成し、特定のPostgreSQLサーバーによって管理される一連のデータベースはデータベースクラスターを形成します。
2.3。新しいテーブルを作成します
テーブルの名前とすべてのフィールド名およびそれらのタイプを宣言することにより、テーブルを作成できます。
CREATE TABLE weather (
city varchar(80),
temp_lo int, -- low temperature
temp_hi int, -- high temperature
prcp real, -- precipitation
date date
);
これらのコードを改行文字とともにpsqlに入力すると、セミコロンが終了するまでコマンドを認識できます。
SQLコマンドでは、空白(つまり、スペース、タブ、および改行)を自由に使用できます。これは、上記とは異なる配置でコマンドを入力でき、すべてのコードを1行で記述できることを意味します。2つのダッシュ( "-")はコメントを紹介します。行末まで続くものはすべて無視されます。SQLは、キーワードと識別子の大文字と小文字を区別しません。ただし、識別子が大文字と小文字の属性を保持するために二重引用符で囲まれている場合を除きます(上記の場合は除く)。
varchar(80)は、最大80文字の任意の文字列を格納できるデータ型を宣言します。intは通常の整数型です。realは、単精度浮動小数点数を格納するために使用される型です。日付の種類は一目瞭然です。(はい、日付型のフィールド名も日付です。これは、より便利な場合もあれば、混乱する場合もあります。自分で確認してください。)
PostgresSQLは、標準のSQL型int、smallint、real、倍精度、char(N)、varchar(N)、date、time、timestamp、interval、およびその他の一般的な型と豊富な幾何型をサポートしています。PostgreSQLは、ユーザー定義のデータ型をいくつでもカスタマイズできます。したがって、SQL標準で要求される特別な場合を除いて、型名は文法的なキーワードではありません。
2番目の例では、都市の名前とそれに関連する地理的位置を保存します。
CREATE TABLE cities (
name varchar(80),
location point
);
ポイントデータ型は、PostgreSQLに固有のデータ型の例です。
最後に、テーブルが不要になった場合、または別のテーブルを作成する場合は、次のコマンドを使用してテーブルを削除できることにも言及します。
DROP TABLE tablename;
2.4。テーブルに行を追加します
次のINSERTコマンドは、テーブルに行を追加するために使用されます。
INSERT INTO weather VALUES ('San Francisco', 46, 50, 0.25, '1994-11-27');
すべてのデータ型がかなり明確な入力形式を使用していることに注意してください。単純な数値ではない定数は、例のように一重引用符( ')で囲む必要があります。日付型は実際には許容可能な形式に非常に柔軟ですが、このチュートリアルでは、ここでは明確な表示形式に固執します。
ポイントタイプには、次のように、入力として座標ペアが必要です。
INSERT INTO cities VALUES ('San Francisco', '(-194.0, 53.0)');
これまでに使用された構文では、フィールドの順序を覚えておく必要があります。オプションの構文を使用すると、フィールドを明示的にリストできます。
INSERT INTO weather (city, temp_lo, temp_hi, prcp, date)
VALUES ('San Francisco', 43, 57, 0.0, '1994-11-29');
必要に応じて、フィールドを別の順序で一覧表示するか、一部のフィールドを無視することができます。たとえば、降水量はわかりません。
INSERT INTO weather (date, city, temp_hi, temp_lo)
VALUES ('1994-11-29', 'Hayward', 54, 37);
多くの開発者は、暗黙の順序に依存するよりも、フィールドを明示的にリストする方がよいと考えています。
次のセクションでデータを利用できるように、上記のすべてのコマンドを入力してください。
COPYコマンドを使用して、テキストファイルから大量のデータをロードすることもできます。COPYコマンドはこのタイプのアプリケーション用に最適化されているため、これは通常は高速ですが、INSERTよりも柔軟性がありません。といった:
COPY weather FROM '/home/user/weather.txt';
ここで、ソースファイルのファイル名は、クライアントではなくバックエンドサーバーからアクセスできる必要があります。これは、バックエンドサーバーがファイルを直接読み取るためです。COPYコマンドの詳細については、COPYセクションを参照してください。
2.5。テーブルをクエリする
テーブルからデータを取得することは、実際にはこのテーブルをクエリしています。この目的のために、SQLSELECTコマンドが使用されます。ステートメントは、選択リスト(返されるフィールドをリストする部分)、テーブルリスト(データが取得されるテーブルをリストする部分)、およびオプションの条件(制限を宣言する部分)に分けられます。たとえば、天気表のすべての行を取得するには、次のように入力します。
SELECT * FROM weather;[1]
ここで、*は「allcolumns」の省略形です。次のクエリでも同じ結果が得られます。
SELECT city, temp_lo, temp_hi, prcp, date FROM weather;
そして、出力は次のようになります。
city | temp_lo | temp_hi | prcp | date
---------------+---------+---------+------+------------
San Francisco | 46 | 50 | 0.25 | 1994-11-27
San Francisco | 43 | 57 | 0 | 1994-11-29
Hayward | 37 | 54 | | 1994-11-29
(3 rows)
列参照だけでなく、選択リストに任意の式を記述できます。たとえば、次のことができます。
SELECT city, (temp_hi+temp_lo)/2 AS temp_avg, date FROM weather;
これは次のようになります。
city | temp_avg | date
---------------+----------+------------
San Francisco | 48 | 1994-11-27
San Francisco | 50 | 1994-11-29
Hayward | 45 | 1994-11-29
(3 rows)
ここでのAS句が出力列の名前を変更する方法に注意してください。(AS句はオプションです。)
WHERE句を使用してクエリを「変更」し、行が必要な場所を宣言できます。WHERE句にはブール(真理値)式が含まれており、ブール式の値がtrueである行のみが返されます。一般的に使用されるブール演算子(AND、OR、およびNOT)は、条件で許可されます。たとえば、次のクエリは、雨の日のサンフランシスコの天気を取得します。
SELECT * FROM weather
WHERE city = 'San Francisco' AND prcp > 0.0;
結果:
city | temp_lo | temp_hi | prcp | date
---------------+---------+---------+------+------------
San Francisco | 46 | 50 | 0.25 | 1994-11-27
(1 row)
返されたクエリを並べ替えることを要求できます。
SELECT * FROM weather
ORDER BY city;
city | temp_lo | temp_hi | prcp | date
---------------+---------+---------+------+------------
Hayward | 37 | 54 | | 1994-11-29
San Francisco | 43 | 57 | 0 | 1994-11-29
San Francisco | 46 | 50 | 0.25 | 1994-11-27
この例では、並べ替えの順序が完全に明確ではないため、サンフランシスコの行データがランダムに並べ替えられている場合があります。ただし、次のステートメントを使用すると、常に上記の結果が得られます
SELECT * FROM weather
ORDER BY city, temp_lo;
次のコマンドを使用して、クエリ結果の重複行を削除できます。
SELECT DISTINCT city
FROM weather;
city
---------------
Hayward
San Francisco
(2 rows)
ここでも、結果行の順序を変更できます。DISTINCTとORDERBYを組み合わせて、一貫した結果を得ることができます。[2]
SELECT DISTINCT city
FROM weather
ORDER BY city;
[1] SELECT *は一時的なクエリに役立ちますが、テーブルにフィールドを追加すると結果が変わるため、これは本番コードでは悪いスタイルであると一般的に考えられています。
[2]古いバージョンのPostgreSQLを含む一部のデータベースシステムでは、DISTINCTを実行すると行が並べ替えられるため、ORDERBYは冗長です。ただし、これはSQL標準の要件ではなく、現在のPostgreSQLは、DISTINCTによってデータ行がソートされることを保証していません。
2.6。テーブル間の接続
これまでのところ、クエリは一度に1つのテーブルにしかアクセスしていません。クエリは、一度に複数のテーブルにアクセスすることも、テーブル内のデータの複数の行を処理しながら何らかの方法でテーブルにアクセスすることもできます。結合クエリとして、同じテーブルまたは異なるテーブルの複数のデータ行に同時にアクセスするクエリを呼び出します。たとえば、すべての気象レコードと、これらのレコードに関連する都市の座標を一覧表示する場合です。この目標を達成するには、天気表の各行の都市フィールドを都市テーブルのすべての行の名前フィールドと比較し、これらの値に一致する行を選択する必要があります。
注;これは単なる概念モデルです。この接続は通常、可能な各行ペアを実際に比較するよりも効率的な方法で実行されますが、これらはユーザーには見えません。
このタスクは、次のクエリで実行できます。
SELECT *
FROM weather, cities
WHERE city = name;
city | temp_lo | temp_hi | prcp | date | name | location
---------------+---------+---------+------+------------+---------------+-----------
San Francisco | 46 | 50 | 0.25 | 1994-11-27 | San Francisco | (-194,53)
San Francisco | 43 | 57 | 0 | 1994-11-29 | San Francisco | (-194,53)
(2 rows)
結果セットの2つの側面を観察します。
ヘイワード市の結果行はありません。これは、citysテーブルにHaywardの一致する行がないため、接続が天気表の一致しない行を無視するためです。この問題を修正する方法については後で説明します。
2つのフィールドには都市名が含まれています。天気と都市のテーブルのフィールドが結合されているため、これは正しいです。ただし、実際にはこれらは必要ないため、*:を使用する代わりに、出力フィールドを明示的にリストすることをお勧めします。
演習:WHERE句を省略するセマンティクスを確認してください。
各フィールドの名前は異なるため、アナライザーはそれらが属するテーブルを自動的に検出します。2つのテーブルに重複するフィールド名がある場合は、修飾されたフィールド名を使用して、どちらが必要かを示す必要があります。クエリは次のとおりです。 :
SELECT weather.city, weather.temp_lo, weather.temp_hi,
weather.prcp, weather.date, cities.location
FROM weather, cities
WHERE cities.name = weather.city;
結合クエリのすべてのフィールド名を制限することは、後でテーブルの1つに重複する列名が追加されても、クエリが失敗しないようにするための優れたスタイルと広く見なされています。
これまでのところ、このタイプの結合クエリは次の形式でも記述できます。
SELECT *
FROM weather INNER JOIN cities ON (weather.city = cities.name);
この文法は上記の文法ほど一般的には使用されていません。次のトピックを理解しやすくするために、ここに記述します。
次に、Haywardレコードを取得する方法を説明します。クエリで実行するのは、天気テーブルをスキャンして、各行の都市テーブルで一致する行を見つけることです。一致する行が見つからない場合は、citysテーブルのフィールドを置き換えるためにいくつかの「空の値」が必要です。このタイプのクエリは、外部結合と呼ばれます。(これまでに見た接続はすべて内部接続です。)このようなコマンドは次のようになります。
SELECT *
FROM weather LEFT OUTER JOIN cities ON (weather.city = cities.name);
city | temp_lo | temp_hi | prcp | date | name | location
---------------+---------+---------+------+------------+---------------+-----------
Hayward | 37 | 54 | | 1994-11-29 | |
San Francisco | 46 | 50 | 0.25 | 1994-11-27 | San Francisco | (-194,53)
San Francisco | 43 | 57 | 0 | 1994-11-29 | San Francisco | (-194,53)
(3 rows)
結合演算子の左側のテーブルの行は出力に少なくとも1回表示される必要があり、右側の行は左側の行に対応する行のみを出力するため、このクエリは左側の外部結合です。一致する行。左側のテーブルの出力行が一致する右側のテーブルの行に対応していない場合、右側の行のフィールドはNULLで埋められます。
練習;正しい接続と完全な接続があります。彼らが何をしているのか調べてみてください。
テーブルを自分自身に接続することもできます。これは自己接続と呼ばれます。たとえば、他の気象記録の温度範囲内にある気象記録を検索するとします。このようにして、天気テーブルの各行のtemp_loフィールドとtemp_hiフィールドを、天気テーブルの他の行のtemp_loフィールドとtemp_hiフィールドと比較する必要があります。次のクエリでこの目標を達成できます。
SELECT W1.city, W1.temp_lo AS low, W1.temp_hi AS high,
W2.city, W2.temp_lo AS low, W2.temp_hi AS high
FROM weather W1, weather W2
WHERE W1.temp_lo < W2.temp_lo
AND W1.temp_hi > W2.temp_hi;
city | low | high | city | low | high
---------------+-----+------+---------------+-----+------
San Francisco | 43 | 57 | San Francisco | 46 | 50
Hayward | 37 | 54 | San Francisco | 46 | 50
(2 rows)
ここでは、接続の左側と右側を区別するために、気象テーブルのラベルをW1とW2に変更します。このようなエイリアスを使用して、次のような他のクエリでいくつかのキーストロークを保存することもできます。
SELECT *
FROM weather w, cities c
WHERE w.city = c.name;
将来、そのような略語に出くわすことがよくあります。
2.7。集計関数
他のほとんどのリレーショナルデータベース製品と同様に、PostgreSQLは集計関数をサポートしています。集計関数は、複数の入力行から結果を計算します。たとえば、一連の行のカウント(数)、合計(合計)、平均(平均)、最大(最大)、および最小(最小)を計算する集計関数があります。
たとえば、次のステートメントを使用して、すべてのレコードの最高気温を見つけることができます。
SELECT max(temp_lo) FROM weather;
max
-----
46
(1 row)
どの都市で読書が行われたかを知りたい場合は、
天気から都市を選択WHEREtemp_lo = max(temp_lo); 違う
ただし、WHERE句で集計関数maxを使用できないため、このクエリは実行できません。(この制限が存在するのは、WHERE句によって集計フェーズに入ることができる行が決定されるため、集計関数を実行する前に計算する必要があります。)ただし、通常は他の方法を使用して目的を達成できます。ここではサブクエリを使用できます。
SELECT city FROM weather
WHERE temp_lo = (SELECT max(temp_lo) FROM weather);
city
---------------
San Francisco
(1 row)
サブクエリは独立した計算であり、外部クエリとは独立して独自の集計を計算するため、これは問題ありません。
集約は、GROUPBY句でも一般的に使用されます。たとえば、各都市で最高の低温値を取得できます。
SELECT city, max(temp_lo)
FROM weather
GROUP BY city;
city | max
---------------+-----
Hayward | 37
San Francisco | 46
(2 rows)
これにより、各都市の出力が得られます。各集計結果は、都市に一致する行で計算されます。これらのグループは、HAVINGでフィルタリングできます。
SELECT city, max(temp_lo)
FROM weather
GROUP BY city
HAVING max(temp_lo) < 40;
city | max
---------+-----
Hayward | 37
(1 row)
これにより、temp_lo値の温度が40度未満であった都市のみが表示されます。最後に、名前が「S」で始まる都市のみを気にする場合は、次を使用できます。
SELECT city, max(temp_lo)
FROM weather
WHERE city LIKE 'S%'(1)
GROUP BY city
HAVING max(temp_lo) < 40;
(1)セクション9.7で説明されているように、LIKEはパターンマッチングを実行します。
集計とSQLWHEREおよびHAVING句の関係を理解することは非常に重要です。WHEREとHAVINGの基本的な違いは次のとおりです。WHEREはグループ化と集計の計算の前に入力行を選択し(したがって、どの行が集計計算に入るのかを制御します)、HAVINGはグループ化と集計の後にグループ化された行を選択します。したがって、WHERE句に集計関数を含めることはできません。集計関数を使用して、集計操作に入力される行を判別しようとしても意味がありません。対照的に、HAVING句には常に集計関数が含まれます。(厳密に言えば、集約を使用しないHAVING句を記述できますが、これが役立つことはめったにありません。同じ条件をWHEREフェーズでより効果的に使用できます。)
前の例では、集約を必要としないため、WHEREで都市名の制限を適用できます。これは、WHEREチェックに失敗した行のグループ化と集計の計算を回避するため、HAVINGの制限を増やすよりも効率的です。
2.8。更新
UPDATEコマンドを使用して、既存の行を更新できます。11月28日のすべての温度カウントが2度低いことがわかった場合、次の方法でデータを更新できます。
UPDATE weather
SET temp_hi = temp_hi - 2, temp_lo = temp_lo - 2
WHERE date > '1994-11-28';
データの新しい状態を見てください。
SELECT * FROM weather;
city | temp_lo | temp_hi | prcp | date
---------------+---------+---------+------+------------
San Francisco | 46 | 50 | 0.25 | 1994-11-27
San Francisco | 41 | 55 | 0 | 1994-11-29
Hayward | 35 | 52 | | 1994-11-29
(3 rows)
2.9。削除
データ行は、DELETEコマンドを使用してテーブルから削除できます。Haywardの天気に関心がなくなった場合は、次の方法でこれらの行をテーブルから削除できます。
DELETE FROM weather WHERE city = 'Hayward';所有属于Hayward的天气记录都将被删除。
SELECT * FROM weather;
city | temp_lo | temp_hi | prcp | date
---------------+---------+---------+------+------------
San Francisco | 46 | 50 | 0.25 | 1994-11-27
San Francisco | 41 | 55 | 0 | 1994-11-29
(2 rows)
次の形式のステートメントを使用する場合は注意が必要です
DELETE FROM tablename;
条件がない場合、DELETEは指定されたテーブルからすべての行を削除してクリアします。これを行う前に、システムは確認を求めません!