質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.47%

  • SQL

    2475questions

    SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

ある値がデータベースに登録済かどうかをチェックする

解決済

回答 4

投稿 編集

  • 評価
  • クリップ 3
  • VIEW 10K+

kuzurotto

score 388

「ログインする際の重複アドレスがないかどうか」

を昨日からずっとやってるんですが、解決しないです。

ある値がデータベースに登録済かどうかをチェックするには、データ(アドレスのカラム)の行数
をカウントするSQL文を使用する
らしいんですが、、、

知りたいのは行数のカウントじゃなくて、登録されているアドレスそのものなのにどういうことなんだ?ってなって頭がぐるぐる回ってます...

「行数のカウントを取得するということは・・・・・」

「つまり・・・・・」

「したがって、・・・・・・」

その場だけの記述を覚えても理解しないと応用できないので、分かりやすく解説頂けると助かります。

sql文はPDOではなくsqliを使っています。
参考書の記述と解説がほとんどsqliでPDOではない為です。

宜しくお願いいたします。

≪追記≫

思った以上に回答してくださる方がいらっしゃいますので、質問を具体的にする為、サンプルのソースを追記します。

冒頭で、「ログインする際の重複アドレスがないかどうか」と記載しておりますが、誤りです。

「新規登録する際の重複アドレスがないかどうか」です。

宜しくお願いします。

// 重複アカウントのチェック
    if (empty($error)) {
        $sql = sprintf('SELECT COUNT(*) AS cnt FROM members WHERE email="%s"',
            mysqli_real_escape_string($db, $_POST['email'])
        );
        $record = mysqli_query($db, $sql) or die(mysqli_error($db));
        $table = mysqli_fetch_assoc($record);
        if ($table['cnt'] > 0) {
            $error['email'] = 'duplicate';
        }
    }


<input type="text" name="email" size="35" maxlength="255" value="<?php echo htmlspecialchars($_POST['email'], ENT_QUOTES, 'UTF-8'); ?>" />
            <?php if ($error['email'] == 'blank'): ?>
            <p class="error">* メールアドレスを入力してください</p>
            <?php endif; ?>
            <?php if ($error['email'] == 'duplicate'): ?>
            <p class="error">* 指定されたメールアドレスはすでに登録されています</p>
            <?php endif; ?>
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 4

checkベストアンサー

+2

useridに「abc」という登録が既にあるかどうか確認するのに
select count(*) from usertbl where userid = 'abc'
とすれば、存在すれば1以上、無ければ0が出力されるので、プログラム上でture/falseのように使えて便利ということだと思いますよ。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/05/16 17:46

    回答ありがとうございます。

    where userid = 'abc'

    この'abc'の部分が入力されるアドレス
    すなわち、$_REQUEST[email]なら辻褄は会うのですが、サンプルソースではこのようになっています。
    ,,,
    // 重複アカウントのチェック
    if (empty($error)) {
    $sql = sprintf('SELECT COUNT(*) AS cnt FROM members WHERE email="%s"',
    mysqli_real_escape_string($db, $_POST['email'])
    );
    $record = mysqli_query($db, $sql) or die(mysqli_error($db));
    $table = mysqli_fetch_assoc($record);
    if ($table['cnt'] > 0) {
    $error['email'] = 'duplicate';
    }
    }


    <input type="text" name="email" size="35" maxlength="255" value="<?php echo htmlspecialchars($_POST['email'], ENT_QUOTES, 'UTF-8'); ?>" />
    <?php if ($error['email'] == 'blank'): ?>
    <p class="error">* メールアドレスを入力してください</p>
    <?php endif; ?>
    <?php if ($error['email'] == 'duplicate'): ?>
    <p class="error">* 指定されたメールアドレスはすでに登録されています</p>
    <?php endif; ?>
    ,,,

    キャンセル

  • 2016/05/16 17:52

    >>$_REQUEST
    >>$_GET、 $_POST そして $_COOKIE の内容をまとめた連想配列です。
    http://php.net/manual/ja/reserved.variables.request.php

    サンプルソースではformから送られてくる想定のようですね。
    それでmembersテーブルのemail要素に「$_POST['email']」と同じ値が存在すればcntに1以上、無ければ0が出力されると思います。

    それを「if ($table['cnt'] > 0) 」で判定していますね。

    キャンセル

  • 2016/05/16 17:56

    sprintf関数とmysqli_real_escape_stringが入っているため混乱されているのかもしれませんが最終的に生成されるsql文は

    SELECT COUNT(*) AS cnt FROM members WHERE email="POSTされたメールアドレス"

    になりますよ

    キャンセル

  • 2016/05/17 00:17

    回答ありがとうございます。

    SELECT COUNT(*) AS cnt FROM members WHERE email="POSTされたメールアドレス"

    これを知れただけでもかなり進歩です。


    email="%s"',はなんなのでしょう?

    ,で区切られているのでなんなんだろうと思ってましたが単純に

    WHERE email=mysqli_real_escape_string($db, $_POST['email'])

    ではダメなのでしょうか?

    キャンセル

  • 2016/05/17 04:12

    email="%s"
    に関してはsprintf関数を調べてみるのがいいと思います。

    sprintfを使わない場合
    $sql='(略)WHERE email="'. mysqli_real_escape_string($db, $_POST['email']). '"';
    とする必要があります。
    whereに指定するパラメータが今回は1つだけなのでこれでもいいのですが、パラメータが増えるほど可読性が下がるのでこうなっているのだと思います。

    ただしmysqliならbind_paramを使うべきですので質問の内容とかなりずれてしまいますが http://php.net/manual/ja/mysqli.prepare.php や「mysqli 手続き側」で検索してみてmysqli自体の使い方をきちんと調べた方がよさそうですね

    キャンセル

+1

SQLでWHEREに判定したい条件を書いて、とりあえず判定は無視してSELECTするとします。すると、

  • データがある時→ヒットしたデータが1行以上返ってくる
  • データがない時→1件もマッチしないので、結果は0行

ということになるので、「条件を満たすデータがあるか」はすなわち、「SELECTして1行以上取れるか」ということと同値になります。

行数さえわかればいいので、SELECT 1 FROM テーブル名 WHERE 条件 LIMIT 1のように実質のデータを取ってこずに結果セットの行数だけ別途で調べるのもありですし、COUNT(*)で行数を数えてしまうのも、状況によっては便利です。

なお、「重複したデータをDBに入れない」ためには、UNIQUEインデックスを使いましょう。アプリケーションレベルで対応するより楽で確実です(ほぼ同時に同じ値を書き込もうとするような場合にも防いでくれます)。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/05/16 18:04

    回答ありがとうございます。

    UNIQUEインデックスの応用もどこかで見かけましたが、例外をcatchする方法が分からないのです...。

    キャンセル

0

例えば下記のようなテーブルがあった場合。

test_table
email,name
a@test.com, a
b@test.com, b
c@test.com, c

仮にb@test.comが登録されているか確認したいということですよね?
という前提で話を進めると、test_table内にb@test.comが何件あるかで判断がつきますね。
上記テーブル例では登録されているので1件になります。
次に様に登録されていない場合、

test_table
email,name
a@test.com, a
c@test.com, c

0件になります。
ということで件数を数えれば登録済みかどうかの判断がつくということになります。

select count(*) from test_table where email='b@test.com'

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/05/16 17:53

    回答ありがとうございます。

    select count(*) from test_table where email='b@test.com'

    この部分は辻褄として理解させていただきました。

    実際はこのようなサンプルになっています。

    sprintf('SELECT COUNT(*) AS cnt FROM members WHERE email="%s"',
    mysqli_real_escape_string($db, $_POST['email'])
    );

    次に分からないことは以下です。

    ・sprintfは書式を整えるためのファンクションというのは分かるけど、そのファンクションが何故ここで使われるのか?

    ・上記ではsprintf(DBから情報を取り出す条件,POST送信内容)のような使い方をしているように見えるのですが、書式を整えるためのファンクションだったのではないのか?

    というところでぐるぐる回ってます...

    キャンセル

  • 2016/05/17 00:20

    sprintfの部分に関してはhirohiroさんとのやり取りの中にも解説がありますが、ここでも書いておきます。
    sprintfは仰るとおり、書式を整える関数です。
    書式は sprintf( フォーマット, 値, ... ) で、書式が整えられた文字列が返却されます。
    例えば、sprintf( "email=%s", "b@test.com" ); であれば、戻り値は "email=b@test.com" となります。
    ご提示のコードでは、sprintfの引数は、'SELECT~' と mysql_real~ の2つです。
    'SELECT ~ "%s"' の %s の部分が、mysql_real~ の値に置き換わります。
    mysql_real~は何をしているかというと、詳細はマニュアルを参照してください。
    https://secure.php.net/manual/ja/mysqli.real-escape-string.php
    「接続の現在の文字セットを考慮して、SQL 文で使用する文字列の特殊文字をエスケープする」とあります。
    データベースの接続情報にあわせて、文字列をうまいことやってくれる、程度に考えて良いでしょう。
    結果、sprintfは、
    SELECT COUNT(*) AS cnt FROM members WHERE email="b@test.com"
    というクエリ文字列を生成し返却します。
    それを $sql で受け取り、mysqli_query関数で投げるという処理になっていますね。

    キャンセル

0

「ログインする際の重複アドレスがないかどうか」

ですが重複アドレスの確認が必要になるのはログイン時ではなくユーザー登録時ではないでしょうか。

ログインの際に必要になる動作はメールアドレス(ユーザーID)からパスワード等のデータを取得するといった流れになるかと思います。

ユーザー登録時でしたら重複を調べる際にユーザーが入力したメールアドレスで検索を行うと思います。
つまりDBからメールアドレスを取得するまでもなく既に確認したいメールアドレスは判明しているわけです。

判明しているメールアドレスを再度DBから取得しても何も意味はありませんので、検索するメールアドレスを含むレコードの件数が0か1(または1以上)かがわかれば「そのメールアドレスは既に使用されています。」という判断が下せるということになります。

いずれの場合でもメールアドレスを元にデータを検索する以上、メールアドレスを取得する必要はないかと思います。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/05/16 17:55

    回答ありがとうございます。

    ログインする際ではなく新規登録する際でした。

    具体的なソースを追記しております。

    宜しくお願いいたします。

    キャンセル

  • 2016/05/16 17:57 編集

    回答ありがとうございます。

    ログインではなく新規登録時の話でした。すみません。

    具体的なソースを追記しました。

    宜しくお願いいたします。

    キャンセル

関連した質問

同じタグがついた質問を見る

  • SQL

    2475questions

    SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。