簡體   English   中英

SQL 服務器插入查詢與 ODBC 和 PHP:奇怪的語法錯誤

[英]SQL Server INSERT query with ODBC & PHP : weird syntax error

我有一個 PHP 網頁,在事務中運行一些 SQL 查詢,寫入 SQL Server 2008 R2 數據庫。 生產服務器使用:

  • PHP 5.3 32 位
  • ODBC SQL 服務器驅動32位版本6.01
  • IIS 7.5

在這種環境下一切正常。

I have to upgrade to PHP 7.3 64 bits on a new Windows Server 2016 server, running IIS 10 and a more recent SQL Server ODBC driver (64 bits). 我嘗試運行同一頁面,但其中一個查詢不起作用:

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 服務器驅動程序][SQL Server]“*=”附近的語法錯誤。

如我們所見,字符“*=”不在此查詢中的任何位置。 我嘗試了多個版本的 PHP(5 或 7)、多個和更新的 ODBC 驅動程序,但是當我通過 odbc_exec() ZC1C425268E687385D1AB5074C1 運行此查詢時總是得到相同的結果我嘗試使用 PDO 或 sqlsrv 函數,但結果是一樣的。

如果我嘗試在 SQL Server Management Studio 中復制/粘貼此查詢,它可以正常工作。

我認為它可能與 ODBC 驅動程序有關,但我無法安裝目前正在生產的同一個驅動程序,因為它不適用於 Windows 2016 並且它是 32 位驅動程序。 我嘗試運行 PHP 7.3 的 32 位版本,但無濟於事。

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 日期時間格式工作正常。 我認為問題根本與它無關。

您需要傳遞正確的日期時間格式(即:MM/dd/yyyy hh:mm:ss)。 因為 SQL 服務器默認理解美國日期時間標准。

請查看下面的 select 查詢。

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'));

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM