Explanations:
You are using PHP Driver for SQL Server, so the following explanations are an additional option for solving your problem:
- It seems that this issue is probably a driver specific problem. SQL Server fills the output buffer of the connection with the result sets that are created by the batch - information about the count of the affected rows (in a case of
INSERT\DELETE\UPDATE statements for example) or progress status (returned from BACKUP\RESTORE DATABADE statements). These result sets must be processed by the PHP script. It seems that this behavior is by design and the PHP script should flush all the pending result sets. After the result sets are fetched, SQL Server completes the execution of the batch. The appropriate functions\methods that you need to use are sqlsrv_next_result() (for SQLSRV version of the driver) and PDOStatement::nextRowset() (for PDO_SQLSRV version of the driver).
- For the SQLSRV version of the driver you need to change the error and warning handling using
sqlsrv_configure("WarningsReturnAsErrors", 0);.
Examples:
I'm able to reproduce the issue from the question and the following examples are working solutions:
Using SQLSRV version of the 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);
?>
Using PDO_SQLSRV version of the 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;
?>
sqlsrv_queryis getting confused by rowcounts and progress messages coming back from your stored procedure. Try addingset nocount onto the top of your stored procedure, but if that doesn't work then try switching tosqlsrv_prepareinstead ofsqlsrv_query.