PostgreSQL 現在のデータベースの確認と操作 – 完全ガイド

データベース・SQL

PostgreSQLで作業していて、こんな疑問を持ったことはありませんか?

「今、どのデータベースに接続しているんだっけ?」 「間違えて本番環境のデータベースを操作していないか心配…」 「複数のデータベースを切り替えながら作業したい」

データベースを操作する際、現在どのデータベースに接続しているかを把握することは非常に重要です。間違ったデータベースでテーブルを削除してしまったら大変ですよね。

この記事では、PostgreSQLで現在のデータベースを確認する方法から、データベースの切り替え、情報取得まで、実践的なテクニックを詳しく解説していきます。

スポンサーリンク

現在のデータベースを確認する5つの方法

方法1:current_database()関数を使う(最も簡単)

-- 現在接続しているデータベース名を表示
SELECT current_database();

-- 結果例
-- current_database
-- -----------------
-- myapp_production

これが最もシンプルで確実な方法です。どんな状況でも使えます。

方法2:psqlのプロンプトで確認

psqlコマンドラインツールを使っている場合、プロンプトにデータベース名が表示されています。

# デフォルトのプロンプト表示
myapp_production=#   # スーパーユーザー
myapp_production=>   # 一般ユーザー

# データベース名が「myapp_production」だと分かる

方法3:\conninfo コマンド(psql)

接続情報の詳細を確認できます。

\conninfo

-- 結果例
-- You are connected to database "myapp_production" as user "postgres" 
-- via socket in "/var/run/postgresql" at port "5432".

データベース名だけでなく、ユーザー名、接続方法、ポート番号も分かります。

方法4:pg_stat_activityビューを使う

現在のセッション情報を確認できます。

-- 自分のセッション情報を確認
SELECT 
    datname AS current_database,
    usename AS current_user,
    client_addr AS client_address,
    application_name,
    state,
    query_start
FROM pg_stat_activity 
WHERE pid = pg_backend_pid();

-- 結果例
-- current_database | current_user | client_address | application_name | state  | query_start
-- -----------------+--------------+----------------+------------------+--------+------------------------
-- myapp_production | postgres     | 192.168.1.100  | psql             | active | 2024-12-25 10:30:15

方法5:システムカタログから確認

-- 現在のデータベースのOIDを取得して名前を確認
SELECT 
    d.datname AS database_name,
    pg_database_size(d.datname) AS size_bytes,
    pg_size_pretty(pg_database_size(d.datname)) AS size_pretty,
    d.datcollate AS collation,
    d.datctype AS character_type
FROM pg_database d
WHERE d.oid = (SELECT oid FROM pg_database WHERE datname = current_database());

-- 結果例
-- database_name    | size_bytes | size_pretty | collation  | character_type
-- -----------------+------------+-------------+------------+---------------
-- myapp_production | 524288000  | 500 MB      | ja_JP.UTF8 | ja_JP.UTF8

データベースの一覧を確認する

psqlコマンドで一覧表示

-- データベース一覧を表示
\l
-- または
\list

-- 結果例
--                              List of databases
--      Name      |  Owner   | Encoding | Collate    | Ctype      | Access privileges
-- ----------------+----------+----------+------------+------------+------------------
-- myapp_dev       | postgres | UTF8     | ja_JP.UTF8 | ja_JP.UTF8 |
-- myapp_production| postgres | UTF8     | ja_JP.UTF8 | ja_JP.UTF8 |
-- myapp_test      | postgres | UTF8     | ja_JP.UTF8 | ja_JP.UTF8 |
-- postgres        | postgres | UTF8     | ja_JP.UTF8 | ja_JP.UTF8 |
-- template0       | postgres | UTF8     | ja_JP.UTF8 | ja_JP.UTF8 | =c/postgres
-- template1       | postgres | UTF8     | ja_JP.UTF8 | ja_JP.UTF8 | =c/postgres

SQLクエリで詳細情報付き一覧

-- データベースの詳細情報を取得
SELECT 
    datname AS database_name,
    pg_size_pretty(pg_database_size(datname)) AS size,
    datcollate AS collation,
    datconnlimit AS connection_limit,
    CASE 
        WHEN datconnlimit = -1 THEN 'unlimited'
        ELSE datconnlimit::text
    END AS max_connections,
    datacl AS access_privileges
FROM pg_database
WHERE datistemplate = false  -- テンプレートデータベースを除外
ORDER BY pg_database_size(datname) DESC;

-- アクティブな接続数も含めて表示
SELECT 
    d.datname AS database_name,
    pg_size_pretty(pg_database_size(d.datname)) AS size,
    COUNT(sa.datname) AS active_connections,
    d.datconnlimit AS max_connections_allowed
FROM pg_database d
LEFT JOIN pg_stat_activity sa ON d.datname = sa.datname
WHERE d.datistemplate = false
GROUP BY d.datname, d.datconnlimit
ORDER BY active_connections DESC;

データベースを切り替える方法

psqlでの切り替え(\c コマンド)

-- 別のデータベースに接続
\c database_name
-- または
\connect database_name

-- 例:開発環境から本番環境へ切り替え
\c myapp_production

-- ユーザーも指定して接続
\c database_name username

-- ホストとポートも指定
\c database_name username hostname port

新しい接続で切り替え

# コマンドラインから直接指定のデータベースに接続
psql -d myapp_production -U postgres

# 環境変数を使って接続
export PGDATABASE=myapp_production
export PGUSER=postgres
export PGHOST=localhost
psql

# URIスタイルで接続
psql postgresql://username:password@localhost:5432/database_name

プログラムからの切り替え

Python (psycopg2)

import psycopg2

# 現在のデータベースを確認
conn = psycopg2.connect(
    host="localhost",
    database="myapp_dev",
    user="postgres",
    password="password"
)

cur = conn.cursor()
cur.execute("SELECT current_database()")
current_db = cur.fetchone()[0]
print(f"現在のデータベース: {current_db}")

# 別のデータベースに切り替え
conn.close()
conn = psycopg2.connect(
    host="localhost",
    database="myapp_production",
    user="postgres",
    password="password"
)

Node.js (pg)

const { Client } = require('pg');

// 現在のデータベースを確認
async function checkCurrentDatabase() {
    const client = new Client({
        host: 'localhost',
        database: 'myapp_dev',
        user: 'postgres',
        password: 'password',
    });
    
    await client.connect();
    const result = await client.query('SELECT current_database()');
    console.log('現在のデータベース:', result.rows[0].current_database);
    await client.end();
}

// データベースを切り替える関数
async function switchDatabase(dbName) {
    const client = new Client({
        host: 'localhost',
        database: dbName,
        user: 'postgres',
        password: 'password',
    });
    
    await client.connect();
    return client;
}

現在のデータベースの詳細情報を取得

データベースのサイズと統計

-- 現在のデータベースのサイズ
SELECT 
    current_database() AS database_name,
    pg_size_pretty(pg_database_size(current_database())) AS total_size;

-- テーブルごとのサイズも含めた詳細
SELECT 
    current_database() AS database_name,
    pg_size_pretty(pg_database_size(current_database())) AS database_size,
    COUNT(DISTINCT tablename) AS table_count,
    pg_size_pretty(SUM(pg_total_relation_size(schemaname||'.'||tablename))) AS total_tables_size
FROM pg_tables
WHERE schemaname NOT IN ('pg_catalog', 'information_schema');

-- スキーマごとのサイズ
SELECT 
    schemaname,
    COUNT(*) AS table_count,
    pg_size_pretty(SUM(pg_total_relation_size(schemaname||'.'||tablename))) AS schema_size
FROM pg_tables
WHERE schemaname NOT IN ('pg_catalog', 'information_schema')
GROUP BY schemaname
ORDER BY SUM(pg_total_relation_size(schemaname||'.'||tablename)) DESC;

接続情報と設定

-- 現在のデータベースの設定を確認
SELECT 
    name,
    setting,
    unit,
    category,
    short_desc
FROM pg_settings
WHERE name IN (
    'max_connections',
    'shared_buffers',
    'effective_cache_size',
    'maintenance_work_mem',
    'work_mem',
    'checkpoint_completion_target',
    'wal_buffers',
    'default_statistics_target',
    'random_page_cost',
    'effective_io_concurrency'
)
ORDER BY category, name;

-- 現在の接続情報の詳細
SELECT 
    current_database() AS database,
    current_user AS user,
    current_schema() AS schema,
    inet_client_addr() AS client_address,
    inet_client_port() AS client_port,
    inet_server_addr() AS server_address,
    inet_server_port() AS server_port,
    version() AS postgresql_version,
    current_timestamp AS current_time;

アクティビティとパフォーマンス

-- 現在のデータベースのアクティビティ
SELECT 
    pid,
    usename,
    application_name,
    client_addr,
    state,
    query_start,
    state_change,
    LEFT(query, 50) AS query_preview
FROM pg_stat_activity
WHERE datname = current_database()
    AND pid != pg_backend_pid()  -- 自分のセッションを除外
ORDER BY query_start DESC;

-- 現在のデータベースの統計情報
SELECT 
    datname AS database,
    numbackends AS active_connections,
    xact_commit AS transactions_committed,
    xact_rollback AS transactions_rolled_back,
    blks_read AS blocks_read_from_disk,
    blks_hit AS blocks_read_from_cache,
    ROUND(100.0 * blks_hit / NULLIF(blks_hit + blks_read, 0), 2) AS cache_hit_ratio,
    tup_returned AS rows_returned,
    tup_fetched AS rows_fetched,
    tup_inserted AS rows_inserted,
    tup_updated AS rows_updated,
    tup_deleted AS rows_deleted
FROM pg_stat_database
WHERE datname = current_database();

セキュリティを考慮した確認方法

権限の確認

-- 現在のユーザーの権限を確認
SELECT 
    current_database() AS database,
    current_user AS user,
    has_database_privilege(current_user, current_database(), 'CREATE') AS can_create,
    has_database_privilege(current_user, current_database(), 'CONNECT') AS can_connect,
    has_database_privilege(current_user, current_database(), 'TEMPORARY') AS can_create_temp;

-- データベースレベルの権限一覧
SELECT 
    datname,
    datacl
FROM pg_database
WHERE datname = current_database();

-- 現在のユーザーがアクセスできるスキーマ
SELECT 
    schema_name,
    schema_owner,
    has_schema_privilege(current_user, schema_name, 'USAGE') AS can_use,
    has_schema_privilege(current_user, schema_name, 'CREATE') AS can_create
FROM information_schema.schemata
WHERE schema_name NOT IN ('pg_catalog', 'information_schema')
ORDER BY schema_name;

監査とログ

-- 接続履歴を記録するテーブルを作成
CREATE TABLE IF NOT EXISTS connection_audit (
    id SERIAL PRIMARY KEY,
    database_name TEXT,
    user_name TEXT,
    client_address INET,
    connection_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    application_name TEXT
);

-- 接続時に自動的に記録するトリガー関数
CREATE OR REPLACE FUNCTION log_connection()
RETURNS event_trigger AS $$
BEGIN
    INSERT INTO connection_audit (
        database_name,
        user_name,
        client_address,
        application_name
    )
    VALUES (
        current_database(),
        current_user,
        inet_client_addr(),
        current_setting('application_name')
    );
END;
$$ LANGUAGE plpgsql;

-- 現在の接続を手動で記録
INSERT INTO connection_audit (
    database_name,
    user_name,
    client_address,
    application_name
)
SELECT 
    current_database(),
    current_user,
    inet_client_addr(),
    current_setting('application_name');

実践的な活用例

開発環境と本番環境を区別する

-- データベース名に基づいて環境を判定する関数
CREATE OR REPLACE FUNCTION get_environment()
RETURNS TEXT AS $$
DECLARE
    db_name TEXT;
    env TEXT;
BEGIN
    db_name := current_database();
    
    CASE 
        WHEN db_name LIKE '%production%' OR db_name LIKE '%prod%' THEN
            env := 'PRODUCTION';
        WHEN db_name LIKE '%staging%' OR db_name LIKE '%stg%' THEN
            env := 'STAGING';
        WHEN db_name LIKE '%development%' OR db_name LIKE '%dev%' THEN
            env := 'DEVELOPMENT';
        WHEN db_name LIKE '%test%' THEN
            env := 'TEST';
        ELSE
            env := 'UNKNOWN';
    END CASE;
    
    RETURN env;
END;
$$ LANGUAGE plpgsql;

-- 使用例
SELECT 
    current_database() AS database,
    get_environment() AS environment,
    CASE get_environment()
        WHEN 'PRODUCTION' THEN 'WARNING: 本番環境です!'
        WHEN 'DEVELOPMENT' THEN '開発環境です'
        ELSE get_environment()
    END AS message;

プロンプトのカスタマイズ(psql)

-- .psqlrcファイルに追加してプロンプトをカスタマイズ
\set PROMPT1 '%[%033[1;31m%]%M%[%033[0m%]:%> %[%033[1;33m%]%n%[%033[0m%]@%[%033[1;34m%]%/%[%033[0m%]%R%# '

-- 環境に応じて色を変える(本番は赤、開発は緑)
\set PROMPT1 '%`echo -e "\\033[$(psql -tc "SELECT CASE WHEN current_database() LIKE \'%prod%\' THEN \'31\' ELSE \'32\' END" | tr -d \' \')`m%/%\\033[0m %n@%M:%>%R%# "'

バックアップスクリプトでの活用

#!/bin/bash
# 現在のデータベースを自動バックアップ

DB_NAME=$(psql -t -c "SELECT current_database()" 2>/dev/null | tr -d ' ')
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
BACKUP_FILE="${DB_NAME}_${TIMESTAMP}.sql"

echo "バックアップ開始: ${DB_NAME}"
pg_dump -d ${DB_NAME} -f ${BACKUP_FILE}

if [ $? -eq 0 ]; then
    echo "バックアップ完了: ${BACKUP_FILE}"
    echo "ファイルサイズ: $(ls -lh ${BACKUP_FILE} | awk '{print $5}')"
else
    echo "バックアップ失敗"
    exit 1
fi

複数データベース間での比較

-- 複数のデータベースのサイズを比較
CREATE OR REPLACE FUNCTION compare_databases()
RETURNS TABLE(
    database_name TEXT,
    size_pretty TEXT,
    table_count BIGINT,
    index_count BIGINT,
    total_connections BIGINT
) AS $$
BEGIN
    RETURN QUERY
    SELECT 
        d.datname::TEXT,
        pg_size_pretty(pg_database_size(d.datname))::TEXT,
        (SELECT COUNT(*) FROM pg_class c 
         JOIN pg_namespace n ON n.oid = c.relnamespace 
         WHERE c.relkind = 'r' AND n.nspname NOT IN ('pg_catalog', 'information_schema')
         AND d.datname = current_database())::BIGINT,
        (SELECT COUNT(*) FROM pg_class c 
         JOIN pg_namespace n ON n.oid = c.relnamespace 
         WHERE c.relkind = 'i' AND n.nspname NOT IN ('pg_catalog', 'information_schema')
         AND d.datname = current_database())::BIGINT,
        COUNT(sa.datname)::BIGINT
    FROM pg_database d
    LEFT JOIN pg_stat_activity sa ON d.datname = sa.datname
    WHERE d.datistemplate = false
    GROUP BY d.datname;
END;
$$ LANGUAGE plpgsql;

トラブルシューティング

問題1:データベース名が表示されない

-- psqlのバージョンを確認
SELECT version();

-- プロンプト設定をリセット
\set PROMPT1 '%/%R%# '
\set PROMPT2 '%/%R%# '

-- 接続情報を再確認
\conninfo

問題2:間違ったデータベースに接続してしまった

-- 即座に接続を切る
\q

-- または別のデータベースに切り替え
\c correct_database

-- トランザクション中の場合はロールバック
ROLLBACK;
\c correct_database

問題3:データベース一覧が見えない

-- 権限を確認
SELECT has_database_privilege(current_user, datname, 'CONNECT')
FROM pg_database;

-- システムカタログへのアクセス権限を確認
SELECT has_table_privilege('pg_database', 'SELECT');

ベストプラクティス

1. 常に現在のデータベースを意識する

-- 危険な操作の前に必ず確認
DO $$
BEGIN
    IF current_database() = 'production' THEN
        RAISE EXCEPTION '本番環境での操作は禁止されています';
    END IF;
END $$;

DROP TABLE important_table;  -- この操作の前に環境確認

2. プロンプトで視覚的に区別

# .psqlrcに設定を追加
echo "\set PROMPT1 '%[%033[33m%]%M/%/%R%#%[%033[0m%] '" >> ~/.psqlrc

3. 接続文字列を環境変数で管理

# .bashrcや.zshrcに追加
export DB_DEV="postgresql://user:pass@localhost/myapp_dev"
export DB_PROD="postgresql://user:pass@localhost/myapp_prod"

# 使用
psql $DB_DEV

4. エイリアスを活用

# エイリアスを設定
alias psql-dev='psql -d myapp_dev'
alias psql-prod='psql -d myapp_production'
alias psql-current='psql -c "SELECT current_database()"'

まとめ:データベースを正しく把握して安全に作業しよう

PostgreSQLで現在のデータベースを確認・操作する方法について解説してきました。

重要なポイント:

  1. current_database()関数が最も確実な確認方法
  2. psqlの\cコマンドで簡単にデータベース切り替え
  3. プロンプトのカスタマイズで視覚的に環境を区別
  4. 権限とセキュリティを意識した操作
  5. 自動化スクリプトでも現在のデータベースを確認

データベースの操作は、一つのミスが大きな問題につながる可能性があります。特に本番環境での作業時は、必ず現在のデータベースを確認してから操作を行いましょう。

今すぐ実践できること:

  • プロンプトをカスタマイズして環境を視覚化
  • 危険な操作の前に確認する習慣をつける
  • バックアップスクリプトに確認処理を追加
  • チーム内で確認ルールを共有

正しいデータベースで、安全に作業を進めていきましょう!

コメント

タイトルとURLをコピーしました