Backup del database di SQL Server utilizzando PHP
Sto cercando di eseguire il backup di un database MS SQL chiamando una procedura memorizzata utilizzando PHP.
Quando eseguo de SP su SSMS, tutto funziona correttamente. Tuttavia, quando lo chiamo dallo script PHP, vedo un ".bak" nella cartella di backup e subito dopo che PHP termina l'elaborazione, il file BackUp.bak scompare.
Ecco la procedura memorizzata:
DECLARE @date VARCHAR(10)
SET @date = (SELECT date FROM tbl_date)
Declare @fileName VARCHAR(100)
SET @fileName = ('C:\db_backup\BackUp_' + @date + '.bak')
BACKUP DATABASE DbName
TO DISK = @fileName
WITH FORMAT,
MEDIANAME = 'SQLServerBackups',
NAME = 'Full Backup of DbName';
Di seguito è riportato il codice PHP che chiamo SP:
$serverName = "server"; $connectionInfo = array( "Database"=>"DbName", "UID"=>"UserName", "PWD"=>"P@ssword", "CharacterSet"=>"UTF-8", "ReturnDatesAsStrings" => "false");
$conn = sqlsrv_connect( $serverName, $connectionInfo); $BackupDB = "Exec DBBackup";
sqlsrv_query($conn, $BackupDB);
Sto eseguendo Apache 2.4.46 e SQL Server Express 2019.
Il mio obiettivo è creare un file ".bak" utilizzando PHP.
Ho provato a utilizzare un SP perché il codice originale è scritto in Classic ASP e funziona perfettamente in questo modo.
Sono aperto a provare approcci diversi.
Grazie.
Risposte
Spiegazioni:
Stai utilizzando PHP Driver per SQL Server, quindi le seguenti spiegazioni sono un'opzione aggiuntiva per risolvere il tuo problema:
- Sembra che questo problema sia probabilmente un problema specifico del driver. SQL Server riempie il buffer di output della connessione con i set di risultati creati dal batch: informazioni sul conteggio delle righe interessate (
INSERT\DELETE\UPDATEad esempio in un caso di istruzioni) o stato di avanzamento (restituito dalleBACKUP\RESTORE DATABADEistruzioni). Questi set di risultati devono essere elaborati dallo script PHP. Sembra che questo comportamento sia di progettazione e lo script PHP dovrebbe svuotare tutti i set di risultati in sospeso. Dopo che i set di risultati vengono recuperati, SQL Server completa l'esecuzione del batch. Le funzioni \ metodi appropriati che è necessario utilizzare sonosqlsrv_next_result()(per la versione SQLSRV del driver) ePDOStatement::nextRowset()(per la versione PDO_SQLSRV del driver). - Per la versione SQLSRV del driver è necessario modificare la gestione degli errori e degli avvisi utilizzando
sqlsrv_configure("WarningsReturnAsErrors", 0);.
Esempi:
Sono in grado di riprodurre il problema dalla domanda e i seguenti esempi sono soluzioni funzionanti:
Utilizzando la versione SQLSRV del driver:
<?php
// Server information
$server = "server\instance,port"; $database = "database";
$uid = "username"; $pwd = "password";
// Configuration
sqlsrv_configure("WarningsReturnAsErrors", 0);
// Connection
$cinfo = array( "UID" => $uid,
"PWD" => $pwd, "Database" => $database
);
$conn = sqlsrv_connect($server, $cinfo); if ($conn === false) {
echo "Unable to connect.";
die( print_r( sqlsrv_errors(), true));
}
// Statement
$sql = " DECLARE @date VARCHAR(19) SET @date = CONVERT(VARCHAR(19), GETDATE(), 126) SET @date = REPLACE(@date, ':', '-') SET @date = REPLACE(@date, 'T', '-') DECLARE @fileName VARCHAR(100) SET @fileName = ('d:\backup\BackUp_' + @date + '.bak') BACKUP DATABASE dbname TO DISK = @fileName WITH FORMAT, STATS = 1, MEDIANAME = 'SQLServerBackups', NAME = 'Full Backup of dbname'; "; $stmt = sqlsrv_query($conn, $sql);
if ($stmt === false) { echo "Unable to execute query."; die( print_r( sqlsrv_errors(), true)); } // Clear buffer while (sqlsrv_next_result($stmt) != null){};
echo "Success";
// End
sqlsrv_free_stmt($stmt); sqlsrv_close($conn);
?>
Utilizzando la versione PDO_SQLSRV del driver:
<?php
// Server information
$server = "server\instance,port"; $database = "database";
$uid = "username"; $pwd = "password";
// Connection
try {
$conn = new PDO("sqlsrv:server=$server;Database=$database", $uid, $pwd); $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch( PDOException $e ) { die( "Error connecting to SQL Server".$e->getMessage());
}
// Statement
$sql = " DECLARE @date VARCHAR(19) SET @date = CONVERT(VARCHAR(19), GETDATE(), 126) SET @date = REPLACE(@date, ':', '-') SET @date = REPLACE(@date, 'T', '-') DECLARE @fileName VARCHAR(100) SET @fileName = ('d:\backup\BackUp_' + @date + '.bak') BACKUP DATABASE dbname TO DISK = @fileName WITH FORMAT, STATS = 1, MEDIANAME = 'SQLServerBackups', NAME = 'Full Backup of dbname'; "; try { $stmt = $conn->prepare($sql);
$stmt->execute(); } catch (PDOException $e) {
die ("Error executing query. ".$e->getMessage()); } // Clear buffer try { while ($stmt->nextRowset() != null){};
echo "Success";
} catch (PDOException $e) { die ("Error executing query. ".$e->getMessage());
}
// End
$stmt = null; $conn = null;
?>