【发布时间】:2019-06-21 01:47:27
【问题描述】:
我正在尝试创建一种方法来搜索客户数据库,其中一些数据(例如电话号码和电子邮件)具有一对多的关系。我有一个包含客户 ID(唯一、自动编号)、名字和姓氏的表。我有第二个表,其中包含一个电话号码,以及与该电话号码关联的客户 ID。我有第三个表,其中包含一个电子邮件地址,以及与该电子邮件地址关联的客户 ID。
这是PHP内置的查询:
$query = "SELECT *
FROM customers
LEFT OUTER JOIN phone_numbers ON customers.customer_id = phone_numbers.associated_customer
LEFT OUTER JOIN email_addresses ON customers.customer_id = email_addresses.associated_customer
WHERE first_name LIKE '%" . $_GET["fname"] . "%'
AND last_name LIKE '%" . $_GET["lname"] . "%'
AND phone_number LIKE '%" . $_GET["phone"] . "%'
AND email_address LIKE '%" . $_GET["email"] . "%'";
这样,我搜索的客户只有在他们有电话号码和电子邮件地址的情况下才会出现。如果客户有多个电话号码或电子邮件,我也会从第一个表中得到重复的结果,所以如果客户有 2 个电话号码和 2 个电子邮件,我会得到 4 个结果。
我是否正确地构建表格以实现这种一对多关系?
编辑:用于澄清的示例数据。
表 1:
╔════════════════════════════════════════╗
║ customers ║
╠═════════════╦════════════╦═════════════╣
║ customer_id ║ first_name ║ last_name ║
╠═════════════╬════════════╬═════════════╣
║ 1 ║ John ║ Doe ║
║ 2 ║ John ║ Wick ║
║ 3 ║ John ║ Cena ║
║ 4 ║ John ║ Krasinski ║
║ 5 ║ Jane ║ Doe ║
║ 6 ║ Freddie ║ Mercury ║
╚═════════════╩════════════╩═════════════╝
表 2:
╔══════════════════════════════════════════════════╗
║ phone numbers ║
╠════════════════╦═══════════════╦═════════════════╣
║ phone_number ║ associated_id ║ primary_contact ║
╠════════════════╬═══════════════╬═════════════════╣
║ 5555555555 ║ 2 ║ 0 ║
║ 6692216251 ║ 2 ║ 1 ║
║ 2025550174 ║ 3 ║ 1 ║
╚════════════════╩═══════════════╩═════════════════╝
表 3:
╔═══════════════════════════════════════════════════╗
║ email_addresses ║
╠═════════════════╦═══════════════╦═════════════════╣
║ email_address ║ associated_id ║ primary_contact ║
╠═════════════════╬═══════════════╬═════════════════╣
║ jdoe@aol.com ║ 1 ║ 1 ║
║ jwick@email.com ║ 2 ║ 1 ║
║ jwick@aol.com ║ 2 ║ 0 ║
╚═════════════════╩═══════════════╩═════════════════╝
搜索查询:
first name: "John"
last name: ""
phone number: ""
email address: ""
预期的结果是它返回名字字段中“John”的所有匹配项,并且只包括主要的联系方式:
╔═════════════╦════════════╦═════════════╦══════════════╦═════════════════╗
║ customer_id ║ first_name ║ last_name ║ phone_number ║ email_address ║
╠═════════════╬════════════╬═════════════╬══════════════╬═════════════════╣
║ 1 ║ John ║ Doe ║ ║ jdoe@aol.com ║
║ 2 ║ John ║ Wick ║ 6692216251 ║ jwick@email.com ║
║ 3 ║ John ║ Cena ║ 2025550174 ║ ║
║ 4 ║ John ║ Krasinski ║ ║ ║
╚═════════════╩════════════╩═════════════╩══════════════╩═════════════════╝
实际结果是排除了所有没有关联电话号码和电子邮件地址的结果,并且每个电话号码和每个电子邮件地址都包含一个重复项:
╔═════════════╦════════════╦═════════════╦══════════════╦═════════════════╗
║ customer_id ║ first_name ║ last_name ║ phone_number ║ email_address ║
╠═════════════╬════════════╬═════════════╬══════════════╬═════════════════╣
║ 2 ║ John ║ Wick ║ 5555555555 ║ jwick@email.com ║
║ 2 ║ John ║ Wick ║ 6692216251 ║ jwick@email.com ║
║ 2 ║ John ║ Wick ║ 5555555555 ║ jwick@aol.com ║
║ 2 ║ John ║ Wick ║ 6692216251 ║ jwick@aol.com ║
╚═════════════╩════════════╩═════════════╩══════════════╩═════════════════╝
但是,假设我的搜索查询如下:
first name: "John"
last name: ""
phone number: "5555555555"
email address: ""
预期的结果是:
╔═════════════╦════════════╦═════════════╦══════════════╦═════════════════╗
║ customer_id ║ first_name ║ last_name ║ phone_number ║ email_address ║
╠═════════════╬════════════╬═════════════╬══════════════╬═════════════════╣
║ 2 ║ John ║ Wick ║ 5555555555 ║ jwick@email.com ║
╚═════════════╩════════════╩═════════════╩══════════════╩═════════════════╝
我知道 SQL 注入攻击。我会采取措施防止它们发生,但这将是一个内部系统,所以我并不担心。
【问题讨论】:
-
您的预期输出是什么,请提供示例数据
-
您正在编写危险的查询。使用 PDO 时,请使用准备好的语句并参数化查询。如果字段是可选的,您应该动态构建查询。
-
可能你的列名发生冲突尝试列名而不是
*输出它的显示。并尝试在 where 子句中使用表对象。 -
请阅读有关 SQL 注入攻击的信息,并了解为什么将用户提供的值直接插入到 SQL 查询中而不进行清理是非常危险的。正如@user3783243 所说,你真的需要参数化这个查询。 w3schools.com/sql/sql_injection.asp
-
您使用的 DBMS 是什么?
标签: php sql search pdo left-join