Sao lưu cơ sở dữ liệu SQL Server bằng PHP

Sep 22 2020

Tôi đang cố gắng sao lưu cơ sở dữ liệu MS SQL gọi Thủ tục được lưu trữ bằng PHP.

Khi tôi thực thi de SP trên SSMS, mọi thứ hoạt động tốt. Tuy nhiên, khi tôi gọi nó từ tập lệnh PHP, tôi có thể thấy ".bak" trong thư mục sao lưu và ngay sau khi PHP xử lý xong, tệp BackUp.bak biến mất.

Đây là quy trình được lưu trữ:

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

Dưới đây là mã PHP mà tôi gọi là 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);

Tôi đang chạy Apache 2.4.46 và SQL Server Express 2019.

Mục tiêu của tôi là tạo tệp ".bak" bằng PHP.

Tôi đã thử sử dụng SP vì mã gốc được viết bằng Classic ASP và nó hoạt động hoàn hảo theo cách này.

Tôi sẵn sàng thử các cách tiếp cận khác nhau.

Cảm ơn bạn.

Trả lời

Zhorov Sep 24 2020 at 07:46

Giải thích:

Bạn đang sử dụng Trình điều khiển PHP cho SQL Server, vì vậy các giải thích sau là một tùy chọn bổ sung để giải quyết vấn đề của bạn:

  • Có vẻ như vấn đề này có lẽ là một vấn đề cụ thể của trình điều khiển. SQL Server lấp đầy bộ đệm đầu ra của kết nối với các tập kết quả được tạo bởi lô - thông tin về số lượng hàng bị ảnh hưởng ( INSERT\DELETE\UPDATEví dụ: trong trường hợp câu lệnh) hoặc trạng thái tiến trình (trả về từ BACKUP\RESTORE DATABADEcâu lệnh). Các tập kết quả này phải được xử lý bởi tập lệnh PHP. Có vẻ như hành vi này là do thiết kế và tập lệnh PHP sẽ xóa tất cả các tập kết quả đang chờ xử lý. Sau khi các tập hợp kết quả được tìm nạp, SQL Server hoàn thành việc thực thi lô. Các hàm \ phương thức thích hợp mà bạn cần sử dụng là sqlsrv_next_result()(cho phiên bản SQLSRV của trình điều khiển) và PDOStatement::nextRowset()(cho phiên bản PDO_SQLSRV của trình điều khiển).
  • Đối với phiên bản SQLSRV của trình điều khiển, bạn cần thay đổi cách xử lý lỗi và cảnh báo bằng cách sử dụng sqlsrv_configure("WarningsReturnAsErrors", 0);.

Ví dụ:

Tôi có thể tái tạo vấn đề từ câu hỏi và các ví dụ sau là các giải pháp hiệu quả:

Sử dụng phiên bản SQLSRV của trình điều khiển:

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

Sử dụng phiên bản PDO_SQLSRV của trình điều khiển:

<?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;
?>