I have a PHP webpage running a few SQL queries in a transaction, to be writted in a SQL Server 2008 R2 database. The production server uses:
Everything works fine on this environment.
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). I tried to run the same page but one of the queries doesn't work:
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'));
The error message is:
Code 37000: [Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error near '*='.
The characters "*=" aren't anywhere in this query, as we can see. I tried multiple versions of PHP (5 or 7), multiple and more recent ODBC drivers, but I always get the same result when I run this query through the odbc_exec() function.I tried using PDO or sqlsrv functions, but the outcome is the same.
If I try to copy/paste this query in SQL Server Management Studio, it works fine.
I think it might be related to the ODBC driver, but I can't install the same one that is currently in production because it doesn't work on Windows 2016 and it is a 32 bits driver. I tried running a 32-bits version of PHP 7.3 to no avail.
Part of the PHP code:
$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;
}
EDIT: The FR datetime format in the queries works fine. Issue isn't related to it at all, I think.
You need to pass correct date time format (ie: MM/dd/yyyy hh:mm:ss). Because SQL Server by default understand US date time standard.
Please check below select query.
SELECT
CONVERT(date, '12/31/2050') LIGNELIVDATEPEREMPTION,
CONVERT(datetime, '09/27/2019 13:48:54') LIGNELIVDATECREATION
Please check below insert script for your answer.
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'));
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.