1
votes

PHP - Avoir des difficultés à insérer des dates à partir d'une colonne de date avec des valeurs nulles. Les valeurs sont à l'intérieur d'un tableau

Je crée un programme SQL Server vers MySQL qui me permet de synchroniser le contenu entre deux tables identiques. Cependant, j'ai des problèmes avec l'insertion de valeurs de date à partir d'une colonne de date dont certaines de ses cellules sont définies sur NULL. La façon dont cela devrait fonctionner est de convertir chaque valeur de la colonne de date en une chaîne à l'aide d'une fonction de format. Puisque je génère chaque ligne à partir d'un tableau et que je l'exécute via une boucle, je ne peux pas sélectionner les lignes avec NULL. Voici le code (il est assez long donc j'ai découpé quelques parties donc merci de rester avec moi):

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

L'erreur qu'il me donne est "Erreur fatale: Erreur non interceptée: Appel à une fonction membre format () on null "ce qui me dit à peu près qu'il ne peut pas utiliser la fonction format sur les valeurs NULL qu'il rencontre. Cependant, avec la fonction de formatage, cela me donnera à la place l'erreur "L'objet DateTime n'a pas pu être converti en chaîne". Y a-t-il un moyen pour moi de contourner ce problème? Je ne peux pas modifier les valeurs de la base de données elle-même car ce n'est pas la mienne.


2 commentaires

vous pouvez omettre les lignes qui sont nulles.. avez-vous essayé cela?


comment je fais ça? si vous voulez dire que je devrais utiliser une commande de suppression dans SQL pour supprimer toutes les lignes avec des valeurs nulles, je ne peux pas le faire car certaines lignes contiennent des données (mais pas dans la colonne de date) et je ne peux pas changer le contenu de la base de données


4 Réponses :


3
votes

Vous pouvez facilement omettre les lignes nulles en utilisant la requête de sélection mysql. Essayez cette requête: SELECT * FROM santé où nom_colonne n'est PAS NULL;


2 commentaires

merci, cela résout complètement tout. je ne peux pas croire que cette solution a survolé ma tête.


désolé de demander à nouveau, mais après avoir ajouté une nouvelle ligne avec une date NULL moi-même, j'ai découvert que ce n'est pas l'insertion même si cela devrait. Existe-t-il un moyen d'ignorer uniquement les valeurs NULL pendant la conversion datetime en chaîne, tout en ajoutant ces lignes lors de l'insertion?



1
votes

Vous pouvez essayer de vérifier si une valeur est_null () puis supprimez-le du tableau.

<?php

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

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

?>


3 commentaires

Dois-je mettre cette ligne de code avant de lier les paramètres, puis appeler à nouveau $ period lors de la liaison?


@YMSmash si votre problème est lorsque vous insérez les valeurs dans la base de données, oui.


le code ne fonctionne toujours pas comme prévu, il renvoie toujours l'erreur ci-dessus. Je modifierai mon message pour que vous voyiez si j'utilise unset de manière incorrecte, car je ne l'ai jamais utilisé auparavant



4
votes

Vous devrez vérifier et vous assurer que la variable est un objet DateTime avant d'appeler format () :

$ period = ($ value ["period"] instance de DateTime)? $ valeur ["période"] -> format ('Y-m-j H: i: s'): null;


3 commentaires

c'est ce qui a fonctionné le mieux pour moi, mais cela vous dérange-t-il d'expliquer exactement comment cette ligne de code fonctionne?


C'est une sorte de condition If Else mais on l'appelle opeartor ternaire en PHP. La première partie de la réponse ($ value ["period"] instanceof DateTime) signifie, si $ value ["period"] est une instance de la classe DateTime, définissez $ value sur $ value ["period"] -> format (' Ymd H: i: s ') et la dernière partie après: signifie si non alors mis à null.


Vous pouvez en savoir plus sur l'opeator ternaire ici: abeautifulsite.net/how -to-use-the-php-ternary-operator C'est juste une autre sorte de condition IF Else, mais elle est généralement écrite en une seule ligne, donc les programmeurs préfèrent utiliser l'opérateur ternaire.



1
votes

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

Il y a énormément de mal avec cette seule ligne de code. Pour commencer, utilisez une fabrique pour traduire une valeur qui est présentée à PHP sous forme de chaîne ou nulll ou continuez simplement à la traiter comme une chaîne / null. Ensuite, le reste des problèmes disparaissent:

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

Mais vous devez vous assurer que vous récupérez les données dans un format cohérent et connu. À partir de MS-SQL, vous devez CONVERT (point, 20) pour obtenir une date ISO 8601. MySQL analysera nativement ceci comme une chaîne et renvoie les heures de date dans ce format.

Malheureusement, le serveur SQL est quelque peu limité dans sa gestion des dates. Bien que vous puissiez utiliser SET DATEFORMAT , cela ne fonctionne que pour certains types de données. Donc, si vous vouliez l'essentiel de la logique en PHP, essayer de renifler le format (et l'état nul) tout ce que vous écrivez serait lié à la locale configurée dans votre serveur MSSQL. Je ne prendrai pas la peine de donner un exemple car si vous coupez et collez mon code et que cela ne fonctionne pas, vous penserez qu'il y a quelque chose qui ne va pas avec le code plutôt que de simplement attendre une locale différente de celle que vous avez configurée.

Je ne sais pas d'emblée si une valeur NULL est renvoyée sous forme de variable PHP nulle ou de chaîne vide par l'extension MSSQL. Mais les deux sont des chaînes de longueur nulle, donc une solution générique serait ....

$period = $value["period"];

2 commentaires

désolé, mais comme je suis encore nouveau en PHP, je ne suis pas tout à fait sûr de ce que vous vouliez dire avec certaines des choses que vous avez dites, à savoir: 1) "Pour commencer, utilisez une usine pour traduire une valeur qui est présentée à PHP comme une chaîne ou null ", je ne sais pas ce que signifierait une usine dans ce contexte 2)" À partir de MS-SQL, vous devriez CONVERTIR (période, 20) pour obtenir une date ISO 8601. ", également pas familier avec ce que le CONVERT fonction fait dans MSSQL, ou ce qu'est un ISO 8601, et 3) $ bindable = strlen ($ avalue)? null: $ avalue; comment fonctionne cette ligne de code et où se situe-t-elle dans mon code?


Aucune des choses que vous avez interrogées ici n'est spécifique à PHP. Vraisemblablement, vous êtes également nouveau dans la programmation. Peut-être êtes-vous un peu trop sollicité ici.