0

このクエリに問題があります。誰かがこれを修正するのを手伝ってくれることを願っています。新しいユーザーを自分のサイトに登録するときに、ユーザー名と電子メール アドレスが登録可能であることを確認しようとしています。ユーザー名はログイン テーブルから取得され、電子メール アドレスは連絡先テーブルから取得されます。ここで、指定されたユーザー名と、新しいユーザーが登録できる電子メールを確認するためのクエリを作成する必要があります。それらが利用できない場合、エラーメッセージを出力したいと思います。このクエリをこのようなものにしようとしていますが、期待どおりに機能しません。

$q = "SELECT username, email FROM login 
      INNER JOIN contact 
      WHERE login.username = '$username' OR contact.email = '$email'";

次に、このクエリを PHP で次のようにチェックしています。

$r = mysqli_query ($dbc, $q);

// Get the number of rows returned:
$rows = mysqli_num_rows($r);

if ($rows == 0) { // No problems!

   // register new user 

} else { // The email address or username is not available.

    if ($rows == 2) { // Both are taken.

    $reg_errors['email'] = 'This email address has already been registered.1';          
    $reg_errors['username'] = 'This username has already been registered.2';            

    } else { // One or both may be taken.

                // Get row:
                $row = mysqli_fetch_array($r, MYSQLI_NUM);

                if( ($row[0] == $_POST['email']) && ($row[1] == $_POST['username'])) { // Both match.
                    $reg_errors['email'] = 'This email address has already been registered.3';  
                    $reg_errors['username'] = 'This username has already been registered with this email address.4';
                } elseif ($row[0] == $_POST['email']) { // Email match.
                    $reg_errors['email'] = 'This email address has already been registered.5';                      
                } elseif ($row[1] == $_POST['username']) { // Username match.
                    $reg_errors['username'] = 'This username has already been registered.6';            
                }

} // End of $rows == 2 ELSE.

私の問題は、PHPスクリプトが常にこのコードに行くことです。ユーザー名と電子メールを個別にチェックしないクエリ。私はこのようなことを試しています..ユーザー名が利用できず、電子メールが利用可能で、電子メールが利用できず、ユーザー名が利用可能です。しかし、いつもこれに行く

if ($rows == 2) { // Both are taken.

$reg_errors['email'] = 'This email address has already been registered.1';          
$reg_errors['username'] = 'This username has already been registered.2';            

}

編集:テーブル構造..

# --------------
# Login Table 
# --------------

CREATE TABLE login (
login_id SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT,
username VARCHAR(80) NOT NULL, 
password VARBINARY(32) NOT NULL,
PRIMARY KEY (login_id),
UNIQUE(username) 
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

# --------------
# Contact Table
# --------------

CREATE TABLE contact (
contact_id SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT,
telephone VARCHAR(60) DEFAULT NULL, 
mobile CHAR(10) NOT NULL, 
email VARCHAR(80) DEFAULT NULL, 
PRIMARY KEY (contact_id),
UNIQUE (email)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
4

5 に答える 5

3

現在、クエリは、どちらか一方に 1 つの一致がある限り、両方のテーブルからすべての行を選択します。両方のテーブルから同時に一致する行を取得できます。

SELECT username FROM login WHERE username = '$username'
UNION ALL SELECT email FROM contact WHERE email = '$email'

...そして別のクエリでも。

クエリは SQL インジェクションに対して脆弱です。

于 2013-01-31T14:19:09.363 に答える
3

ON2 つのテーブルが互いにどのように関連しているかについて、関係を定義する句を指定する必要があります。

SELECT  username, email 
FROM    login 
        INNER JOIN contact 
            ON login.colname = b.colName  // change to your orignal colName
WHERE   login.username = '$username' OR 
        contact.email = '$email'

補足として、変数のSQL Injection値が外部から取得された場合、クエリは脆弱です。予防方法については、以下の記事をご覧ください。を使用すると、値を一重引用符で囲む必要がなくなります。PreparedStatements

テーブルの値をチェックせずにこれを行う別の方法はUNIQUE、テーブルの列に制約を適用することです。

ALTER TABLE login ADD CONSTRAINT tb_uq UNIQUE (username);
ALTER TABLE contact ADD CONSTRAINT tb_uq1 UNIQUE (email);

2 つの変更ステートメントが正常に実行された場合、値がその列に既に存在する場合、値を挿入することはできません。

更新 1

SELECT COUNT(*)
FROM
(
   SELECT userName as Value FROM Login
   UNION
   SELECT email as Value FROM contact
) s
WHERE VALUE IN ('$username','$email')

上記のクエリが 0 より大きい値を返す場合は、値が既に存在することを意味します。

更新 2

SELECT *
FROM
(
   SELECT userName, NULL AS email FROM Login
   UNION
   SELECT NULL AS username, email FROM contact
) s
WHERE username = '$username' OR email = '$email'
于 2013-01-31T14:19:52.733 に答える
1

すべての内部結合句には、2 つのテーブルを結合するときに適用するルールを指定する述語または「ON」条件が必要です...

クエリには、内部結合の後に「ON」句が必要です。その条件がどうあるべきかはわかりませんが、例として....

    $q = "SELECT username, email FROM login 
           INNER JOIN contact 
               On contact.username = login.userName 
           WHERE login.username = '$username' OR contact.email = '$email'";
于 2013-01-31T14:19:52.967 に答える
1

結合する列を決定する必要があるため、結合に問題があります。

たとえば、NNER JOIN contact On contact.id= login.contactId

于 2013-01-31T14:22:36.580 に答える