У меня есть база данных SQL Server с информацией Customer
, а CustomerPhone
имеет столбец с несколькими значениями, который равен C_Phone
.
Это мой код:
if (!empty($_GET['customer_id'])){
// 'id' input from the user
$id = $_GET['customer_id'];
// Customer Information
$sql = "SELECT Customer.C_Code, C_FirstName, C_LastName, C_Email, C_HomeAddress, C_OfficeAddress, C_Phone
FROM Customer, CustomerPhone
WHERE Customer.C_code = CustomerPhone.C_code and Customer.C_code = $id;";
$query = sqlsrv_query($conn, $sql);
$row = sqlsrv_fetch_array($query);
if (!empty($row)) {
echo "
<div class=\"card\" style=\"width: 25rem; margin-left: auto; margin-right: auto;\">
<div class=\"card-body\">
<h5 class=\"card-title\">Customer Information</h5>";
echo "<p class=\"card-text\">C_code: " . $row['C_Code'] . "</p>";
echo "<p class=\"card-text\">C_Name: " . $row['C_FirstName'] . " " . $row['C_LastName'] . "</p>";
echo "<p class=\"card-text\">C_Email: " . $row['C_Email'] . "</p>";
echo "<p class=\"card-text\">C_HomeAddress: " . $row['C_HomeAddress'] . "</p>";
echo "<p class=\"card-text\">C_OfficeAddress: " . $row['C_OfficeAddress'] . "</p>";
echo "<p class=\"card-text\">C_Phone: ";
while($row = sqlsrv_fetch_array($query))
{
echo $row['C_Phone'] . "<br>";
}
echo "</p>";
echo "
</div>
</div>";
}
Это результат, который я получил. Как я могу напечатать второй номер телефона под первым?
Если я выполню приведенный выше SQL-запрос в SSMS, я получу этот результат с Customer.C_Code = 7
:
@TimMorton спасибо, что указали на проблему SQL-инъекций в моем коде, раньше я этого не замечал.
Есть как минимум два пути, по которым вы можете пойти. Вам придется адаптировать эти идеи к вашим функциям подключения к базе данных, так как у меня нет опыта работы с базами данных Microsoft.
В каждой итерации информации о клиенте выполняйте второй запрос CustomerPhone, используя C_code, полученный от Customer. Как упоминалось в комментариях, используйте оператор while
для повторения результатов.
while($row=sqlsrv_fetch_array($query) {
Необходимо соблюдать осторожность, чтобы внутренний запрос не затмил внешний!
Это включает в себя создание более сложного запроса. Вы можете group by
поле и база данных объединяет поля:
SELECT
Customer.C_Code, C_FirstName, C_LastName,
C_Email, C_HomeAddress, C_OfficeAddress,
string_agg(C_Phone, ', ') AS phone
FROM Customer
INNER JOIN CustomerPhone ON Customer.C_code = CustomerPhone.C_code
WHERE
Customer.C_code = ?
GROUP BY Customer.C_code
(обратите внимание, что в некоторых базах данных требуется, чтобы каждое поле использовалось в предложении group by
)
(примечание 2. Это параметризованный запрос, который следует использовать с командой подготовки. См. документацию по подготовленным операторам. Это правильный способ использования значений в запросе)
Как показано, они будут перечислены как csv. Вы также можете использовать <br>
, чтобы разделить их вместо запятой.
Причина такого неожиданного поведения заключается в том, что вам нужно вывести номер телефона клиента из первой выбранной строки (echo "<p class=\"card-text\">C_Phone: ". $row['C_Phone'] . "<br>";
вместо echo "<p class=\"card-text\">C_Phone: ";
).
Вы также можете рассмотреть следующее:
JOIN
.Следующий пример, основанный на вашем коде, является возможным решением вашей проблемы:
if (!empty($_GET['customer_id'])) {
// Customer Information
$sql = "
SELECT c.C_Code, c.C_FirstName, c.C_LastName, c.C_Email, c.C_HomeAddress, c.C_OfficeAddress, p.C_Phone
FROM Customer c
JOIN CustomerPhone p ON c.C_code = p.C_code
WHERE c.C_code = ?;
";
$params = array($_GET['customer_id']);
$query = sqlsrv_query($conn, $sql, $params);
if ($query === false) {
echo "Error (sqlsrv_query): ".print_r(sqlsrv_errors(), true);
exit;
}
// fetch data
$row = sqlsrv_fetch_array($query);
if (!empty($row)) {
echo "
<div class=\"card\" style=\"width: 25rem; margin-left: auto; margin-right: auto;\">
<div class=\"card-body\">
<h5 class=\"card-title\">Customer Information</h5>";
echo "<p class=\"card-text\">C_code: " . $row['C_Code'] . "</p>";
echo "<p class=\"card-text\">C_Name: " . $row['C_FirstName'] . " " . $row['C_LastName'] . "</p>";
echo "<p class=\"card-text\">C_Email: " . $row['C_Email'] . "</p>";
echo "<p class=\"card-text\">C_HomeAddress: " . $row['C_HomeAddress'] . "</p>";
echo "<p class=\"card-text\">C_OfficeAddress: " . $row['C_OfficeAddress'] . "</p>";
echo "<p class=\"card-text\">C_Phone: ". $row['C_Phone'] . "<br>";
while ($row = sqlsrv_fetch_array($query))
{
echo $row['C_Phone'] . "<br>";
}
echo "</p>";
echo "
</div>
</div>";
}
}
Главное - ваш код уязвим для SQL-инъекций. Используйте подготовленные операторы каждый раз, когда переменная должна быть помещена в запрос. Незначительная вещь - «столбец с несколькими значениями» неверен. То, что у вас есть, - это отношение один ко многим. Между ними огромная разница; первое - кошмар, а второе - правильно. К счастью, похоже, что ваши таблицы верны. Если бы вы использовали
while ($row=sqlsrv_fetch_array)
вместоif
, вы бы получили обе строки. Чтобы получить желаемый результат, вы должны либо использовать вложенные запросы, либо использовать агрегатные функции в вашем sql.