topic: db (PDO / SQL / マルチDB) / ch11 — MySQL 固有の文法と運用 / 演習 02

📝 ドリル 02 — テーブル一覧を取得する (driver 別の SHOW TABLES 相当)

問題

採点ランナーが usersposts の 2 テーブルを用意する。これらのテーブル名を アルファベット順 で 1 行ずつ出力する。

DB ごとにテーブル一覧の取り方が違うので、DOJO_DB_DRIVER (sqlite / mysql / pgsql) で分岐する。

driver 取り方
sqlite SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%' ORDER BY name
mysql SHOW TABLES
pgsql SELECT tablename FROM pg_tables WHERE schemaname = current_schema() ORDER BY tablename

期待される出力

posts
users

ヒント

  • getenv('DOJO_DB_DRIVER') ?: 'sqlite' で driver 取得
  • PHP 8 の match 式で driver ごとに SQL を切り替えると見通しが良い
  • SHOW TABLES は 1 列だけ返るので FETCH_NUM[0] を取り出すと簡単
  • MySQL/PostgreSQL は連想配列のキー名が DB によって変わる (e.g. Tables_in_<dbname>) ので、列インデックス取得が無難
  • アルファベット順なので postsusers の順 (採点ランナーは MySQL の SHOW TABLES もこの順で返す)

採点

php scripts/grade.php topics/11-db/ch11-mysql-specific/drill/02-show-tables/

学ぶこと

  • 「DB 内のテーブル一覧」は PDO で標準化されていない。DB ごとに違うクエリを叩く必要がある
  • 逆に言えば、PDO のレイヤを抜けると DB 固有のメタデータ操作にすぐ手が届く

テストケース

期待される出力

posts
users

📄 starter.php(雛形)

このコードから書き始めてください。

<?php

require __DIR__ . '/../../../../../scripts/shared/db-connect.php';

$pdo = dojo_db_connect();
$driver = getenv('DOJO_DB_DRIVER') ?: 'sqlite';

// TODO:
// 1) $driver の値で SQL を分岐:
//    sqlite -> SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%' ORDER BY name
//    mysql  -> SHOW TABLES
//    pgsql  -> SELECT tablename FROM pg_tables WHERE schemaname = current_schema() ORDER BY tablename
// 2) クエリを実行し、テーブル名の配列を作る
// 3) 1 行ずつ echo して出力 (アルファベット順)
✅ 解答例を見る(自分で解いてから)
<?php

require __DIR__ . '/../../../../../scripts/shared/db-connect.php';

$pdo = dojo_db_connect();
$driver = getenv('DOJO_DB_DRIVER') ?: 'sqlite';

$tables = match ($driver) {
    'sqlite' => array_column(
        $pdo->query("SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%' ORDER BY name")
            ->fetchAll(PDO::FETCH_ASSOC),
        'name'
    ),
    'mysql' => array_column(
        $pdo->query("SHOW TABLES")->fetchAll(PDO::FETCH_NUM),
        0
    ),
    'pgsql' => array_column(
        $pdo->query("SELECT tablename FROM pg_tables WHERE schemaname = current_schema() ORDER BY tablename")
            ->fetchAll(PDO::FETCH_ASSOC),
        'tablename'
    ),
};

sort($tables);
foreach ($tables as $t) {
    echo "{$t}\n";
}