MySQLデータベースの操作

PHP

MySQLデータベースの操作

MySQL Server 5.7.16 / PHP 7.3.11 / macOS 10.15.7
PHPのスクリプトで MySQLデータベースを SQLコマンドにより操作する手順について説明する。

使用するデータベース

データベース:practice
テーブル:test

データベースと接続する

PDO(PHP Data Objects)によりデータベースに接続する。データベースを利用するPHPスクリプトは、db_connect関数を実行し、データベースと接続した PODオブジェクトを取得する。
後述する静的プレースホルダを使用するときには、ATTR_EMULATE_PREPARES属性を falseにしておくことが推奨されている。trueを指定しても静的プレースホルダは使用できるが、SQLインジェクション回避のためにはこちらの方が色々と望ましいようだ。

SELECT文

queryメソッドで SQL文を実行する。SELECTの結果は、fetchAll関数により行の配列として取得できる。行はフィールド名をキーとした連想配列になる。

INSERT文/UPDATE文

指定したキーのレコードがあれば更新し、なければ追加する。

静的プレースホルダを使用する

次の例はレコードを SELECTする処理である。想定してるのは指定したidのレコードのみ抽出する処理であるが、例えば idに「"1 OR 1=1"」を指定すると全てのレコードが抽出できてしまう。Webアプリケーションにおいて、パラメータとしてこのような送信ができると、セキュリティホールとして働いてしまう。これがいわゆる SQLインジェクションと呼ぶもので非常にまずい。
静的プレースホルダを使用することによって SQLインジェクションを回避することができる。
これは、SQL文の中の変数 (*1) を PHPの bindValue関数を経由て置換するものである。関数の第1引数には SQL文の中の変数、第2引数には第1引数の変数を置き換えるスクリプトの中の変数、第3引数にはデータ型を指定る。変数はここで指定した型に変換される。(暗黙的な型変換ができる場合はこの引数を指定しなくても構わないようだ。
(*1) フィールドの値のことであり、SQLステートメントやテーブル名や列名は対象外である。
このコードで$id="1 OR 1=1;" を指定した場合、 id=1のレコードのみが抽出され全レコードが抽出されることはない。(中のメカニズムはよくわからないが対応はできているようだ)

ローカルディスクの CSVファイルからデータをテーブルにインポートする

SQLの LOAD DATA文によりローカルファイルからデータをテーブルにインポートすることができる。
MySQLサーバ側の設定(デフォルトでは ONになっている)
設定を変更する方法
MySQLサーバの設定をローカルファイルに出力する方法
PHPスクリプト
PDOオプション MYSQL_ATTR_LOCAL_INFILEを設定する。(なお、setAttributeメソッドでオプションを設定しても、なぜか有効にならない。)
CSVファイル
PHP備忘録
php.iniファイルの場所を探すコマンド
macOSにバンドルされている php7には、php.iniが存在しないが、PHPは特に問題なく動作しているようだ。設定が必要になったときは /etc/php.inidefault をリネームして使えばいいのだろうか?