PostgreSQLからMySQLへのテーブルデータ移行

PostgreSQL to MySQL

PostgreSQLもまだまだ現役ですが、フロントエンジニアからすれば、ツールの充実などの都合でMySQLを選択せざるを得ない状況も増えてきました。PHPもまだまだ現役。なんとか一発でMySQLへの移行ができたらと思い、作りました。

				
					<?php

// PostgreSQLデータベースの設定を配列に保存します
$pgsql = [
    'host' => 'your_postgresql_host', // PostgreSQLのホスト
    'db' => 'your_postgresql_dbname', // 使用するデータベース名
    'user' => 'your_postgresql_user', // ユーザー名
    'password' => 'your_postgresql_password' // パスワード
];

// MySQLデータベースの設定を配列に保存します
$mysql = [
    'host' => 'your_mysql_host', // MySQLのホスト
    'db' => 'your_mysql_dbname', // 使用するデータベース名
    'user' => 'your_mysql_user', // ユーザー名
    'password' => 'your_mysql_password' // パスワード
];

// PostgreSQLデータベースにPDOを使用して接続します
$pgsqlConn = new PDO("pgsql:host={$pgsql['host']};dbname={$pgsql['db']}", $pgsql['user'], $pgsql['password']);

// publicスキーマ内の全てのテーブル名を取得するSQLクエリを実行します
$tablesResult = $pgsqlConn->query("SELECT table_name FROM information_schema.tables WHERE table_schema = 'public'");
$tables = $tablesResult->fetchAll(PDO::FETCH_COLUMN); // 結果を配列として取得

// 取得したテーブルごとに処理を行います
foreach ($tables as $table) {
    // MySQLデータベースにPDOを使用して接続します
    $mysqlConn = new PDO("mysql:host={$mysql['host']};dbname={$mysql['db']}", $mysql['user'], $mysql['password']);

    // 対象テーブルのカラム名とデータ型を取得します
    $columnsResult = $pgsqlConn->query("SELECT column_name, data_type FROM information_schema.columns WHERE table_name = '{$table}'");
    $columns = $columnsResult->fetchAll(PDO::FETCH_ASSOC);

    // MySQLで使用するCREATE TABLE文を組み立てます
    $createTableSQL = "CREATE TABLE `{$table}` (";
    $colDefinitions = [];

    // 取得したカラムごとに処理を行います
    foreach ($columns as $column) {
        $colName = $column['column_name']; // カラム名
        $dataType = $column['data_type']; // データ型

        // PostgreSQLのデータ型をMySQLのデータ型に変換します
        switch ($dataType) {
            case 'character varying':
            case 'text':
                $mysqlDataType = 'TEXT';
                break;
            case 'integer':
                $mysqlDataType = 'INT';
                break;
            case 'timestamp without time zone':
                $mysqlDataType = 'TIMESTAMP';
                break;
            case 'date':
                $mysqlDataType = 'DATE';
                break;
            default:
                $mysqlDataType = 'TEXT'; // デフォルトではTEXT型を使用
        }

        $colDefinitions[] = "`$colName` $mysqlDataType"; // カラム定義を配列に追加
    }

    $createTableSQL .= join(', ', $colDefinitions) . ");"; // CREATE TABLE文を完成させます
    $mysqlConn->exec($createTableSQL); // MySQLでテーブルを作成

    // PostgreSQLからデータを選択し、MySQLに挿入します
    $pgsqlResult = $pgsqlConn->query("SELECT * FROM \"{$table}\"");

    while ($row = $pgsqlResult->fetch(PDO::FETCH_ASSOC)) {
        // カラム名を取得
        $columns = array_keys($row);
        // 値のプレースホルダーを生成
        $placeholders = array_fill(0, count($row), '?');
        // INSERT文を組み立て
        $insertSQL = "INSERT INTO `{$table}` (`" . implode('`, `', $columns) . "`) VALUES (" . implode(', ', $placeholders) . ")";

        // MySQLデータベースへのトランザクションを開始します
        $mysqlConn->beginTransaction();
        try {
            // INSERT文を準備し、値をバインドして実行します
            $stmt = $mysqlConn->prepare($insertSQL);
            $stmt->execute(array_values($row)); // PDOStatement::executeには値の配列を渡します
            $mysqlConn->commit(); // 変更をコミットし、トランザクションを終了します
        } catch (Exception $e) {
            // エラーが発生した場合、トランザクションをロールバックします
            $mysqlConn->rollBack();
            echo "エラー: " . $e->getMessage();
        }
    }
}
?>

				
			

文字コードに気をつけて

カラム名に日本語を使ってる場合や、EUCからUTF8に移行する場合などは下記のmysqlへの接続部分を改変してください。じゃないと化けます。

				
						$mysqlConn = new PDO("mysql:host={$mysql['host']};dbname={$mysql['db']};charset=utf8mb4", $mysql['user'], $mysql['password']);