[模擬問題] PHP7初級 – 情報の保存:データベース(エバンジェリスト三雲勇二からの出題)

PHP7初級試験 模擬問題 – 出題範囲: 情報の保存:データベース からの出題となります。
受験を考えているあなたも、試験を合格したあなたも、ぜひチャレンジしてみてください!

目次

問題

次の選択肢のなかで、正しいものはどれでしょう? (1つ選択)

  1. データベースは製品により SQL の書き方は必ず同じ
  2. PHP からデータベースに接続するには、DSN に PDO を設定して接続する
  3. SQL でデータを操作する SELECT, UPDATE, INSERT, DELETE 文にはテーブルを指定する場合に必ず FROM 句が必要である
  4. PDO で SQL の SELECT の実行結果の行数を取得するには rowCount() メソッドを使用するとよい
  5. SQL をプログラム内で組み立てる際はプリペアドステートメントのプレースホルダを利用するとよい

解答と解説は下にスクロールしてください





























解答

正解は 5. です。

解説

1. データベースは製品により SQL の書き方は必ず同じ

SQL の書き方は概ね同じではありますが、製品ごとに異なることがあります。

SQL の標準規格としては、ANSI や ISO などで定められたものもありますが、各データベース製品ごとに SQL が独自に拡張されてきた歴史もあります。

Web で情報を調べる際には、どの製品の SQL の構文の話か確認する必要があります。
この際には、バージョンによっても構文が変わることもあるので、合わせて確認するようにしてください。
SQL の書き方を確認する際には、各データベース製品の公式ドキュメントにも必ず目を通すようにもしましょう。

【試験合格後もステップアップ!】

SQL はすこし特徴的な構文なことも相まって、初心者には苦手意識を持たれることの多い言語です。
しかし、SQL は昔から構文がほとんど変わらないにもかかわらず、現在でも第一線で活躍する息の長い言語です。
一度覚えてしまうと長く使用できるので、ぜひ苦手意識を持たずに習得を目指してみてください。

データベースの中でもリレーショナルデータベースと呼ばれるものは数学の集合論と深い関係がありますので、集合論をきちんと理解することも併せておすすめします。

2. PHP からデータベースに接続するには、DSN に PDO を設定して接続する

PDO に DSN を設定して接続します。

DSN はデータソース名 (Data Sourse Name) の頭文字です。 PDO では接続するデータベースの種類や接続に関するパラメータを DSN で指定します。

【データベースの接続例】

  • データベースの種類: MySQL
  • ホスト名: localhost (自分自身のサーバー)
  • データベース名: testdbname
  • ユーザー名: testuser
  • パスワード: testpass
$db = new PDO('mysql:host=localhost;dbname=testdbname', 'testuser', 'testpass');

また、データベース接続時にはデータベースが動作していないことなどが考えられますので、接続時には必ずエラー処理が必要になります。

【試験合格後もステップアップ!】

上記の DSN には文字コードの指定がされていません。
文字コード UTF-8 をセットするには DSN に `charset=utf8` を追加します。

$db = new PDO(‘mysql:host=localhost;dbname=testdbname;charset=utf8’, ‘testuser’, ‘testpass’);

文字コードは全てにおいてできる限り UTF-8 に統一することを意識したほうが良いです。
理由は、過去に文字コード起因で「5C 問題による SQL インジェクション」が発生する問題がありました。
ShiftJIS の 2 バイト目が 5C になる「ソ」「表」「能」「申」「十」などの文字が原因で SQL インジェクションが発生するという、まず普通には認識できないであろう問題です。
現在この問題は修正されておりますが、そもそも文字コードが入力と内部と出力のそれぞれで別のものが使われていたことが大きな原因でした。

データベースやファイルなど PHP に他のシステムからデータを参照する際には、入力・内部・出力それぞれ UTF-8 にできる限り統一していることを改めて意識しておくことが重要です。

3. SQL でデータを操作する SELECT, UPDATE, INSERT, DELETE 文にはテーブルを指定する場合に必ず FROM 句が必要である

UPDATE, INSERT 文では FROM 句は必須ではありません。

FROM 句には基本的にテーブルやビュー、サブクエリなどを指定する構文となります。 UPDATE 文でテーブルなどを指定する場合には UPDATE テーブル名 SET 〜 のように FROM 句をつけることなく指定します。

INSERT 文でテーブルなどを指定する場合には INSERT INTO テーブル名 (フィールド...) VALUES 〜 のように FROM 句をつけることなく指定します。

【試験合格後もステップアップ!】

UPDATE, INSERT 文で FROM 句が全く使えないわけではありません。
別のテーブルやビューを基に UPDATE, INSERT を行う場合には使用することもあります。

また、SELECT 文でも FROM 句を使用しない場合もあります。

SELECT 60 * 60 * 24;

こちらは一日の秒数を結果として返す SQL 文になります。
ただし、MySQL や PostgreSQL では実行が可能ですが、Oracle では FROM 句の省略はできないため実行できません。

このように先の 1. でも書いたとおり、基本的な FROM 句でもデータベース製品によって SQL の違いがありますので注意してください。

4. PDO で SQL の SELECT の実行結果の行数を取得するには rowCount() メソッドを使用するとよい

rowCount() で取得するのは、直近の UPDATE, INSERT, DELETE 文の実行結果で作用した件数を取得するために使用します。

SELECT 文に rowCount() メソッドで行数を取れるケースもありますが、この動作は保証されていません。したがって使用すべきではありません。

【試験合格後もステップアップ!】

SELECT 文で実行結果の行数を取得する場合は、以下の方法が考えられます。

1. SQLCount() 関数の実行結果を取得
2. fetchAll() で全レコードを配列に取得したうえで、配列の行数を取得
3. foreach でイテレータを回している間にカウンタ変数で数える

総件数を表示する目的に応じて使い分けてください。
2.の手法はメモリにデータをすべて展開するため、小さいデータ量でない限り使用は控えたほうがよいでしょう。

実際の例では、一般的に SQL で実行するほうがマシン上の実行速度やメモリ効率が高いことが多いため、1.の手法を用いつことが多いです。 画面に表示する20件などのデータを取ってくる SELECT * FROM 〜 LIMIT 〜 OFFSET 〜 文と、総件数を取得する SELECT count(id) AS total FROM 〜 のような文に分けるほうがコンピュータに負荷がかかりにくくよく使われます。

5. SQL をプログラム内で組み立てる際はプリペアドステートメントのプレースホルダを利用するとよい

選択肢のとおりです。

プリペアドステートメントとは SQL 文を一種のテンプレートとして用意するようなものです。
例を上げると、検索する日時の期間だけ変えたい SQL 文などで利用します。
このとき変えたい部分(上記例では日時の期間)にプレースホルダとよばれる特殊な文字を当て込み、実際に SQL 文を実行するときに置き換えます。
一般的にプレースホルダには ? を使うことが多いです。

プリペアドステートメントを利用するメリットは大きく2つあります。

  • 1点目は、事前に SQL 文を用意しておくことで処理の高速化が望めます。
  • 2点目は、実行時にプレースホルダに入れ込まれる値が内部的にエスケープ処理されます。

【試験合格後もステップアップ!】

SQL 文をプログラム内で作成するときに、文字列に変数などを組み合わせて作成することもできますが、SQL インジェクションというセキュリティ上の脆弱性が生まれやすいためおすすめしません。

SQL インジェクションとは、入力される値をそのまま SQL 文作成に利用してしまい、本来想定しなかった SQL を実行させて攻撃する手法です。
この攻撃が成立してしまうと、データベースへの攻撃のため、データがすべて出力させ情報の漏洩につながったり、データの変更や削除を実行させられデータを改ざんされるなど、どれも致命的な攻撃を成立させることが理論上可能となります。

これを防ぐためには、プリペアドステートメントを利用して事前に SQL を組み立てておき、入力されるプレースホルダに入れる変数のサニタイジングをしっかりと行うことが必要です。

プリペアドステートメント側でもエスケープ処理はされますが、できる限り事前に自分でプレースホルダに入れる変数をサニタイジングする意識を持ちましょう。
SQL インジェクションに限らず、データを事前に検証することはセキュリティ面のみならずバグを発生させない面でも非常に重要です。

試験の情報

PHP7初級試験 の詳細およびキャンペーン情報はこちら
https://www.phpexam.jp/summary/novice7/

今回の内容は、セキュリティや脆弱性に直結する項目も含まれておりますのできちんと押さえておいてください。
PHP 7 初級レベルではウェブ・セキュリティの基本を押さえただけにとどまりますので、実務ではもう少し深く知っておく必要があります。
ウェブ・セキュリティの名著として知られる徳丸浩氏による「体系的に学ぶ 安全なWebアプリケーションの作り方 第2版」では、より丁寧で詳細にウェブ・セキュリティについて学ぶことができますのでおすすめです。
上記の本は「ウェブ・セキュリティ基礎試験(通称:徳丸基礎試験)」の主教材でもあります。

ウェブ・セキュリティ基礎試験(徳丸基礎試験)
https://www.phpexam.jp/tokumarubasic/

徳丸基礎試験は Python や Ruby on Rails などの PHP 以外の言語で Web アプリケーションを作成されている方にも非常に有益な試験となっております。
知識としても実務としても PHP 関わらず幅広く使えるため、ウェブに関わるエンジニアに私が一番オススメしている試験が「徳丸基礎試験」だったりします。
PHP 7 初級を合格した方は、徳丸基礎試験もぜひチャレンジしてみてください!

模擬問題作成及び解説

三雲 勇二
プライム・ストラテジー株式会社 所属。PHP 技術者認定機構で実施している 7 試験 ( PHP8上級 / PHP5上級 / PHP7初級 / PHP5初級 / 徳丸実務 / 徳丸基礎 / KUSANAGI for WordPress ) 含め多数の試験に合格。ペチゾーをデスク周りにおいて日々お仕事しています。
Facebook: facebook.com/yuji.mikumo
Twitter: @maikeru

この記事が気に入ったら
いいね または フォローしてね!

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!
目次