SQLiteで躓いた時の発見から。MySQLのCREATE TABLEを使いまわせる書き方のように見えたのですが・・・
見出し
接続と、テーブル一覧表示部分
成否だけでは確認も難があるので、まずは接続と、テーブル一覧の出力です。
接続部分
try{ $pdo = new PDO( "sqlite:".dirname(__FILE__).'/dbfiles/sample.sqlite3', null, null, array( PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION ,PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC ) ); }catch (PDOException $e) { echo 'Connection failed: ' . $e->getMessage()."\n"; exit; }
テーブル一覧部分
$sql = "SELECT name,sql FROM `sqlite_master`"; $result = $pdo->query($sql)->fetchAll(PDO::FETCH_ASSOC); echo "<h2>テーブル一覧</h2>"; echo "<pre>"; var_dump($result); echo "</pre>"; echo "<hr>\n";
テーブルを作ってみる
INTで書くと失敗
AUTOINCREMENTと書かなければならないことに要注意である点、派生的な型もINT等はINTEGER、VARCHARなどはTEXTとして扱ってくれるという前提知識があったので、MySQLとの流用前提の型名で書いてみたのですが・・・
$sql = "CREATE TABLE IF NOT EXISTS `sample` ( `num` INT PRIMARY KEY AUTOINCREMENT ,`name` VARCHAR(50) ,`age` INT )"; $result = $pdo->exec($sql);
SQLSTATE[HY000]: General error: 1 AUTOINCREMENT is only allowed on an INTEGER PRIMARY KEY
結果はエラー。PRIMARY KEYにできるのはINTEGERですが、INTEGER扱いされた別の型名は対象外のようです。
INTEGERにすると成功
まずは素直に当該列だけINTEGERにすると無事動きました。
$sql = "CREATE TABLE IF NOT EXISTS `sample0` ( `num` INTEGER PRIMARY KEY AUTOINCREMENT ,`name` VARCHAR(50) ,`age` INT )"; $result = $pdo->exec($sql);
INTと後置にするとエラーになったが?
MySQLの場合、型によってプライマリキー設定を後置しないといけない場合があるので、もしかして後置すれば変換結果で判定してくれたりしないか?ということで、INTに戻し、後置で試しました。
$sql = "CREATE TABLE IF NOT EXISTS `sample` ( `num` INT AUTOINCREMENT ,`name` VARCHAR(50) ,`age` INT , PRIMARY KEY (`num`) )"; $result = $pdo->exec($sql);
SQLSTATE[HY000]: General error: 1 near “AUTOINCREMENT”: syntax error
エラーなのですが内容は違い、なぜかAUTOINCREMENTに問題があるとの結果です。なお、ちゃんとINTEGERにしてもアウトです。
INTとAUTO_INCREMENTでも作成成功
まさかとは思いつつ、AUTO_INCREMENTにしてみます。すると・・・
$sql = "CREATE TABLE IF NOT EXISTS `sample` ( `num` INT AUTO_INCREMENT ,`name` VARCHAR(50) ,`age` INT , PRIMARY KEY (`num`) )"; $result = $pdo->exec($sql);
エラーにならずにテーブル作成に成功しました。
MySQLの時もプライマリキー後に書くよう癖をつけておくと、SQLiteでもそのまま使える、と思ったのですが・・・
実際にINSERTしてみると
ランダムINSERTとテーブル表示部分
$tbl_name = "sample"; //INSERT $in_name = "user-".rand(1000,9999); $in_age = rand(18,60); $sql = "INSERT INTO `{$tbl_name}` (`name`, `age`) VALUES(:name, :age)"; $stmt = $pdo->prepare($sql);//実行・結果取得 $stmt->bindValue(':name', $in_name, PDO::PARAM_STR); $stmt->bindValue(':age', $in_age, PDO::PARAM_INT); $stmt->execute(); //テーブル内容表示---------- $sql = "SELECT * FROM `{$tbl_name}`"; $table_data = $pdo->query($sql)->fetchAll(PDO::FETCH_ASSOC); } ?> <h2>テーブル「<?php echo $tbl_name?>」の内容</h2> <table> <tr><th>NUMBER</th><th>NAME</th><th>AGE</th></tr> <?php foreach($table_data as $row):?> <tr> <td><?php echo $row['num'];?></td> <td><?php echo $row['name'];?></td> <td><?php echo $row['age'];?></td> </tr> <?php endforeach;?>
結果は
NUMBER | NAME | AGE |
---|---|---|
user-1929 | 45 | |
user-4317 | 56 | |
user-2775 | 53 |
作成時エラーになっていなかったものの、numはAUTO INCREMENTされていませんでした。
「後ろに置くとAUTO_INCREMENTにしないとエラーがでる」のは納得がいかない現象ですが、結局PRIMARY KEYの後置はできない、「INTEGER」とアンダーバー無しの「AUTOINCREMENT」でないといけない。という形で、都合よくSQL文を使いまわすことはできないようです。