PHP - 从具有空值的日期列中插入日期时遇到问题。值在数组内

Posted

技术标签:

【中文标题】PHP - 从具有空值的日期列中插入日期时遇到问题。值在数组内【英文标题】:PHP - Having trouble inserting dates from a date column with null values. Values are inside an array 【发布时间】:2019-04-26 12:07:21 【问题描述】:

我正在制作一个 SQL Server 到 mysql 程序,它允许我在两个相同的表之间同步内容。但是,我无法从日期列中插入日期值,该日期列的某些单元格设置为 NULL。这应该工作的方式是它应该使用格式函数将日期列中的每个值转换为字符串。因为我是从一个数组中生成每一行并通过一个循环运行它,所以我不能手工挑选带有 NULL 的行。这是代码(它相当长,所以我剪掉了一些部分,所以请多多包涵):

//SELECT FROM SQL SERVER DB
$mssql_array = array();
$ms_sql = "SELECT * FROM health";
$mssql_query = sqlsrv_query($conn_mssql, $ms_sql);

while($row = sqlsrv_fetch_array($mssql_query))

  //turn individual rows into array    
  $mssql_array[] = array(
  'id' => $row['id'], 
  'period' => $row["period"], //date column; has NULLs in it that prevent insert
  'BP' => $row['BP'], 
  'pulserate' => $row['pulserate'],
  'temperature' => $row['temperature'],
  'labresult' => $row['labresult'],
  'waistline' => $row['waistline'],
  'weight' => $row['weight'],
  'BMI' => $row['BMI'],
  'findings' => $row['findings'],
  'diagnosis' => $row['diagnosis'],
  'plano' => $row['plano'] ... );


foreach($mssql_array as $key => $value)

  //SELECT FROM MySQL DB
  $my_sql = $conn_mysql->prepare(" SELECT * FROM health  
  WHERE id = ? 
  AND period = ?
  AND `BP` = ?
  AND pulserate = ?
  AND temperature = ? 
  AND labresult = ? 
  AND waistline = ? 
  AND weight = ? 
  AND BMI = ? 
  AND findings = ? 
  AND diagnosis = ? 
  AND plano = ? ... ");

  $my_sql->bind_param("issssssssssssssiissssssssiiiiss", $id, $period, $BP, $pulserate, $temperature, $labresult, $waistline, $weight, $BMI, $findings, $diagnosis, $plano ... );

  $id = $value["id"]; 
  $period = $value["period"]->format('Y-m-d H:i:s'); //prevents me from converting all date values to string...

  if(is_null($period))
  
    unset($period);
  

  $BP = $value["BP"]; 
  $pulserate = $value["pulserate"];
  $temperature = $value["temperature"];
  $labresult = $value["labresult"];
  $waistline = $value["waistline"];
  $weight = $value["weight"];
  $BMI = $value["BMI"];
  $findings = $value["findings"];
  $diagnosis = $value["diagnosis"];
  $plano = $value["plano"]; ...

  $my_sql->execute();
  $num_rows = $my_sql->num_rows();

  $my_sql->close();

  //PREPARE INSERT INTO MySQL DB
  $sql = $conn_mysql->prepare("INSERT INTO `health` VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");//31 total

  $sql->bind_param("issssssssssssssiissssssssiiiiss", $id, $period, $BP, $pulserate, $temperature, $labresult, $waistline, $weight, $BMI, $findings, $diagnosis, $plano ... );

  $id = $value["id"]; 
  $period = $value["period"]->format('Y-m-d H:i:s'); //...because it stops the process when it encounters a NULL value

  if(is_null($period))
  
    unset($period);
  

  $BP = $value["BP"]; 
  $pulserate = $value["pulserate"];
  $temperature = $value["temperature"];
  $labresult = $value["labresult"];
  $waistline = $value["waistline"];
  $weight = $value["weight"];
  $BMI = $value["BMI"];
  $findings = $value["findings"];
  $diagnosis = $value["diagnosis"];
  $plano = $value["plano"]; ...

    if($num_rows == 0)
      
        $sql->execute();
      


echo 'Table health from MS SQL DB and table health from MySQL DB are now synced!'."<br>";
echo "<a href='table_updater.php'>Go back to updater</a>";

它给我的错误是“致命错误:未捕获的错误:在 null 上调用成员函数 format()”,这几乎告诉我它不能在遇到的 NULL 值上使用格式函数。但是,使用格式功能,它会给我错误“对象日期时间无法转换为字符串”。我有什么办法可以解决这个问题吗?我无法更改数据库值本身,因为它不是我的。

【问题讨论】:

你可以省略空行。你试过了吗? 我该怎么做?如果您的意思是我应该在 SQL 中使用删除命令来删除所有带有空值的行,那么我不能这样做,因为某些行中确实有数据(只是不在日期列中)并且我无法更改数据库的内容 【参考方案1】:

在调用 format() 之前,您必须检查并确保该变量是 DateTime 对象:

$period = ($value["period"] instanceof DateTime) ? $value["period"]-&gt;format('Y-m-d H:i:s') : null;

【讨论】:

这对我来说是最有效的,但是你介意解释一下这行代码是如何工作的吗? 这是一种 If Else 条件,但在 PHP 中称为三元运算符。答案的第一部分( $value["period"] instanceof DateTime )的意思是,如果 $value["period"] 是 DateTime 类的实例,则将 $value 设置为 $value["period"]->format(' Y-m-d H:i:s') 和 : 之后的最后一部分表示如果不是则设置为 null。 您可以在此处阅读有关三元运算符的更多信息:abeautifulsite.net/how-to-use-the-php-ternary-operator 这只是另一种 IF Else 条件,但它通常写在单行中,因此程序员更喜欢使用三元运算符。【参考方案2】:

您可以使用 mysql 选择查询轻松省略空行。试试这个查询: SELECT * FROM health where column_name is NOT NULL;

【讨论】:

谢谢,这完全解决了一切。我不敢相信这个解决方案飞过我的脑袋。 很抱歉再次询问,但是在我自己添加了一个带有 NULL 日期的新行之后,我发现它没有插入它,即使它应该插入它。有没有办法让它在日期时间到字符串转换期间只忽略 NULL,但在插入期间仍然添加这些行?【参考方案3】:

您可以尝试检查数组中是否有值is_null(),然后unset。

<?php

$period = $value["period"]->format('Y-m-d H:i:s');

if( is_null($period) )
unset($period);


?>

【讨论】:

要不要在绑定参数之前先放这行代码,绑定的时候再调用$period? @YMSmash 如果您的问题是在数据库中插入值时,是的。 代码仍然不能按预期工作,它仍然返回上面的错误。我会为你编辑我的帖子,看看我是否使用 unset 不当,因为我以前从未使用过它【参考方案4】:

$period = $value["period"]->format('Y-m-d H:i:s');

那一行代码有很多错误。对于初学者,要么使用工厂来转换作为字符串或 nulll 呈现给 PHP 的值,要么继续将其视为字符串/null。然后剩下的问题就迎刃而解了:

$period = $value["period"];

但您需要确保以一致且已知的格式检索数据。在 MS-SQL 中,您应该 CONVERT(period, 20) 获取 ISO 8601 日期。 MySQL 将本机将其解析为字符串并以这种格式返回日期时间。

不幸的是,SQL Server 在处理日期方面有些限制。虽然您可以使用SET DATEFORMAT,但这仅适用于某些数据类型。因此,如果您想了解 PHP 中的大部分逻辑,尝试嗅探格式(和 null 状态)您编写的任何内容都将与您的 MSSQL 服务器中配置的语言环境相关联。我不会费心提供示例,因为如果您剪切和粘贴我的代码并且它不起作用,您会认为代码有问题,而不是仅仅期望与您配置的语言环境不同。

我不知道如果一个 NULL 值是作为一个空 PHP 变量返回还是由 MSSQL 扩展返回一个空字符串。但两者都是零长度字符串,因此通用解决方案是......

$bindable=strlen($avalue) ? null : $avalue;

【讨论】:

抱歉,但由于我还是 PHP 新手,所以我不太确定您所说的某些内容是什么意思,即:1)“对于初学者,要么使用工厂来翻译以字符串或 null 的形式呈现给 PHP 的值”,我不知道工厂在这种情况下意味着什么 2) “从 MS-SQL 中,您应该 CONVERT(period, 20) 以获取 ISO 8601 日期。” ,也不熟悉 CONVERT 函数在 MSSQL 中的作用,或者 ISO 8601 是什么,以及 3)$bindable=strlen($avalue) ? null : $avalue; 这行代码是如何工作的,它在我的代码中的什么位置? 您在此处查询的所有内容都不是特定于 PHP 的。想必你也是编程新手。也许你在这里有点过分了。

以上是关于PHP - 从具有空值的日期列中插入日期时遇到问题。值在数组内的主要内容,如果未能解决你的问题,请参考以下文章

弹性搜索:索引具有空值的日期字段

Oracle 中参数中具有空值的结果

pandas-对列中具有相同值的连续行进行分组和聚合

使用空值加入和最大日期

在其中一列中具有多个空值的复合唯一键约束

SQL 选择较早的日期(包括 NULL)