У меня есть веб-страница 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 в запросах работает нормально,Думаю, проблема вообще не связана с этим.