修正准备好的陈述

时间:2019-01-14 00:30:25

标签: php mysql sql

我有两个问题:

  1. 我是否有一种更干净的方法来执行此准备好的语句?似乎这里发生了很多事情。

  2. 您能否在代码中指出“我如何对此进行清理”的部分进行解决?我要确保它的安全。

顺便说一句,这一切似乎都很好。只是想修复一下。

this

2 个答案:

答案 0 :(得分:3)

如前所述,htmlentities()与防止SQL注入无关。当您希望将某些内容输出到HTML并希望避免XSS漏洞时使用它。

我不会将所有这些查询都写为单独的子查询。单个SQL语句的结果不太可能需要获取所有这些信息。尝试将大量工作塞入单个SQL调用中并不会使其效率大大提高,但是确实使您编写代码变得更加困难。

请记住以下智慧:

  

每个人都知道调试的难度是编写程序的两倍。因此,如果您在编写时尽可能聪明,那么将如何调试它?

所以这是我的编码方式:

如果使用参数化查询,则根本不需要清理。但是,如果需要,这是一种更简单的方法:

$customer_id = (int) $_GET['customer_id'];

是的!只需强制转换为(int)。编写此代码很简单,在代码审查中也很容易解释,并且比函数调用执行起来更快。

然后将SQL分为几个查询,以一种明智的方式将它们分组,因此您不需要子查询或列别名。更简单的查询更易于编码,更易于调试,更易于修改(如果您以后需要这样做)(或者,如果另一个开发人员需要对其进行修改,他们将感谢您编写更易于使用的代码)。

获得首次访问的一种简单方法是按created_at排序并使用LIMIT 1。

$sql = "SELECT bdi, pain, suicidality FROM treatment_log WHERE treatment_fk = ?  
  ORDER BY created_at LIMIT 1";
$stmt = $conn->prepare($sql);
$stmt->bind_param("i", $customer_id);
$stmt->execute();
$rows1 = $stmt->fetch_all(MYSQLI_ASSOC);

获取最后一次访问-按created_at 降序排序并使用LIMIT 1。

$sql = "SELECT bdi, pain, suicidality, DATE(created_at) AS last_visit 
  FROM treatment_log WHERE treatment_fk = ?
  ORDER BY created_at DESC LIMIT 1";
$stmt = $conn->prepare($sql);
$stmt->bind_param("i", $customer_id);
$stmt->execute();
$rows2 = $stmt->fetch_all(MYSQLI_ASSOC);

这是一个技巧:在MySQL中true为1,false为0,因此您可以SUM() 1来作为对某些表达式为true的行进行计数的一种方式。

$sql = "SELECT COUNT(*) AS completed_treatments, 
    SUM(missed_treatments='yes') AS number_of_missed_treatments 
  FROM treatment_log WHERE treatment_fk = ?";
$stmt = $conn->prepare($sql);
$stmt->bind_param("i", $customer_id);
$stmt->execute();
$rows3 = $stmt->fetch_all(MYSQLI_ASSOC);

其他查询非常简单。

$sql = "SELECT COUNT(*) AS completed_bdis FROM bdi WHERE bdi_fk = ?";
$stmt = $conn->prepare($sql);
$stmt->bind_param("i", $customer_id);
$stmt->execute();
$rows4 = $stmt->fetch_all(MYSQLI_ASSOC);

$sql = "SELECT f_name, l_name, status, mrn, ohip, sex, address, city, country, 
    phone, about, date_of_birth, protocol, treatment_location, area, dx, room, 
    coil, target_threshold, number_of_treatments, motor_threshold, 
    threshold_multiplier, created_at, updated_at
  FROM customers WHERE id = ?";
$stmt = $conn->prepare($sql);
$stmt->bind_param("i", $customer_id);
$stmt->execute();
$rows5 = $stmt->fetch_all(MYSQLI_ASSOC);

在所有这些查询中,我们只需为每个查询绑定一次$customer_id,这使编写此代码的方式更加容易。无需费心计算长字符串“ iiii ...”的长度并将其与参数数量匹配。

P.S .:我没有测试此代码,因此,如果有错别字,我相信您可以解决。

答案 1 :(得分:2)

开始于:

SELECT {customer fields},
       {MIN/MAX(treatment log fields)},
       COUNT(*) as completed_treatements
       SUM(missed_treatment='yes') AS number_of_missed_treatments
FROM customers
LEFT JOIN treatment_log ON treatment_log.treatment_fk=customers.id
WHERE customer.id=?

bdi似乎无关