SQL Server INSERT запрос с ODBC и PHP: странная синтаксическая ошибка - PullRequest
0 голосов
/ 27 сентября 2019

У меня есть веб-страница PHP, выполняющая несколько запросов SQL в транзакции, для записи в базу данных SQL Server 2008 R2.Рабочий сервер использует:

  • PHP 5.3 32 бита
  • ODBC SQL Server Драйвер 32 бита, версия 6.01
  • IIS 7.5

Всеотлично работает в этой среде.

Мне нужно обновить до PHP 7.3 64 бит на новом сервере Windows Server 2016, работающем под управлением IIS 10 и более позднем драйвере ODBC для SQL Server (64 бит).Я пытался запустить ту же страницу, но один из запросов не работает:

INSERT INTO LIGNELIVRAISON 
(ARTICLEID, LCDEID, LIVID, LIGNELIVQTELIV, LIGNELIVDATECREATION, LIGNELIVQTEINITIALE, LIGNELIVMTUNITHT, LIGNELIVMTUNITTVA, LIGNELIVMTUNITTTC, LIGNELIVMTREMISE, LIGNELIVCODELOT, LIGNELIVDATEPEREMPTION) 
VALUES 
(1573, 44551, 35232, 3, CONVERT(datetime, '27/09/2019 13:48:54'), 3, 50, 4.25, 54.25, 0, '???', CONVERT(date, '31/12/2050'));

Сообщение об ошибке:

Код 37000: [Microsoft] [ODBC SQL ServerДрайвер] [SQL Server] Синтаксическая ошибка рядом с '* ='.

Символы "* =" в этом запросе отсутствуют, как мы видим.Я пробовал несколько версий PHP (5 или 7), несколько и более свежие драйверы ODBC, но всегда получаю один и тот же результат, когда выполняю этот запрос через функцию odbc_exec ().Я пытался использовать функции PDO или sqlsrv, но результат тот же.

Если я попытаюсь скопировать / вставить этот запрос в SQL Server Management Studio, он отлично работает.

Я думаю, что это можетбыть связанным с драйвером ODBC, но я не могу установить тот, который в настоящее время находится в производстве, потому что он не работает в Windows 2016 и это 32-битный драйвер.Я попытался запустить 32-битную версию PHP 7.3, но безрезультатно.

Часть кода PHP:

$ms->hdebug();
    //$ms->libre('SET IMPLICIT_TRANSACTIONS OFF');
    //$ms->libre('BEGIN TRANSACTION');
    odbc_autocommit($ms->get_lien(), false);

    $id_utilisateur_creation = id_utilisateur_athome($my, $ms);

    // On a ajouté un contrôle en amont mais par sécurité, on ajoute un contrôle ici
    if ($id_utilisateur_creation === FALSE) {
      $id_utilisateur_creation = 1;
    }

    // 25 = Fournisseur matériel
    $id_type_intervenant = 25; 
    $type_facture = 'F';
    // 2 = Location
    $id_type_produit = 2;
    // 5 = Livrée
    $id_etat_commande = 5;
    $franco_port = 'N';
    $tproduitcode = 'LOCA';
    $date = date('d/m/Y');
    $date_heure = date('d/m/Y H:i:s');
    $montant_remise = 0;
    $total_ttc = 0;
    $etat_sejour_suivi = 14;
    // Pour éviter une erreur lors de l'insertion des lignes de livraison, liées a une procédure stockée
    $code_lot_article = '???';
    $date_peremption_article = '31/12/2050';
    $commentaires = addslashes('Commande créée pour le bon de location n° ' . $_POST['id_location']);

    // Récupération des TVA AtHome
    $tva_athome = $ms->lire(
      'TVAID, TVATAUX * 100',
      'TVA',
      "AND TVAVISIBLE = 'O'",
      "TVATAUX ASC"
    );

    $mapping_tva = array();

    foreach($tva_athome as $tva) {
      list($id_tva, $taux_tva) = $tva;
      $mapping_tva[$id_tva] = round($taux_tva, 2);
    }
    // -

    // Etape 1: Création de la commande et lignes de commande
    $id_commande = $ms->ajouter(
      'CDEFRN',
      'UTIID, TPRODUITID, FOURNID, ETATCDEID, PATID,
       CDEFRNDATE, CDEFRNFRANCOPORT, CDEFRNDATECREATION, TProduitCode, CDEFRNCOMMENTAIRE',
      "$id_utilisateur_creation, $id_type_produit, {$_POST['id_fournisseur']}, $id_etat_commande, {$_POST['ipp']},
       CONVERT(date, '$date'), '$franco_port', CONVERT(datetime, '$date_heure'), '$tproduitcode', '$commentaires'"
    );

    $lignes_commande = array();

    // Ajout des lignes d'articles
    foreach($_POST['articles'] as $id_article) {
      if ($_POST['prix'][$id_article] > 0 && $_POST['quantite'][$id_article] > 0) {
        $quantite = $_POST['quantite'][$id_article];
        $taux_tva = $mapping_tva[$_POST['tva'][$id_article]];
        $prix_ht = round($_POST['prix'][$id_article], 2);
        // On calcule les arrondis ici pour ne pas avoir de problème d'arrondi dans AtHome à cause des champs de type money
        $prix_ttc = round($prix_ht * (1 + ($taux_tva / 100)), 2);
        $montant_tva = $prix_ttc - $prix_ht;

        $lignes_commande[$id_article] = $ms->ajouter(
          'LIGNECDEFRN',
          'CDEFRNID, ARTICLEID, LCDEQTECDE, LCDEMTHT, LCDEMTTVA,
           LCDEMTTTC, LCDEMTREMISE, LCDEDATECREATION, LCDEQTEINITIALE',
          "$id_commande, $id_article, $quantite, $prix_ht, $montant_tva,
           $prix_ttc, $montant_remise, CONVERT(datetime, '$date_heure'), $quantite"
        );

        $total_ttc += $prix_ttc;
      }
    }

    $total_ttc = round($total_ttc, 2);

    // Etape 2: Livraison
    $id_livraison = $ms->ajouter(
      'LIVRAISON',
      'CDEFRNID, LIVDATE, LIVDATECREATION',
      "$id_commande, CONVERT(date, '$date'), CONVERT(datetime, '$date_heure')"
    );

    $lignes_livraison = array();

    // Ajout des lignes de livraison
    foreach($_POST['articles'] as $id_article) {
      if ($_POST['prix'][$id_article] > 0 && $_POST['quantite'][$id_article] > 0) {
        $quantite = $_POST['quantite'][$id_article];
        $taux_tva = $mapping_tva[$_POST['tva'][$id_article]];
        $prix_ht = round($_POST['prix'][$id_article], 2);
        // On calcule les arrondis ici pour ne pas avoir de problème d'arrondi dans AtHome à cause des champs de type money
        $prix_ttc = round($prix_ht * (1 + ($taux_tva / 100)), 2);
        $montant_tva = $prix_ttc - $prix_ht;

        $lignes_livraison[$id_article] = $ms->ajouter(
          'LIGNELIVRAISON',
          'ARTICLEID, LCDEID, LIVID, LIGNELIVQTELIV, LIGNELIVDATECREATION,
           LIGNELIVQTEINITIALE, LIGNELIVMTUNITHT, LIGNELIVMTUNITTVA, LIGNELIVMTUNITTTC, LIGNELIVMTREMISE,
           LIGNELIVCODELOT, LIGNELIVDATEPEREMPTION',
          "$id_article, {$lignes_commande[$id_article]}, $id_livraison, $quantite, CONVERT(datetime, '$date_heure'),
           $quantite, $prix_ht, $montant_tva, $prix_ttc, $montant_remise,
           '$code_lot_article', CONVERT(date, '$date_peremption_article')"
        );
      }
    }
public function ajouter($table,$champs,$valeurs)
    {
      if(trim($champs)=="")
      {
        $req="INSERT INTO ".$table." VALUES(".$valeurs.");";
      }
      else
      {
        $req="INSERT INTO ".$table." (".$champs.") VALUES(".$valeurs.");";
      }
      $retour=-1;
      if($this->hdebug)
      {
        $this->log->logguer("INS",$req);
      }
      if($this->debug)
      {
        echo "<debug_sql>".$req."</debug_sql>";
      }
      else
      {
        if($this->calcul_temps)
        {
          $_SESSION["Temps_Execution"]->Debut_Compter("MsSQL");
        }
        //$res = @mssql_query($req,$this->lien) or $this->erreur("insert",$req,0,"");
        //$res = odbc_prepare($this->lien, $req);
        //$res_ex = odbc_execute($res);

        $res = odbc_exec($this->lien, $req);

        if (!$res) {
          //var_dump($req);
          $this->erreur("insert", $req, odbc_error($this->lien), odbc_errormsg($this->lien));
        }

        $id_retour=@odbc_exec($this->lien,"SELECT @@IDENTITY") or $this->erreur("insert",$req,0,"");
        $retour=odbc_result($id_retour, 1);
        if($this->calcul_temps)
        {
          $_SESSION["Temps_Execution"]->Fin_Compter("MsSQL");
        }
        //$retour=mysql_insert_id($this->lien);
      }
      //$retour=0;
      return $retour;
    }

РЕДАКТИРОВАТЬ: формат даты и времени FR в запросах работает нормально,Думаю, проблема вообще не связана с этим.

1 Ответ

0 голосов
/ 27 сентября 2019

Вам необходимо передать правильный формат даты и времени (то есть: ММ / дд / гггг чч: мм: сс).Поскольку SQL Server по умолчанию понимает стандарт даты и времени США.

Пожалуйста, отметьте ниже выбранный запрос.

SELECT 
    CONVERT(date, '12/31/2050') LIGNELIVDATEPEREMPTION,
    CONVERT(datetime, '09/27/2019 13:48:54') LIGNELIVDATECREATION

Пожалуйста, проверьте ниже вставьте скрипт для вашего ответа.

INSERT INTO LIGNELIVRAISON 
(ARTICLEID, LCDEID, LIVID, LIGNELIVQTELIV, LIGNELIVDATECREATION, LIGNELIVQTEINITIALE, LIGNELIVMTUNITHT, LIGNELIVMTUNITTVA, LIGNELIVMTUNITTTC, LIGNELIVMTREMISE, LIGNELIVCODELOT, LIGNELIVDATEPEREMPTION) 
VALUES 
(1573, 44551, 35232, 3, CONVERT(datetime, '09/27/2019 13:48:54'), 3, 50, 4.25, 54.25, 0, '???', CONVERT(date, '12/31/2050'));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...