MySQLデータベースを生成する場合、CREATE TABLE IF NOT EXISTS
を使うと、作成済みのテーブルを作ろうとするエラーを防げます。しかし、その後のスクリプトの処理が面倒になるっぽいです。
元ネタはPHP逆引きレシピ 第2版 (PROGRAMMER’S RECiPE)のレシピ270です。コードのライセンスは修正BSDです。
$sql = "CREATE TABLE IF NOT EXISTS example ( id INT(11) NOT NULL auto_increment PRIMARY KEY, message TEXT ) DEFAULT CHARSET=utf8"; try { $db = new PDO($dsn,$dbUser,$dbPass); $db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false); $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $db->query($sql); echo 'Table created!'; } catch (PDOException $e) { echo htmlspecialchars($e->getMessage(),ENT_QUOTES,'UTF-8'); }
テーブルを作成するSQLを実行するスクリプトです。テーブルexampleが無ければ作成し、Table created!
を出力します。
では、テーブルexampleがある場合はどうなるでしょうか。SQL内にCREATE TABLE IF NOT EXISTS
があります。これは「テーブルが無い場合は作成しなさい」という命令なので、実行すると「テーブルがあるので何もしなかったよ(エラーではないよ)」と返ってきます。そうするとスクリプトは正常に実行されて、(実際には何もしていないのに)Table created!
を出力します。
db->query($sql);
の結果が正常終了となると、スクリプト側での判定(テーブルを作ったのか/テーブル作成済みで何もしなかったのか)は難しそうです。テーブル作成後に初期データ流し込み、という処理を書いた場合、このコードを二回実行すると、テーブル作成は一回だけですが初期データが二回挿入されます。この辺、うまく処理できると嬉しいのですが。
なお、CREATE TABLE
だけを記述した場合は、echo htmlspecialchars($e->getMessage(),ENT_QUOTES,'UTF-8');
が
SQLSTATE[42S01]: Base table or view already exists: 1050 Table 'example' already exists
というエラーを表示します。なのでテーブルが既に存在している場合の処理を変える事ができます。だからといって、わざわざIF NOT EXISTS
を外すのもイマイチかな、と思います。