【问题标题】:No data from Database没有来自数据库的数据
【发布时间】:2020-07-13 08:24:27
【问题描述】:

我编写了一个 php 应用程序,它应该根据给定的日期从数据库中选择数据。数据库中的日期存储为2020-07-03。执行语句的代码如下所示


$from = $_POST['from'];
$to = $_POST['to'];

$sql = "SELECT * FROM Database WHERE Date < $from";
$stmt = sqlsrv_query($conn, $sql);

if($stmt == false){
    die( print_r( sqlsrv_errors(), true) );
}
echo $sql;

while( $row = sqlsrv_fetch_array( $stmt, SQLSRV_FETCH_NUMERIC) ) {
    echo $row[0].", ".$row[1]."<br />";
}

$from$to 是一个范围,由用户使用日期输入字段给出,并返回用户输入,如2020-07-02。 “日期”字段的数据类型是日期。我没有收到任何错误或类似的东西,但它不会执行 while 循环,我不知道为什么。

【问题讨论】:

  • 不要注入你的参数,使用参数化/准备好的查询。 WHERE Date &lt; $from 将导致 WHERE Date &lt; 2020-07-03 将是 WHERE Date &lt; 2010。作为datetimeint 的值2010 是值'1905-07-04',我怀疑您是否有任何值小于该值的行。
  • 不应该引用日期以使用直接变量吗? WHERE Date &lt; '$from'?更好的是,使用准备好的语句 - php.net/manual/en/function.sqlsrv-prepare.php - 这样,您不必担心它是否被引用,并且它是额外的安全层。
  • 不应该参数化,@Qirel,不应该注入引号。
  • @Larnu 阅读我的完整评论......
  • 你在之后编辑了我的评论,@Qirel ...

标签: php sql-server sqlsrv


【解决方案1】:

您需要在语句中使用参数。正如documentation 中提到的,sqlsrv_query() 函数非常适合一次性查询,除非有特殊情况,否则应该是执行查询的默认选择。此函数提供了一种简化的方法,可以用最少的代码执行查询。 sqlsrv_query函数既做语句准备也做语句执行,可以用来执行参数化查询

您需要通过以下方式之一传递参数的值:

  • 作为使用明确日期格式 (yyyymmdd) 的文本,
  • 使用扩展参数语法和适当的数据类型绑定。

示例,基于问题中的代码,使用文本值作为日期:

<?php
// Connection
$server    = 'server,port';
$database  = 'database';
$uid       = 'uid';
$pwd       = 'pwd';
$cinfo = array(
   "ReturnDatesAsStrings" => true,
   "Database" => $database,
   "UID" => $uid,
   "PWD" => $pwd
);
$conn = sqlsrv_connect($server, $cinfo);
if ($conn === false) {
   echo "Error (sqlsrv_connect): ".print_r(sqlsrv_errors(), true);
   exit;
}

// Test input
$from = (new DateTime('2020-07-02'))->format('Ymd');
$to   = (new DateTime('2020-07-03'))->format('Ymd');

// Statement
$sql = "
    SELECT * 
    FROM Database 
    WHERE (? <= [Date]) AND ([Date] <= ?)"
;
$params = array($from, $to);
$stmt = sqlsrv_query($conn, $sql, $params);
if($stmt == false){
    die( print_r( sqlsrv_errors(), true) );
}
echo $sql;

// Data
while( $row = sqlsrv_fetch_array( $stmt, SQLSRV_FETCH_NUMERIC) ) {
    echo $row[0].", ".$row[1]."<br />";
}

// End
sqlsrv_free_stmt($stmt);

?>

示例,根据问题中的代码,使用 PHP 日期对象和适当的参数绑定:

<?php
// Connection
$server    = 'server,port';
$database  = 'database';
$uid       = 'uid';
$pwd       = 'pwd';
$cinfo = array(
   "ReturnDatesAsStrings" => true,
   "Database" => $database,
   "UID" => $uid,
   "PWD" => $pwd
);
$conn = sqlsrv_connect($server, $cinfo);
if ($conn === false) {
   echo "Error (sqlsrv_connect): ".print_r(sqlsrv_errors(), true);
   exit;
}

// Test input
$from = new DateTime('2020-07-02');
$to   = new DateTime('2020-07-03');

// Statement
$sql = "
    SELECT * 
    FROM Database 
    WHERE (CONVERT(date, ?) <= [Date]) AND ([Date] <= CONVERT(date, ?))"
;
$params = array(
   array($from, SQLSRV_PARAM_IN, SQLSRV_PHPTYPE_DATETIME, SQLSRV_SQLTYPE_DATETIME),
   array($to, SQLSRV_PARAM_IN, SQLSRV_PHPTYPE_DATETIME, SQLSRV_SQLTYPE_DATETIME)
);
$stmt = sqlsrv_query($conn, $sql, $params);
if($stmt == false){
    die( print_r( sqlsrv_errors(), true) );
}
echo $sql;

// Data
while( $row = sqlsrv_fetch_array( $stmt, SQLSRV_FETCH_NUMERIC) ) {
    echo $row[0].", ".$row[1]."<br />";
}

// End
sqlsrv_free_stmt($stmt);

?>

【讨论】:

  • 现在出现以下错误Recoverable fatal error: Object of class DateTime could not be converted to string
  • 遇到另一个错误。 core_sqlsrv_bind_param: invalid encoding 它说它会发生在这条线上 $stmt = sqlsrv_query($conn, $sql, $params);
  • @fhprogrammer 答案中的示例工作正常(使用 PHP 7.4.8 和 PHP Driver for SQL Server 5.8 测试)。如果我在第二个示例中使用$from = (new DateTime('2020-07-02'))-&gt;format('Ymd') 而不是$from = new DateTime('2001-07-02'),我能够重现第二个错误。谢谢。
  • 在我的情况下它既不是第一个例子也不是第二个例子。当我尝试第一个错误时,我收到第一个错误,当我尝试第二个错误时,我收到第二个错误消息。对不起
  • @fhprogrammer 1) 对于第一个示例 - 检查您如何准确地获取从语句返回的日期值(answer 解释了类似的问题)。 2) 对于第二个示例,您需要将 PHP 日期时间对象分配给 $from$to 变量,而不是字符串。这些示例使用"ReturnDatesAsStrings"=&gt;true, 连接选项进行了更新。
猜你喜欢
  • 1970-01-01
  • 2018-02-08
  • 2017-07-07
  • 2017-01-30
  • 2020-01-08
  • 2016-06-29
  • 2011-12-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多