我对此查询有疑问,希望有人帮我解决此问题。我正在尝试检查用户名和电子邮件地址,以便在向我的网站注册新用户时进行注册。用户名来自登录表,电子邮件地址来自联系表。现在我需要进行查询以检查新用户可以注册的用户名和电子邮件。如果那些不可用,我想打印错误消息。我试图让这个问题像这样,但它没有像我期望的那样工作。
$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;
答案 0 :(得分:3)
目前,您的查询会从两个表中选择每一行,只要一个匹配一个或另一个。您可以同时从两个表中获取匹配的行:
SELECT username FROM login WHERE username = '$username'
UNION ALL SELECT email FROM contact WHERE email = '$email'
...还有单独的查询。
您的查询容易受到SQL注入攻击。
答案 1 :(得分:3)
<击> 撞击>
<击>您必须提供ON
子句,用于定义两个表彼此之间关系的关系。
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'
击> <击> 撞击>
作为旁注,如果变量的值( s )来自外部,则查询易受SQL Injection
攻击。请查看下面的文章,了解如何防止它。通过使用PreparedStatements
,您可以摆脱在值周围使用单引号。
在不检查表的值的情况下执行此操作的另一种方法是对表的列强制执行UNIQUE
约束,例如
ALTER TABLE login ADD CONSTRAINT tb_uq UNIQUE (username);
ALTER TABLE contact ADD CONSTRAINT tb_uq1 UNIQUE (email);
当两个alter语句成功执行后,如果该列已经存在,则无法插入值。
更新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'
答案 2 :(得分:2)
你真的在检查两件事。单个查询没有意义,至少不是join
。我建议改为union
:
select 'username' as exists from login
where username = '$username'
union all
select 'email' as exists from contact
where email = '$email'
这将返回一个表,其中包含一个名为exists
的列,以及一个存在的每个元素的行。如果用户名和电子邮件都存在,您将获得以下内容:
EXISTS
username
email
在运行此查询的位置,您已经知道他们输入的用户名和电子邮件是什么,因此从表中返回这些值没有意义。
正如其他人所指出的那样,如果直接从用户传递$username
和$email
,则会有很大的安全漏洞。你肯定要以某种方式处理它。
答案 3 :(得分:1)
每个内连接子句需要有一个谓词或“开”条件来指定加入两个表时要强制执行的规则...
查询在Inner Join之后需要一个“ON”子句。我不确定那个条件应该是什么,但是,作为一个例子......
$q = "SELECT username, email FROM login
INNER JOIN contact
On contact.username = login.userName
WHERE login.username = '$username' OR contact.email = '$email'";
答案 4 :(得分:1)
您的联接有问题,因为您应该确定要加入的列!
例如,NNER JOIN联系 在contact.id = login.contactId
上