【问题标题】:How to print multiple value column in PHP如何在 PHP 中打印多值列
【发布时间】:2020-12-10 01:32:07
【问题描述】:

我有一个关于 Customer 信息的 SQL Server 数据库,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>";
    }

这是我得到的结果。如何在第一个电话号码下打印第二个电话号码?

如果我在 SSMS 上运行上面的 SQL 查询,我会得到 Customer.C_Code = 7 的结果:

【问题讨论】:

  • 主要问题 - 您的代码容易受到 sql 注入的影响。每当需要将变量放入查询中时,请使用准备好的语句。 小事 - “多值列”不正确。你所拥有的是一对多的关系。两者之间有很大的不同;前者是一场噩梦,后者是正确的。幸运的是,看起来您的表格是正确的。如果您使用while ($row=sqlsrv_fetch_array) 而不是if,您将得到两行。要获得您想要的结果,您必须在 sql 中使用嵌套查询或使用聚合函数。
  • @TimMorton 感谢您指出我的代码中的 SQL 注入问题,我之前没有注意到。

标签: php sql-server sqlsrv


【解决方案1】:

这种意外行为的原因是您需要从第一个获取的行中回显客户电话(echo "&lt;p class=\"card-text\"&gt;C_Phone: ". $row['C_Phone'] . "&lt;br&gt;"; 而不是echo "&lt;p class=\"card-text\"&gt;C_Phone: ";)。

您还可以考虑以下几点:

  • 使用明确的JOIN 语法。
  • 使用参数化查询。正如documentation 中提到的,sqlsrv_query 函数非常适合一次性查询,并且应该是执行查询的默认选择,除非有特殊情况,并且 sqlsrv_query 函数同时进行语句准备和语句执行,并且可以用于执行参数化查询

以下示例基于您的代码,是您问题的可能解决方案:

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>";
    }
}

【讨论】:

    【解决方案2】:

    您至少可以选择两条路线。您必须将这些想法适应您的数据库连接功能,因为我没有使用 microsoft 数据库的经验

    嵌套循环

    在客户信息的每次迭代中,使用从 Customer 获得的 C_code 对 CustomerPhone 进行第二次查询。如 cmets 中所述,使用 while 语句遍历结果。

    while($row=sqlsrv_fetch_array($query) {
    

    必须注意防止内部查询破坏外部查询!

    SQL 聚合函数

    这涉及进行更复杂的查询。您可以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。您也可以使用&lt;br&gt; 代替逗号来分隔它们。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-10-07
      • 2019-11-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-04-13
      • 1970-01-01
      相关资源
      最近更新 更多