PostgreSQL入門:データベースの基礎と使い始め方


PostgreSQL入門:データベースの基礎と使い始め方

はじめに:データベースの世界へようこそ

現代のITシステムにおいて、データベースは情報の心臓部と言えます。Webアプリケーション、モバイルアプリ、業務システム、データ分析など、ありとあらゆる場所でデータは収集され、蓄積され、活用されています。データを効率的かつ安全に管理するために、データベースシステム(Database Management System, DBMS)は不可欠な存在です。

数あるデータベースシステムの中でも、PostgreSQLは特にその堅牢性、機能の豊富さ、標準への準拠性の高さから、世界中の多くの開発者や企業に利用されています。オープンソースでありながら商用データベースに匹敵する、あるいはそれ以上の機能を持つと評されることも少なくありません。

この記事は、データベースの基本的な概念から学び始め、PostgreSQLのインストール、基本的な操作、そしてデータ操作のためのSQL(Structured Query Language)の基礎までを、約5000語というボリュームで詳細に解説する入門記事です。これからデータベースを学びたい方、特にPostgreSQLを使ってみたいと考えている方を対象としています。

読み進めるにつれて、あなたは以下のことを理解できるようになるでしょう。

  • データベースとDBMSの違い、リレーショナルデータベースの基本的な考え方
  • なぜPostgreSQLが選ばれるのか、その特徴とメリット
  • 自分のコンピュータにPostgreSQLをインストールする方法
  • psqlコマンドラインツールを使った基本的なPostgreSQLの操作(データベース作成、接続など)
  • SQLを使ってテーブルを作成し、データを登録・参照・更新・削除する方法
  • データの一貫性や整合性を保つための「制約」の概念
  • データの効率的な検索に役立つ「インデックス」や「ビュー」の基本的な考え方
  • 複数のテーブルから関連するデータを取得する「JOIN」の基本的な方法
  • データベース操作における「トランザクション」の重要性

さあ、PostgreSQLの世界へ、そしてデータベースの世界へ、一緒に深く潜っていきましょう。

第1章:データベースの基礎知識

PostgreSQLを使い始める前に、まずはデータベースに関する基本的な用語と概念を理解しておくことが重要です。

1.1 データベースとは?

「データベース」という言葉は、文脈によって少し意味合いが変わることがあります。広義には「構造化されたデータの集まり」を指します。例えば、本棚に整理された本のリスト、Excelで作成された顧客一覧なども「データベース」と呼べます。

しかし、ITの文脈で単に「データベース」と言った場合、多くは後述するDBMSによって管理されるデータを指します。この場合、データベースは単なるデータの集まりではなく、特定の構造(テーブル、リレーションなど)を持ち、整合性が保たれた状態であることが期待されます。

1.2 データベース管理システム (DBMS) とは?

データベース管理システム(Database Management System, DBMS)は、データベースを構築、管理、利用するためのソフトウェアです。DBMSの主な役割は以下の通りです。

  • データの定義: どのような構造でデータを格納するか(テーブル、列、データ型など)を定義します。
  • データの操作: データの追加 (Insert)、参照 (Select)、更新 (Update)、削除 (Delete) を行います。これらの操作はSQLという言語を使って行われるのが一般的です。
  • データの制御: データの整合性(矛盾がないこと)、セキュリティ(アクセス権限)、可用性(いつでも利用できること)、信頼性(障害発生時の復旧)などを管理します。

DBMSを使うことで、複数のユーザーやアプリケーションが同時にデータに安全にアクセスできるようになり、データの重複や矛盾を防ぎ、大規模なデータも効率的に扱えるようになります。

PostgreSQLは、このDBMSの一つです。他にもOracle Database, MySQL, SQL Server, SQLiteなどが代表的なDBMSです。

1.3 リレーショナルデータベース (RDB) とは?

リレーショナルデータベース(Relational Database)は、現在最も広く使われているデータベースの形式です。データを「リレーション」(関連)という数学的な概念に基づいて管理します。リレーションは、コンピュータの世界では「テーブル」として表現されます。

RDBでは、データは行と列からなる二次元の表形式で格納されます。

  • テーブル (Table): 特定の種類のデータをまとめたものです。例えば、「顧客リスト」「商品リスト」「注文リスト」などがそれぞれ一つのテーブルになります。
  • 行 (Row) / レコード (Record): テーブルにおける一つのデータ単位です。顧客リストなら顧客一人分の情報、商品リストなら商品一つ分の情報が行にあたります。
  • 列 (Column) / フィールド (Field) / 属性 (Attribute): テーブルにおけるデータの種類です。顧客リストなら「顧客ID」「氏名」「住所」「電話番号」などが列にあたります。

リレーショナルデータベースの特徴は、複数のテーブルを「関連」(リレーション)によって結びつけることができる点です。例えば、「注文テーブル」と「顧客テーブル」は、「顧客ID」という共通の列を持つことで関連付けることができます。これにより、「どの顧客が」「何を注文したか」といった複雑な情報を、構造的に、かつ重複なく管理することが可能になります。

PostgreSQLは、このリレーショナルデータベースの代表的なDBMSの一つです。厳密には、リレーショナルデータベースに加えて、オブジェクト指向的な要素も取り入れた「オブジェクト・リレーショナルデータベース」に分類されますが、基本的な使い方は一般的なRDBと同様です。

1.4 SQLとは?

SQL(Structured Query Language、構造化クエリ言語)は、リレーショナルデータベースの操作や定義を行うための標準的な言語です。多くのRDBMはSQLをサポートしており、ユーザーはSQL文をDBMSに発行することで、データの操作やデータベースの構造変更を行います。

SQLは、主に以下の4種類の操作に分類されます。

  • DDL (Data Definition Language): データベースの構造を定義・変更・削除するための言語です。
    • CREATE TABLE: 新しいテーブルを作成する
    • ALTER TABLE: 既存のテーブル構造を変更する
    • DROP TABLE: テーブルを削除する
    • CREATE DATABASE: データベースを作成する
    • DROP DATABASE: データベースを削除する
    • その他、インデックスやビューなどのオブジェクト作成・変更・削除にも使われます。
  • DML (Data Manipulation Language): データベース内のデータを操作するための言語です。
    • INSERT INTO: 新しいデータをテーブルに追加する
    • SELECT: テーブルからデータを検索(取得)する
    • UPDATE: 既存のデータを更新する
    • DELETE FROM: データを削除する
  • DCL (Data Control Language): データベースへのアクセス権限などを制御するための言語です。
    • GRANT: ユーザーに権限を与える
    • REVOKE: ユーザーから権限を剥奪する
  • TCL (Transaction Control Language): トランザクション(一連のデータベース操作のまとまり)を制御するための言語です。
    • BEGIN: トランザクションを開始する
    • COMMIT: トランザクションを確定する(変更を永続化する)
    • ROLLBACK: トランザクションを取り消す(変更を元に戻す)

この記事の後半では、DMLとDDLを中心に、PostgreSQLでSQLを使う方法を詳しく見ていきます。SQLは非常に強力で汎用性の高い言語であり、一度基本的な構文を習得すれば、他のRDBMSでも応用が効きます。

第2章:PostgreSQLとは?

PostgreSQLは、冒頭でも触れたように、非常に人気のある高機能なオブジェクト・リレーショナルデータベースシステムです。その特徴、利点、歴史、そして他のデータベースとの比較について見ていきましょう。

2.1 PostgreSQLの歴史と特徴

PostgreSQLは、カリフォルニア大学バークレー校で開発されていたINGRESプロジェクトの後継として、1986年に開発が始まりました。「Post-INGRES」という意味で「Postgres」と呼ばれ、1996年にSQLへの対応が強化された際に、PostgreSQLと改名されました。以来、世界中の活発なコミュニティによって開発・保守が続けられています。

PostgreSQLの主な特徴は以下の通りです。

  • オープンソースであること: PostgreSQLはBSDライセンスの下で公開されており、誰でも無償で利用、配布、改変することができます。商用データベースのようなライセンス費用がかからないため、コストを抑えたいプロジェクトや企業にとって大きなメリットとなります。
  • 標準SQLへの高い準拠性: PostgreSQLは、SQLの国際標準(SQL:2011など)に非常に高いレベルで準拠しています。これは、他のRDBMSからの移行や、将来的なシステムの柔軟性を高める上で重要です。
  • 堅牢性と信頼性: WAL (Write-Ahead Logging) と呼ばれる仕組みにより、クラッシュや障害発生時でもデータの損失を最小限に抑え、整合性を保つことができます。トランザクション処理も強力で、ACID特性(原子性、一貫性、独立性、永続性)を保証します。
  • 機能の豊富さ: 基本的なRDB機能に加え、以下のような多くの高度な機能を提供します。
    • 複雑なデータ型(配列、JSON/JSONB、XML、ジオメトリデータなど)
    • 関数、ストアドプロシージャ、トリガー
    • ビュー、マテリアライズドビュー
    • インデックスの種類が豊富(B-tree, Hash, GiST, SP-GiST, GIN, BRINなど)
    • 外部データラッパー (Foreign Data Wrappers, FDW) による外部データソースへのアクセス
    • フルテキスト検索機能
    • パーティショニング
    • 論理レプリケーション
    • など、挙げきれないほどの機能があります。
  • 拡張性の高さ: ユーザー定義関数、カスタムデータ型、アドオンモジュールなどにより、機能を拡張することが容易です。多くの便利な拡張機能がコミュニティから提供されています(例えば、PostGISは地理空間データ処理のための有名な拡張機能です)。
  • 活発なコミュニティ: 世界中に開発者とユーザーがおり、フォーラムやメーリングリストで情報交換が行われ、問題解決や機能改善が活発に行われています。

これらの特徴により、PostgreSQLはWebサービス、エンタープライズシステム、科学技術計算、地理情報システムなど、様々な分野で利用されています。

2.2 他の主要なデータベースとの比較

PostgreSQLとよく比較される他の主要なDBMSと比較してみましょう。

  • MySQL:
    • PostgreSQLと同様に広く普及しているオープンソースRDBMSです。
    • MySQLは、Webアプリケーションのバックエンドとして非常に人気があり、LAMPスタック(Linux, Apache, MySQL, PHP/Python/Perl)の一部として広く使われています。
    • 一般的に、MySQLはPostgreSQLと比較して、セットアップが容易で、シンプルで高速な読み込み操作が得意とされます。
    • しかし、PostgreSQLの方が、より複雑なクエリ処理、標準SQLへの準拠性、高度な機能(豊富なデータ型、強力なトランザクション、様々なインデックスタイプ、拡張機能など)においては優れていると言われることが多いです。特に、金融系や学術研究など、データの厳密な管理や複雑な分析が求められる分野ではPostgreSQLが選ばれる傾向があります。
    • 近年、MySQLも機能が向上しており、差は縮まりつつありますが、設計思想や得意な領域には違いがあります。
  • SQLite:
    • PostgreSQLやMySQLとは異なり、サーバープロセスを持たない組み込み型データベースです。データベース全体が単一のファイルとして保存されます。
    • セットアップが不要で、手軽に使えるのが最大の利点です。モバイルアプリやデスクトップアプリのローカルデータ保存、小規模なウェブサイトなどに適しています。
    • SQLiteは軽量でシンプルですが、同時アクセス性能や機能の豊富さ、スケーラビリティにおいてはPostgreSQLに及びません。大規模な複数ユーザーからのアクセスや、複雑な機能が必要な場合にはPostgreSQLなどのクライアント・サーバー型DBMSが適しています。
  • Oracle Database / SQL Server:
    • これらは代表的な商用RDBMSです。長い歴史を持ち、エンタープライズ向けの豊富な機能とサポートが提供されています。
    • 機能面ではPostgreSQLと競合する部分も多いですが、商用ライセンス費用が高額になることが大きな違いです。
    • PostgreSQLは、多くのエンタープライズ機能(レプリケーション、パーティショニング、高度なセキュリティなど)をオープンソースで提供しており、商用データベースからの移行先としても注目されています。

このように、それぞれに得意な領域や特徴があります。PostgreSQLは、オープンソースの柔軟性とコストメリットを持ちながら、エンタープライズレベルの機能と信頼性を求める場合に非常に魅力的な選択肢となります。

第3章:PostgreSQLのインストール

PostgreSQLを使うためには、まず自分のコンピュータにPostgreSQLサーバーをインストールする必要があります。インストール方法はOSによって異なりますが、ここでは一般的な手順と注意点を紹介します。

3.1 インストール前の準備

  • システムの要件確認: PostgreSQLのバージョンによって推奨されるOSやハードウェアの要件が異なります。利用したいバージョンの公式ドキュメントで確認しましょう。
  • 管理者権限: インストールには通常、システムの管理者権限が必要です。
  • 既存のPostgreSQLの有無: 既にPostgreSQLがインストールされていないか確認してください。もしインストールされている場合は、バージョンアップや複数バージョン共存のポリシーを検討します。

3.2 各OSでのインストール方法

PostgreSQLのインストール方法はいくつかあります。最も一般的な方法を紹介します。

Windows

Windowsでは、公式ウェブサイト(https://www.postgresql.org/download/windows/)から提供されている「EDB Interactive installer」を利用するのが最も簡単です。

  1. 公式ダウンロードページから、利用したいバージョンのインストーラー(.exeファイル)をダウンロードします。
  2. ダウンロードしたファイルを実行します。
  3. インストーラーの指示に従ってインストールを進めます。
    • インストールするコンポーネント(PostgreSQL Server, pgAdmin 4, Stack Builder, Command Line Toolsなど)を選択します。通常は全て選択して問題ありません。
    • データの保存場所(Data Directory)を指定します。
    • データベースに接続するためのスーパーユーザー(デフォルトではpostgres)のパスワードを設定します。このパスワードは非常に重要なので忘れないようにメモしておきましょう。
    • ポート番号(デフォルトは5432)やロケール(文字コードや日付/時刻の形式)を設定します。特別な理由がなければデフォルトのままで構いません。
  4. インストールが完了したら、PostgreSQLサーバーが起動していることを確認します。インストーラーによっては、インストール完了後にサービスとして自動起動する設定になっています。
macOS

macOSでは、Homebrewというパッケージマネージャーを利用するのが最も手軽です。

  1. Homebrewがインストールされていない場合は、先にインストールします(https://brew.sh/)。ターミナルを開き、以下のコマンドを実行します。
    bash
    /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
  2. Homebrewを使ってPostgreSQLをインストールします。
    bash
    brew install postgresql
  3. インストールが完了したら、サービスとしてPostgreSQLを起動します。
    bash
    brew services start postgresql
  4. 必要であれば、初回セットアップを行います(バージョンによっては不要な場合もあります)。詳細はHomebrewのインストール時のメッセージやPostgreSQLのドキュメントを参照してください。

その他、公式ウェブサイトから提供されているmacOS用のインストーラー(EDB installer for macOS)や、Postgres.app (https://postgresapp.com/) のようにGUIで簡単に起動・停止できるアプリもあります。

Linux

Linuxディストリビューションの場合、各ディストリビューションのパッケージマネージャー(apt, yum, dnfなど)を利用するのが最も一般的かつ推奨される方法です。これにより、システムの他のソフトウェアとの依存関係が適切に管理されます。

  • Debian / Ubuntu 系: aptコマンドを使います。
    bash
    sudo apt update
    sudo apt install postgresql postgresql-contrib

    postgresql-contribパッケージには、便利な拡張機能などが含まれています。インストール後、PostgreSQLサービスは自動的に起動する設定になっていることが多いです。
  • RHEL / CentOS / Fedora 系: yum または dnf コマンドを使います。
    bash
    # CentOS/RHEL 7まで
    sudo yum install postgresql-server postgresql-contrib
    sudo postgresql-setup initdb # 初回データベースクラスターの初期化
    sudo systemctl enable postgresql # 自動起動設定
    sudo systemctl start postgresql # サービス起動
    # Fedora/CentOS 8以降/RHEL 8以降
    sudo dnf install postgresql-server postgresql-contrib
    sudo postgresql-setup --initdb # 初回データベースクラスターの初期化
    sudo systemctl enable postgresql # 自動起動設定
    sudo systemctl start postgresql # サービス起動

パッケージマネージャーでインストールした場合、postgresという名前のデータベーススーパーユーザーが作成されます。デフォルトでは、このユーザーはOS上のpostgresユーザーとしてログインした場合にのみパスワードなしで接続できるようになっています。外部からの接続や、別のOSユーザーからの接続を許可するには、設定ファイル(pg_hba.conf)の編集や、postgresユーザーのパスワード設定が必要になります(これらは少し高度な内容なので、ここでは割愛します)。

3.3 インストール後の確認と初期設定(psqlへの接続)

インストールが完了したら、PostgreSQLが正しく動作しているか、そしてデータベースに接続できるかを確認しましょう。最も基本的な方法は、PostgreSQLのコマンドラインツールであるpsqlを使うことです。

psqlは、PostgreSQLサーバーに接続し、SQLコマンドを実行するための対話型ターミナルプログラムです。

Windows:
スタートメニューから「SQL Shell (psql)」を探して起動します。いくつか設定(サーバー名、データベース名、ポート、ユーザー名)を聞かれます。
* Server: localhost または 127.0.0.1 (デフォルト)
* Database: postgres (デフォルトのデータベース)
* Port: 5432 (デフォルト)
* Username: postgres (デフォルトのスーパーユーザー)
設定したスーパーユーザーのパスワードを入力すると、postgres=# または ユーザー名=# のようなプロンプトが表示され、接続成功です。

macOS / Linux:
ターミナルを開き、以下のコマンドを実行します。
bash
psql -U postgres

-U postgresはユーザー名をpostgresとして接続するというオプションです。パスワードを聞かれたら、インストール時に設定したpostgresユーザーのパスワードを入力します。
パスワードが正しければ、postgres=# または ユーザー名=# のようなプロンプトが表示され、接続成功です。

psqlプロンプトが表示されたら、以下のコマンドを実行して、サーバーのバージョン情報を確認してみましょう。

sql
SELECT version();

または、psqlのメタコマンド(\で始まるコマンド)を使います。

\conninfo
接続情報が表示されます。

\q
psqlを終了します。

もし接続できない場合、以下の点を確認してください。
* PostgreSQLサーバーが起動しているか? (Windowsサービス、Homebrew services, systemctlなどで確認)
* ユーザー名、データベース名、ポート番号は正しいか?
* パスワードは正しいか?
* Linuxなどで、OSユーザーとデータベースユーザーのマッピングが適切か? (pg_hba.confの設定など)

無事psqlに接続できれば、PostgreSQLのインストールは成功です!

第4章:PostgreSQLの基本的な使い方(psqlコマンド)

ここでは、psqlコマンドを使って、データベースの作成や接続といった基本的な操作方法を見ていきます。

4.1 データベースの作成と削除

PostgreSQLをインストールした直後には、postgresなどのデフォルトデータベースがいくつか存在しますが、通常は用途別に新しいデータベースを作成して使います。

データベースを作成するには、psqlに接続した状態でSQLのCREATE DATABASE文を実行するか、createdbという専用のコマンドラインツールを使います。

createdbコマンドを使う方法:
ターミナルを開き、以下のコマンドを実行します。

bash
createdb mydatabase -U postgres

mydatabaseは作成したいデータベース名です。-U postgresは、スーパーユーザーであるpostgresユーザーとして作成するというオプションです。パスワードを求められたら入力します。

SQL文を使う方法(psql接続後):
psqlpostgresユーザーとして接続します。
bash
psql -U postgres

psqlプロンプト(postgres=#)が表示されたら、以下のSQL文を実行します。

sql
CREATE DATABASE mydatabase;

最後にセミコロン;をつけるのを忘れないでください。SQL文はセミコロンで終わるのが基本です。

データベースが作成されたことを確認するには、psql接続中に以下のメタコマンドを使います。

\l
または

\list
サーバー上の全てのデータベースがリスト表示されます。作成したmydatabaseが表示されていれば成功です。

データベースを削除するには、dropdbコマンドまたはSQLのDROP DATABASE文を使います。注意:データベースを削除すると、中に含まれる全てのデータも失われます。実行には十分注意してください。

dropdbコマンドを使う方法:
ターミナルを開き、以下のコマンドを実行します。

bash
dropdb mydatabase -U postgres

SQL文を使う方法(psql接続後):
psqlに接続し、削除したいデータベース以外のデータベースに接続した状態で以下のSQL文を実行します。例えば、postgresデータベースに接続します。

bash
psql -U postgres

psqlプロンプト(postgres=#)が表示されたら、以下のSQL文を実行します。

sql
DROP DATABASE mydatabase;

4.2 ユーザーの作成と削除

PostgreSQLでは、データベースへのアクセスを制御するためにユーザー(またはロール)を作成します。ユーザーごとに、特定のデータベースやテーブルに対するアクセス権限を付与することができます。

新しいユーザーを作成するには、createuserコマンドまたはSQLのCREATE USER文を使います。

createuserコマンドを使う方法:
ターミナルを開き、スーパーユーザー(例: postgres)として以下のコマンドを実行します。

bash
createuser myuser -P -U postgres

myuserは作成したいユーザー名です。-Pオプションをつけると、ユーザーのパスワード設定を促されます。パスワードを2回入力します。

SQL文を使う方法(psql接続後):
psqlにスーパーユーザーとして接続します。

bash
psql -U postgres

psqlプロンプトが表示されたら、以下のSQL文を実行します。

sql
CREATE USER myuser WITH PASSWORD 'mypassword';

myuserは作成したいユーザー名、mypasswordはそのパスワードです。WITH PASSWORD句は省略可能ですが、セキュリティのためパスワードを設定することを強く推奨します。より詳細な権限(データベース作成権限など)もここで指定できますが、まずは基本的なユーザー作成に留めます。

作成されたユーザーを確認するには、psql接続中に以下のメタコマンドを使います。

\du
または

\dp
ユーザー(ロール)の一覧とそれぞれの権限が表示されます。

ユーザーを削除するには、dropuserコマンドまたはSQLのDROP USER文を使います。注意:ユーザーが所有しているオブジェクト(テーブルなど)がある場合、削除できないか、オブジェクトも同時に削除される可能性があります。

dropuserコマンドを使う方法:
ターミナルを開き、スーパーユーザーとして以下のコマンドを実行します。

bash
dropuser myuser -U postgres

SQL文を使う方法(psql接続後):
psqlにスーパーユーザーとして接続し、以下のSQL文を実行します。

sql
DROP USER myuser;

4.3 データベースへの接続と切断

作成したデータベースに接続するには、psqlコマンドのオプションで接続先を指定します。

ターミナルで以下のコマンドを実行します。

bash
psql -d mydatabase -U myuser -h localhost -p 5432

* -d mydatabase: 接続先のデータベース名
* -U myuser: 接続ユーザー名
* -h localhost: 接続先ホスト名(ローカルホストの場合)
* -p 5432: 接続先ポート番号(デフォルトの5432以外の場合)

パスワードを求められたら入力します。接続に成功すると、プロンプトがmydatabase=>またはmydatabase=#(スーパーユーザーの場合)のように変化します。

psqlに接続した後で、別のデータベースに切り替えることも可能です。psql接続中に以下のメタコマンドを使います。

\c anotherdatabase
または

\connect anotherdatabase
接続先のデータベースがanotherdatabaseに切り替わります。

psqlセッションを終了するには、以下のコマンドを実行します。

\q

4.4 psqlの便利な機能

psqlには、SQL文の実行以外にも便利な機能が多くあります。

  • メタコマンド: \で始まるコマンドはSQL文ではなく、psqlに対する命令です。\l, \du, \c 以外にも多くのコマンドがあります。例えば、\dt でテーブル一覧、\d table_name でテーブルの詳細情報が表示されます。
  • 入力補完: SQLキーワード、テーブル名、列名などは、Tabキーを押すことで入力補完が効きます。
  • コマンド履歴: 上下キーで過去に実行したコマンドを呼び出せます。
  • 外部ファイルからのSQL実行: \i filename でファイルに書かれたSQL文を一括実行できます。

\?コマンドでメタコマンドのヘルプが表示されます。\h でSQLコマンドのヘルプが表示されます。ぜひ色々と試してみてください。

第5章:SQLの基礎(DMLとDDL)

ここからがデータベース操作の核心です。SQLを使ってテーブルを作成し、データを操作する方法を具体的に見ていきましょう。

以降のSQL例は、psqlで作成したデータベースに接続し、プロンプトが表示されている状態で行うことを想定しています。

5.1 テーブルの作成 (CREATE TABLE)

リレーショナルデータベースはテーブルを中心に構成されます。テーブルを作成するには、CREATE TABLE文を使います。テーブルを定義する際には、テーブル名、各列の名前、そしてその列に格納するデータの種類を示す「データ型」を指定します。

基本的な構文:

sql
CREATE TABLE table_name (
column1_name data_type [column_constraint],
column2_name data_type [column_constraint],
...
[table_constraint]
);

例:顧客情報を格納するcustomersテーブルを作成します。

sql
CREATE TABLE customers (
customer_id SERIAL PRIMARY KEY,
first_name VARCHAR(50) NOT NULL,
last_name VARCHAR(50) NOT NULL,
email VARCHAR(100) UNIQUE,
phone VARCHAR(20),
address TEXT,
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);

上記の例で使われている要素を見ていきましょう。

  • CREATE TABLE customers (...): customersという名前のテーブルを作成します。
  • customer_id SERIAL PRIMARY KEY:
    • customer_id: 列の名前です。
    • SERIAL: PostgreSQL固有のデータ型です。整数型(通常はINTEGER)の一種で、新しい行が追加されるたびに自動的にユニークな連番が生成され、その列に挿入されます。主キー(PRIMARY KEY)として使われることが多いです。内部的にはシーケンスというオブジェクトが使われます。
    • PRIMARY KEY: その列がテーブルの主キーであることを示します。主キーは、テーブル内の各行を一意に識別するための列または列の組み合わせです。主キーには以下の特性があります。
      • 値はテーブル内でユニークであること。
      • 値がNULLであってはならないこと(NOT NULL制約が自動的に付与されます)。
      • 各テーブルは通常、一つだけ主キーを持ちます。
  • first_name VARCHAR(50) NOT NULL:
    • first_name: 列の名前です。
    • VARCHAR(50): 可変長文字列型です。括弧内の数字(50)は、格納できる最大文字数を示します。
    • NOT NULL: 列制約の一つです。この列にNULL値(値が未定義である状態)を格納することを禁止します。
  • last_name VARCHAR(50) NOT NULL: first_nameと同様です。
  • email VARCHAR(100) UNIQUE:
    • UNIQUE: 列制約の一つです。この列の値がテーブル全体でユニーク(一意)でなければならないことを示します。ただし、NULL値は複数許容されます(標準SQLのUNIQUE制約の仕様)。
  • phone VARCHAR(20): 電話番号を格納する可変長文字列型です。特に制約はつけていませんが、必要に応じてUNIQUE制約などを追加できます。
  • address TEXT: 可変長文字列型の一種で、VARCHARよりも長い文字列を格納するのに適しています。長さの制限はほとんどありません。
  • created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP:
    • TIMESTAMP WITH TIME ZONE: タイムゾーン情報を含む日付と時刻を格納するデータ型です。
    • DEFAULT CURRENT_TIMESTAMP: デフォルト値制約です。新しい行が挿入される際に、この列に値が指定されなかった場合、CURRENT_TIMESTAMP(現在のサーバー時刻とタイムゾーン)が自動的に挿入されます。

PostgreSQLの主なデータ型:

データ型 説明
SMALLINT, INTEGER, BIGINT 整数型(格納できる範囲が異なる) 123, -45
SERIAL, BIGSERIAL 自動増加する整数型(主キーによく使われる) 自動生成される連番
DECIMAL(p, s), NUMERIC(p, s) 精度の高い数値型(p: 全桁数, s: 小数点以下の桁数) 123.45, -10.00
REAL, DOUBLE PRECISION 浮動小数点数型(概算値) 3.14, 1.2e-5
BOOLEAN, BOOL 真偽値 (TRUE, FALSE, NULL) TRUE, FALSE
VARCHAR(n), CHARACTER VARYING(n) 可変長文字列(最大長n) 'Hello'
CHAR(n), CHARACTER(n) 固定長文字列(常にn文字、短い場合はスペースで埋める) 'A '
TEXT 長い可変長文字列(実質的な長さ制限なし) '長い文章'
DATE 日付のみ '2023-10-27'
TIME, TIME WITH TIME ZONE 時刻のみ '10:30:00', '10:30:00+09'
TIMESTAMP, TIMESTAMP WITH TIME ZONE 日付と時刻 '2023-10-27 10:30:00', '2023-10-27 10:30:00+09'
INTERVAL 時間間隔 '1 hour', '1 year 2 months'
UUID ユニバーサル一意識別子 'a1b2c3d4-e5f6-7890-1234-567890abcdef'
JSON, JSONB JSONデータ(JSONBはバイナリ形式で効率的) '{"key": "value"}'
ARRAY 配列(例: INTEGER[] 整数型の配列) {1, 2, 3}

テーブル一覧を表示するには \dt コマンド、テーブルの詳細(列や制約)を表示するには \d table_name コマンドを使います。

\dt
\d customers

5.2 データの挿入 (INSERT INTO)

テーブルに新しい行を追加するには、INSERT INTO文を使います。

基本的な構文:

sql
INSERT INTO table_name (column1, column2, ...)
VALUES (value1, value2, ...);

例:customersテーブルに新しい顧客を追加します。customer_idはSERIAL型なので指定不要です。created_atはデフォルト値があるので指定しなくても自動的に入ります。

“`sql
INSERT INTO customers (first_name, last_name, email, phone, address)
VALUES (‘Taro’, ‘Yamada’, ‘[email protected]’, ‘090-1234-5678’, ‘Tokyo, Japan’);

INSERT INTO customers (first_name, last_name, email)
VALUES (‘Hanako’, ‘Sato’, ‘[email protected]’);
``SERIAL型のcustomer_idDEFAULT値を持つcreated_at`列は、値を省略して挿入できます。これらの列には、PostgreSQLによって自動生成された値またはデフォルト値が格納されます。

全ての列に値を指定する場合(SERIALやDEFAULTを持つ列も含め、テーブル定義の順番通りに値を指定する場合)は、列名のリストを省略することも可能です。

sql
-- 非推奨: 列の順番が変わるとエラーになるため、列リストは明示する方が安全
-- INSERT INTO customers VALUES (DEFAULT, 'Jiro', 'Tanaka', '[email protected]', NULL, NULL, DEFAULT);

SERIAL列に明示的に値を指定したい場合はDEFAULTキーワードを使用するか、値を直接指定します(ただし、重複しないように注意が必要です)。

挿入に成功すると、INSERT 0 1 のようなメッセージが表示されます。これは「0行目から開始して、1行挿入しました」という意味です。

5.3 データの参照 (SELECT)

テーブルに格納されているデータを取得するには、SELECT文を使います。これが最も頻繁に使うSQL文です。

基本的な構文:

sql
SELECT column1, column2, ... FROM table_name [WHERE condition] [ORDER BY columns] [LIMIT count] [OFFSET offset];

例:customersテーブルから全ての列、全ての行を取得します。

sql
SELECT * FROM customers;

*は「全ての列」を意味します。

特定の列だけを取得する場合:

sql
SELECT first_name, last_name, email FROM customers;

5.4 条件を指定してデータを絞り込む (WHERE)

特定の条件を満たす行だけを取得するには、WHERE句を使います。

基本的な構文:

sql
SELECT ... FROM table_name WHERE condition;

conditionには、列の値を使った比較や論理式を指定します。

例:姓が’Yamada’の顧客を取得します。

sql
SELECT * FROM customers WHERE last_name = 'Yamada';

文字列リテラルはシングルクォーテーション'で囲みます。

例:IDが2より大きい顧客を取得します。

sql
SELECT * FROM customers WHERE customer_id > 2;

例:メールアドレスが登録されている顧客を取得します(NULLではない行)。

sql
SELECT * FROM customers WHERE email IS NOT NULL;

NULLとの比較には =<> ではなく IS NULL または IS NOT NULL を使います。

例:名前に’太郎’が含まれる顧客を取得します(部分一致検索)。

sql
SELECT * FROM customers WHERE first_name LIKE '%太郎%';

LIKE句は文字列のパターンマッチングに使います。%は任意の長さ(0文字以上)の文字列を表します。_は任意の一文字を表します。

複数の条件を組み合わせるには、AND, OR, NOT といった論理演算子を使います。

例:姓が’Yamada’で、かつメールアドレスが登録されている顧客を取得します。

sql
SELECT * FROM customers WHERE last_name = 'Yamada' AND email IS NOT NULL;

例:姓が’Yamada’、または姓が’Sato’の顧客を取得します。

sql
SELECT * FROM customers WHERE last_name = 'Yamada' OR last_name = 'Sato';

IN演算子を使うと、複数の OR 条件を簡潔に書くことができます。

sql
SELECT * FROM customers WHERE last_name IN ('Yamada', 'Sato');

例:IDが1から3の間の顧客を取得します。

sql
SELECT * FROM customers WHERE customer_id BETWEEN 1 AND 3;

BETWEENは指定した範囲(境界値を含む)の値を取得します。

5.5 取得するデータの並び順を指定する (ORDER BY)

取得したデータを特定の列の順に並べ替えるには、ORDER BY句を使います。

基本的な構文:

sql
SELECT ... FROM table_name [WHERE condition] ORDER BY column1 [ASC|DESC], column2 [ASC|DESC], ...;

例:顧客を姓の昇順(あいうえお順)で並べ替えます。

sql
SELECT * FROM customers ORDER BY last_name ASC; -- ASCは昇順(デフォルト)

例:顧客を登録日時が新しい順(降順)で並べ替えます。

sql
SELECT * FROM customers ORDER BY created_at DESC; -- DESCは降順

複数の列で並べ替える場合、ORDER BY句に複数の列をカンマ区切りで指定します。最初の列で並べ替えた後、同じ値を持つ行は次の列で並べ替えます。

例:姓の昇順で並べ替え、同じ姓の場合は名の昇順で並べ替えます。

sql
SELECT * FROM customers ORDER BY last_name ASC, first_name ASC;

5.6 取得する行数を制限する (LIMIT, OFFSET)

取得するデータの件数を制限したり、特定の位置からデータを取得したりするには、LIMIT句とOFFSET句を使います。これらは、Webサイトのページング機能などでよく利用されます。

基本的な構文:

sql
SELECT ... FROM table_name [WHERE condition] [ORDER BY columns] LIMIT count [OFFSET offset];

例:最初の3人の顧客を取得します。

sql
SELECT * FROM customers LIMIT 3;

例:最初の3人をスキップして、次の3人の顧客を取得します(2ページ目を表示する場合など)。

sql
SELECT * FROM customers LIMIT 3 OFFSET 3;

LIMITOFFSETは通常、ORDER BY句と組み合わせて使います。なぜなら、順序を指定しないと、どの「最初の」行や「次の」行が取得されるかがデータベースの実装に依存し、結果が不定になる可能性があるためです。

5.7 データの更新 (UPDATE)

既存のデータを変更するには、UPDATE文を使います。

基本的な構文:

sql
UPDATE table_name
SET column1 = value1, column2 = value2, ...
[WHERE condition];

WHERE句を省略すると、テーブルの全ての行が更新されてしまうので、UPDATE文を使う際はWHERE句の指定を忘れないように細心の注意を払ってください。

例:IDが1の顧客のメールアドレスと電話番号を更新します。

sql
UPDATE customers
SET email = '[email protected]', phone = '080-9876-5432'
WHERE customer_id = 1;

例:電話番号がNULLの全ての顧客の電話番号を、特定のデフォルト値で更新します。

sql
UPDATE customers
SET phone = 'UNKNOWN'
WHERE phone IS NULL;

更新に成功すると、UPDATE N のようなメッセージが表示されます。Nは更新された行数です。

5.8 データの削除 (DELETE FROM)

テーブルから行を削除するには、DELETE FROM文を使います。

基本的な構文:

sql
DELETE FROM table_name [WHERE condition];

WHERE句を省略すると、テーブルの全ての行が削除されてしまうので、DELETE文を使う際はWHERE句の指定を忘れないように細心の注意を払ってください。

例:IDが2の顧客を削除します。

sql
DELETE FROM customers WHERE customer_id = 2;

例:姓が’Sato’の全ての顧客を削除します。

sql
DELETE FROM customers WHERE last_name = 'Sato';

テーブルの全ての行を削除したい場合は、TRUNCATE TABLEを使う方が効率的な場合があります(ただし、トランザクションの挙動などがDELETEとは異なります)。

例:customersテーブルの全ての行を削除(切り捨て)します。

sql
TRUNCATE TABLE customers;

TRUNCATE TABLEは、テーブルを再作成するのと似た動作をします。通常、DELETEのように1行ずつ削除するよりも高速です。ただし、トランザクション内でロールバック可能ではありますが、トリガーは発生しません。

削除に成功すると、DELETE N のようなメッセージが表示されます。Nは削除された行数です。(TRUNCATEの場合は通常メッセージは出ません)

第6章:より進んだSQLの概念(入門編)

ここでは、入門者向けにも理解しておくと役立つ、少しだけ進んだSQLの概念をいくつか紹介します。

6.1 制約 (Constraints)

第5章のCREATE TABLEの例でPRIMARY KEY, NOT NULL, UNIQUE, DEFAULTといった制約が出てきました。制約は、テーブル内のデータが満たすべきルールを定義し、データの正確性や一貫性(Integrity)を保証するために非常に重要です。

主な制約を改めてまとめます。

  • NOT NULL: その列にNULL値を格納することを禁止します。
  • UNIQUE: その列の値(または列の組み合わせの値)がテーブル全体で一意でなければならないことを保証します。複数の列を組み合わせたユニーク制約も定義できます。
  • PRIMARY KEY: テーブルの主キーを定義します。NOT NULLUNIQUEの両方の特性を持ち、各行を一意に識別するために使用されます。各テーブルに一つだけ定義できます。
  • FOREIGN KEY (外部キー): 他のテーブルの主キー(またはUNIQUE制約を持つ列)を参照する列です。これにより、テーブル間のリレーションシップを表現し、参照先のテーブルに存在する値のみが参照元テーブルに格納されるように強制できます。データの「参照整合性」を保つために不可欠です。
    • 例:注文テーブルが顧客テーブルのcustomer_idを参照する場合。存在しない顧客IDの注文は登録できなくなります。
  • CHECK: 特定の条件を満たす値のみがその列に格納されるように強制します。
    • 例:年齢列が0以上の値であること、性別列が’M’または’F’のみを受け入れることなど。

FOREIGN KEYの例:

商品テーブルproductsと注文項目テーブルorder_itemsを考えます。order_itemsテーブルは、どの商品が注文されたかを示すために、productsテーブルのproduct_idを参照する必要があります。

“`sql
CREATE TABLE products (
product_id SERIAL PRIMARY KEY,
product_name VARCHAR(100) NOT NULL,
price DECIMAL(10, 2) NOT NULL
);

CREATE TABLE order_items (
order_item_id SERIAL PRIMARY KEY,
order_id INTEGER NOT NULL, — 注文テーブルへの参照を想定
product_id INTEGER NOT NULL,
quantity INTEGER NOT NULL CHECK (quantity > 0), — 数量は0より大きい
FOREIGN KEY (product_id) REFERENCES products (product_id) ON DELETE RESTRICT
);
``order_itemsテーブルのproduct_id列は、productsテーブルのproduct_id`列を参照する外部キーとして定義されています。

ON DELETE RESTRICTは、参照先の行(ここではproductsテーブルの商品)を削除しようとしたときに、その行を参照している外部キーを持つ行(ここではorder_itemsの項目)が存在する場合は削除を禁止するという設定です。他にもCASCADE(参照元も一緒に削除)、SET NULL(参照元の外部キー列をNULLにする)、SET DEFAULTなどのオプションがあります。

制約はCREATE TABLE時に定義するのが一般的ですが、ALTER TABLE文を使って後から追加・削除することも可能です。

6.2 インデックス (Indexes)

インデックスは、テーブルからデータを高速に検索するための仕組みです。本の索引に似ています。特定の列にインデックスを作成すると、その列の値に基づいてデータを効率的に検索できるようになります。

WHERE句で頻繁に検索条件として使われる列や、JOIN句で関連付けに使われる列には、インデックスを作成することを検討すると良いでしょう。主キーとUNIQUE制約を持つ列には、通常自動的にインデックスが作成されます。

インデックスを作成するには、CREATE INDEX文を使います。

基本的な構文:

sql
CREATE INDEX index_name ON table_name (column1, column2, ...);

例:customersテーブルのlast_name列にインデックスを作成します。

sql
CREATE INDEX idx_customers_last_name ON customers (last_name);

インデックスは検索を高速化しますが、データの挿入・更新・削除時にはインデックスの更新が必要になるため、これらの操作のパフォーマンスにはわずかに影響を与えます。したがって、全ての列に無差別にインデックスを作成するのではなく、実際に検索性能がボトルネックになっている箇所に効果的に作成することが重要です。

テーブルに作成されているインデックスを確認するには \d table_name コマンドを使います。

6.3 ビュー (Views)

ビューは、一つまたは複数のテーブルに対するSELECTクエリの結果を仮想的なテーブルとして定義したものです。ビュー自体はデータを持ちませんが、ビューを参照すると、その定義に従ってデータがリアルタイムに生成されます。

ビューを使うと、以下のようなメリットがあります。

  • 複雑なクエリの単純化: 複雑なSELECT文をビューとして定義しておけば、後はビューを普通のテーブルのように参照するだけで済みます。
  • セキュリティ: ユーザーに特定のテーブルの全ての列を見せたくない場合、必要な列だけを含むビューを作成し、そのビューへのアクセス権限だけを付与するといった使い方ができます。
  • 互換性: テーブル構造を変更した場合でも、ビューの定義を修正することで、ビューを利用しているアプリケーション側のコードを変更せずに済む場合があります。

ビューを作成するには、CREATE VIEW文を使います。

基本的な構文:

sql
CREATE VIEW view_name AS
SELECT ... FROM ... WHERE ...; -- ビューの定義となるSELECT文

例:customersテーブルから、氏名とメールアドレスだけを含むビューを作成します。

sql
CREATE VIEW customer_contact_info AS
SELECT customer_id, first_name, last_name, email
FROM customers;

作成したビューは、通常のテーブルと同様にSELECT文で参照できます。

sql
SELECT * FROM customer_contact_info WHERE customer_id = 1;

ビュー一覧を表示するには \dv コマンドを使います。

6.4 トランザクション (Transactions)

トランザクションは、データベースに対する一連の操作(SQL文)を一つの論理的な作業単位として扱う仕組みです。トランザクション内の全ての操作が成功するか、あるいは一つでも失敗した場合は全ての操作がキャンセルされ、データベースはトランザクション開始前の状態に戻ります。

これにより、データの整合性を保つことができます。例えば、銀行の口座振替処理では、「A口座から1000円減らす」操作と「B口座に1000円増やす」操作は、両方成功するか、両方とも失敗する必要があります。片方だけ成功してしまうと、データの矛盾(お金が消える、または増える)が発生します。トランザクションを使えば、このような問題を回避できます。

トランザクションは以下のACID特性を満たすことが期待されます。

  • Atomicity (原子性): トランザクション内の全ての操作は、全て実行されるか、全く実行されないかのどちらかである。
  • Consistency (一貫性): トランザクションの開始前と完了後で、データベースの整合性制約が満たされている。
  • Isolation (独立性): 複数のトランザクションが同時に実行されても、それぞれが独立して実行されているかのように振る舞い、互いに干渉しない。
  • Durability (永続性): トランザクションが一度完了(コミット)したら、その変更はシステム障害が発生しても失われない。

多くのDBMSでは、デフォルトで各SQL文が独立したトランザクションとして自動的にコミットされます(オートコミット)。しかし、複数の関連する操作を一つの単位として扱いたい場合は、明示的にトランザクションを開始する必要があります。

PostgreSQLでトランザクションを制御するためのSQL文は以下の通りです。

  • BEGIN; または START TRANSACTION;: トランザクションを開始します。
  • COMMIT;: トランザクション内の全ての操作を確定し、変更をデータベースに永続化します。
  • ROLLBACK;: トランザクション内の全ての操作を取り消し、データベースをトランザクション開始前の状態に戻します。

例:複数のINSERT操作を一つのトランザクションとして実行します。

“`sql
BEGIN; — トランザクション開始

— 最初の挿入
INSERT INTO customers (first_name, last_name, email) VALUES (‘Ichiro’, ‘Suzuki’, ‘[email protected]’);

— 2番目の挿入(ここでは意図的にエラーを発生させる構文間違いを想定)
— INSERT INTO customers (first_name, last_name, email) VALUES (‘Jiro’, ‘Sato’, ‘[email protected]

— もし全て成功したと仮定してコミット
— COMMIT;

— もし途中でエラーが発生した場合、または操作を取り消したい場合
— ROLLBACK;
“`

上記の例で、もし2番目のINSERT文がエラーになった場合、ROLLBACK;を実行すれば、最初のINSERT文による変更(Ichiro Suzukiの追加)も取り消され、データベースの状態はBEGIN;を実行する前に戻ります。全て成功した場合にのみCOMMIT;を実行します。

psqlでは、デフォルトでオートコミットが有効になっています。\set AUTOCOMMIT off メタコマンドを使うと、オートコミットを無効にして、明示的にCOMMITまたはROLLBACKするまで変更が確定されないようにすることができます。

6.5 集計関数とGROUP BY

データに対して合計、平均、個数などを計算するには、集計関数を使います。

主な集計関数:

  • COUNT(*) または COUNT(column): 行数を数えます。COUNT(column)はNULL値を除く行数を数えます。
  • SUM(column): 数値列の合計値を計算します。
  • AVG(column): 数値列の平均値を計算します。
  • MIN(column): 列の最小値を求めます。
  • MAX(column): 列の最大値を求めます。

例:customersテーブルの行数を数えます。

sql
SELECT COUNT(*) FROM customers;

例:productsテーブルの商品の平均価格を求めます。

sql
SELECT AVG(price) FROM products;

GROUP BY: 集計関数は、テーブル全体に対して計算を行うのが基本ですが、GROUP BY句を使うと、特定の列の値に基づいて行をグループ化し、グループごとに集計を行うことができます。

基本的な構文:

sql
SELECT column1, column2, ..., aggregate_function(column)
FROM table_name
[WHERE condition]
GROUP BY column1, column2, ...
[HAVING condition_on_group]
[ORDER BY columns];

例:注文項目テーブルorder_itemsがあると仮定して、商品ごとに注文された合計数量を求めます。

sql
SELECT product_id, SUM(quantity) AS total_quantity
FROM order_items
GROUP BY product_id;

AS total_quantityは、集計結果の列に別名(エイリアス)をつけるものです。

HAVING句は、GROUP BYでグループ化された結果に対して条件を指定する場合に使います。WHERE句はグループ化前の各行に対して条件を指定するのに対し、HAVING句はグループ全体の集計値などに対して条件を指定します。

例:商品ごとに注文された合計数量を求め、合計数量が10以上の商品のみを表示します。

sql
SELECT product_id, SUM(quantity) AS total_quantity
FROM order_items
GROUP BY product_id
HAVING SUM(quantity) >= 10;

6.6 JOIN

リレーショナルデータベースでは、関連するデータが複数のテーブルに分散して格納されているのが一般的です。例えば、顧客情報と注文情報は別々のテーブルに格納されます。これらの関連する情報を組み合わせて取得するには、JOIN句を使います。

最も一般的なのは、共通の列(通常は一方のテーブルの主キーと、もう一方のテーブルの外部キー)の値が一致する行を結合するINNER JOINです。

基本的な構文:

sql
SELECT column_list
FROM table1
INNER JOIN table2 ON table1.common_column = table2.common_column;

例:customersテーブルとordersテーブル(顧客IDを外部キーとして持つと仮定)を結合し、どの顧客がどの注文をしたかを表示します。

“`sql
— orders テーブルの定義例
— CREATE TABLE orders (
— order_id SERIAL PRIMARY KEY,
— customer_id INTEGER NOT NULL REFERENCES customers (customer_id),
— order_date DATE NOT NULL
— );

SELECT
customers.first_name,
customers.last_name,
orders.order_id,
orders.order_date
FROM
customers
INNER JOIN
orders ON customers.customer_id = orders.customer_id;
``ON customers.customer_id = orders.customer_idは、customersテーブルのcustomer_id列とordersテーブルのcustomer_id列の値が一致する行を結合する条件です。列名が重複する場合(例:customer_id)、table_name.column_name`のようにテーブル名をプレフィックスとして付けて区別する必要があります。

エイリアス: テーブル名が長い場合や、自己結合(同じテーブルを結合)を行う場合など、テーブル名に短い別名(エイリアス)を付けるとクエリが読みやすくなります。

sql
SELECT
c.first_name,
c.last_name,
o.order_id,
o.order_date
FROM
customers AS c -- customers テーブルに c というエイリアスをつける
INNER JOIN
orders AS o ON c.customer_id = o.customer_id; -- orders テーブルに o というエイリアスをつける

JOINの種類: INNER JOIN以外にも、以下のような結合方法があります。

  • LEFT JOIN (または LEFT OUTER JOIN): 左側のテーブルの全ての行と、結合条件に一致する右側のテーブルの行を結合します。右側に一致する行がない場合は、右側の列はNULLになります。
  • RIGHT JOIN (または RIGHT OUTER JOIN): 右側のテーブルの全ての行と、結合条件に一致する左側のテーブルの行を結合します。左側に一致する行がない場合は、左側の列はNULLになります。
  • FULL JOIN (または FULL OUTER JOIN): 左右どちらかのテーブルの行に一致するものがあれば全て結合します。どちらかのテーブルにしか存在しない行の場合、他方のテーブルの列はNULLになります。
  • CROSS JOIN: 左側のテーブルの全ての行と右側のテーブルの全ての行の組み合わせを生成します(デカルト積)。通常、結合条件は指定しません。

例:全ての顧客(たとえ注文がなくても)と、もしあればその注文情報を表示します。

sql
SELECT
c.first_name,
c.last_name,
o.order_id,
o.order_date
FROM
customers AS c
LEFT JOIN -- LEFT JOIN を使用
orders AS o ON c.customer_id = o.customer_id;

このクエリを実行すると、注文がない顧客の行も結果に含まれます。その場合、o.order_ido.order_dateの列はNULLになります。

JOINはリレーショナルデータベースの強力な機能であり、複数のテーブルからデータを結合して取得するクエリは非常に頻繁に登場します。最初は難しく感じるかもしれませんが、図などを書いてテーブル間の関係性を整理しながら練習すると理解が深まります。

第7章:GUIツールの紹介

これまでコマンドラインツールであるpsqlを中心に説明してきましたが、データベースの操作や管理にはGUIツールを使う方が視覚的で分かりやすい場面が多くあります。PostgreSQL用のGUIツールはいくつか存在します。

7.1 pgAdmin

pgAdmin (https://www.pgadmin.org/) は、PostgreSQLの公式GUI管理ツールです。Windows、macOS、Linuxで利用できます。PostgreSQLのインストーラーに含まれていることが多く、別途インストールすることも可能です。

pgAdminを使うと、以下のような操作をGUIで行えます。

  • サーバーへの接続、管理
  • データベース、スキーマ、テーブル、ビューなどのオブジェクト作成、変更、削除
  • テーブルデータの閲覧、編集、挿入、削除
  • SQLクエリエディタでのクエリ実行、結果表示
  • インデックス、制約、トリガーなどの管理
  • サーバーログの表示
  • バックアップ、リストア

特にSQLクエリエディタは、入力補完や構文ハイライトなどがあり、SQL文を作成・実行する際に非常に便利です。psqlと並行して、あるいは主に使用するツールとして活用すると良いでしょう。

7.2 その他のGUIツール

pgAdmin以外にも、多くのPostgreSQL対応GUIツールがあります。

  • DBeaver: オープンソースの汎用データベースツールで、PostgreSQL以外にも多くのデータベースに対応しています。機能が豊富で、カスタマイズ性も高いです。
  • TablePlus: シンプルで高速なGUIツールで、多くのデータベースに対応しています。直感的な操作性が特徴です。
  • DataGrip: JetBrains社が提供する商用データベースIDEです。非常に高機能で、大規模開発やプロフェッショナルな用途に適しています。

これらのツールも検討し、自分の好みや必要な機能に応じて選んでみてください。

第8章:トラブルシューティングのヒント

データベースを使い始める際には、様々な問題に遭遇することがあります。ここでは、入門者が遭遇しやすい一般的な問題と、その対処法に関するヒントをいくつか紹介します。

8.1 接続エラー

PostgreSQLサーバーに接続できない場合、以下の点を確認してください。

  • サーバーは起動していますか?: PostgreSQLサービス/プロセスが実行されているか確認してください。OSのサービス管理ツール(Windowsサービス、systemctl、brew servicesなど)や、アクティビティモニター/タスクマネージャーなどで確認できます。
  • ポート番号は正しいですか?: デフォルトは5432ですが、設定で変更されている可能性があります。接続しようとしているポート番号とサーバーの設定(postgresql.confファイルで確認可能)が一致しているか確認してください。
  • ホスト名やIPアドレスは正しいですか?: localhost127.0.0.1で接続できない場合、サーバーが別のマシンで動いているか、ネットワーク設定に問題がある可能性があります。
  • ユーザー名とパスワードは正しいですか?: 大文字小文字を含めて正確に入力されているか確認してください。
  • 認証設定は正しいですか?: PostgreSQLはクライアント認証に様々な方法(password, trust, peer, identなど)を利用できます。サーバーの設定ファイル(通常pg_hba.conf)で、接続元、データベース、ユーザー、認証方法の組み合わせが許可されているか確認する必要があります。特にLinux環境でOSユーザーとデータベースユーザーのマッピングに起因する認証エラーが多いです。
  • ファイアウォールはブロックしていませんか?: サーバー側やクライアント側のファイアウォールがPostgreSQLのポート(デフォルト5432)への接続をブロックしていないか確認してください。

8.2 SQL構文エラー

ERROR: syntax error at or near ... のようなメッセージが表示された場合、SQL文の構文に誤りがあります。

  • キーワードのスペルミス: SELECT, FROM, WHEREなどのキーワードのスペルを確認してください。
  • セミコロンの不足: SQL文の最後に;がついているか確認してください(psqlでは必須ではありませんが、つけるのが慣例で安全です)。
  • クォーテーションの不足: 文字列リテラルはシングルクォーテーション'で囲む必要があります。テーブル名や列名に予約語や特殊文字が含まれる場合はダブルクォーテーション"で囲む必要があります。
  • カッコの対応: (...)[...]などのカッコが正しく対応しているか確認してください。
  • データ型の不一致: INSERTUPDATEで、列のデータ型と挿入/更新しようとしている値のデータ型が一致しない場合にエラーになることがあります。
  • 存在しないオブジェクト: テーブル名や列名が存在しない場合にエラーになります。\d コマンドなどで確認してください。

エラーメッセージには、エラーが発生した位置(行番号や文字位置)や、原因のヒントが示されていることが多いです。メッセージをよく読み、どの部分が問題なのかを特定することが重要です。

8.3 データ関連のエラー

  • 制約違反: NOT NULL制約に違反してNULLを挿入しようとしたり、UNIQUE制約に違反して重複する値を挿入しようとしたり、FOREIGN KEY制約に違反して参照先の存在しない値を挿入しようとした場合などにエラーが発生します。エラーメッセージには、どの制約に違反したかが示されます。
  • データ型の範囲外: 数値型や日付/時刻型の列に、そのデータ型で表現できない範囲の値を挿入しようとするとエラーになります。

8.4 ログファイルの確認

PostgreSQLサーバーは、起動時や実行中に発生したエラー、警告、情報メッセージなどをログファイルに記録します。問題が発生した際には、ログファイルを確認することが原因特定の手がかりになります。

ログファイルの場所は、PostgreSQLの設定(postgresql.confファイル)やインストール方法によって異なります。一般的な場所としては、データディレクトリ内のlogサブディレクトリや、OSのシステムログ(syslog, journaldなど)に記録されることがあります。

ログファイルを確認する際は、エラーが発生した日時付近のメッセージに注目しましょう。

第9章:次のステップ

この記事では、PostgreSQLの基本的な概念と使い始め方、SQLの基礎を中心に解説しました。PostgreSQLは非常に多機能なDBMSであり、学ぶべきことは他にもたくさんあります。ここでは、さらにPostgreSQLの学習を深めるための次のステップを紹介します。

  • 公式ドキュメントを読む: PostgreSQLの公式ドキュメント(https://www.postgresql.org/docs/)は非常に網羅的で正確な情報源です。最初は難しく感じるかもしれませんが、特定の機能やSQL文について詳しく知りたいときに参照すると役立ちます。
  • より高度なSQL: サブクエリ、共通テーブル式 (CTE)、ウィンドウ関数、分析関数など、より複雑なデータ分析や操作のためのSQL機能を学びましょう。
  • データ定義と操作の詳細: データ型の詳細、型キャスト、演算子、組み込み関数などを学び、様々なデータを効果的に扱えるようになりましょう。
  • パフォーマンスチューニング: 大量のデータを扱うシステムでは、クエリの実行速度が重要になります。実行計画 (Execution Plan) の読み方、インデックス戦略、テーブル設計の最適化など、パフォーマンス関連の知識を深めましょう。
  • バックアップとリストア: データの損失を防ぐために、データベースのバックアップ方法と、万が一の際にデータを復旧させるリストア方法を学びましょう。pg_dumppg_restoreコマンドがよく使われます。
  • ユーザーと権限管理: 複数のユーザーがデータベースを利用する際には、セキュリティのために適切な権限管理が不可欠です。GRANTREVOKEを使った権限管理について学びましょう。
  • ストアドプロシージャと関数: 複雑な処理をデータベースサーバー側で実行するための関数やプロシージャを作成する方法を学びましょう。
  • トリガー: テーブルのデータが変更された際に、自動的に特定の処理を実行するためのトリガーを作成する方法を学びましょう。
  • 拡張機能 (Extensions): PostgreSQLは多くの便利な拡張機能を提供しています。PostGIS(地理空間データ)、pg_stat_statements(クエリ統計情報)、uuid-ossp(UUID生成)など、用途に応じた拡張機能の利用方法を学びましょう。
  • レプリケーションと高可用性: システムの信頼性や可用性を高めるために、データの複製(レプリケーション)やフェイルオーバーの仕組みについて学びましょう。
  • プログラミング言語からのアクセス: Python (psycopg2), Java (JDBC), Node.js (pg), Ruby (pg) など、様々なプログラミング言語からPostgreSQLに接続し、データベースを操作する方法を学び、アプリケーション開発に活かしましょう。

まとめ

この記事では、PostgreSQLを「使い始める」ために必要な基礎知識から、インストール方法、そして最も基本的なSQLによるデータ操作方法までを詳しく解説しました。

データベースとは何か、なぜリレーショナルデータベースが広く使われるのか、そしてPostgreSQLがどのような特徴を持つDBMSなのかを理解しました。

実際にPostgreSQLをコンピュータにインストールし、psqlコマンドを使ってデータベースを作成したり接続したりする基本的な操作を体験しました。

そして、SQLのCREATE TABLE, INSERT, SELECT, UPDATE, DELETEといったDMLおよびDDLの基本的な構文と使い方を学びました。さらに、データの整合性を保つための制約、検索を高速化するインデックス、仮想的なテーブルであるビュー、そして複数の操作を一つにまとめるトランザクションといった、リレーショナルデータベースを効果的に利用するための重要な概念にも触れました。

最後に、便利なGUIツールの紹介や、学習を進める上での次のステップについても触れました。

データベースの世界は奥深く、PostgreSQLはその中でも非常に強力で多機能なシステムです。この記事で得た知識は、その広大な世界への第一歩に過ぎません。ぜひ、手を動かしながら様々なSQL文を試したり、この記事で紹介した「次のステップ」のトピックを深掘りしたりして、PostgreSQLのスキルを磨いていってください。

この入門記事が、あなたのPostgreSQL学習の確かな土台となることを願っています。 Happy Hacking with PostgreSQL!


コメントする

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

上部へスクロール