Sử dụng CSDL MySQL

GIỚI THIỆU

CSDL là 1 phần quan trọng không thể thể thiếu được trong các ứng dụng web chuyên nghiệp. MySQL từ lâu đã là hệ CSDL được dùng phổ biến nhất với PHP vì tính gọn nhẹ, nhanh, miễn phí và được PHP hỗ trợ sẵn. Trong bài viết này chúng ta sẽ tìm hiểu cách kết nối vào CSDL MySQL, truy cập và lưu trữ dữ liệu với PHP.

KẾT NỐI VÀO MYSQL SERVER

PHP cung cấp hàm mysql_connect để kết nối vèo MySQL server. Cú pháp của hàm này như sau:

mysql_connect($server_address, $username, $password)

$server_address là địa chỉ của MySQL server, có thể là domain name hoặc IP address,
các ví dụ trong bài viết này sẽ dùng giá trị “localhost” cho $server_address.
$username là tên account dùng để login vào MySQL server, các ví dụ trong bài viết sẽ sử dụng giá trị “root” cho $username.
$password là mật mã để kết nối vào MySQL server, các ví dụ trong bài viết sẽ sử dụng chuỗi rỗng “” làm mật mã.
Hàm mysql_connect sẽ trả về 1 kết nối đến MySQL server nếu như quá trình kết nối thành công, hoặc trả về giá trị FALSE nếu như kết nối không được.

Để đóng kết nối tới MySQL server, PHP cung cấp hàm mysql_close. Đoạn mã sau ví dụ quá trình kết nối vào MySQL server và đóng kết nối.

<?php $SERVER = "localhost"; $USERNAME = "root";  $PASSWORD = "";    $conn = mysql_connect($SERVER, $USERNAME, $PASSWORD);  if ( !$conn ) {     //Không kết nối được, thoát ra và báo lỗi        die("không nết nối được vào MySQL server"); }    //end if     //đóng kết nối  mysql_close($conn); ?>

CHỌN CSDL ĐỂ LÀM VIỆC

Sau khi connet vào MySQL server, thao tác tiếp theo là chọn CSDL để làm việc. PHP cung cấp cho ta hàm mysql_select_db để làm việc này. Cú pháp của hàm này như sau:

mysql_select_db($db_name[, $conn])

Với $db_name là tên CSDL cần chọn, $conn là kết nối được thực hiện qua lệnh mysql_connect. Các ví dụ trong bài viết này sẽ sử dụng CSDL có tên là test:

<?php  
$SERVER = "localhost";  
$USERNAME = "root";  
$PASSWORD = "";  
$DBNAME = "test";     
$conn = mysql_connect($SERVER, $USERNAME, $PASSWORD);  
if ( !$conn ) {  
   //Không kết nối được, thoát ra và báo lỗi  	
   die("không nết nối được vào MySQL server");  } 
   //end if     
  //chọn CSDL để làm việc  
   mysql_select_db($DBNAME, $conn);     
 //đóng kết nối  mysql_close($conn); 
?>

 THỰC THI 1 CÂU LỆNH SELECT VÀ LẤY KẾT QUẢ TRẢ VỀ

PHP cung cấp cho ta 3 hàm hữu dụng để thực hiện công việc này:

  • $result = mysql_query($sql, $conn): thực hiện câu lệnh SQL được cung cấp qua tham số $sql và trả về 1 kết quả kiểu $result (hàm này trả về FALSE nếu như câu lệnh thực hiện không thành công).
  • mysql_num_rows($result): hàm này trả về số lượng row lấy được qua câu lệnh SELECT (được thực thi bởi hàm mysql_query) trước đó.
  • $row = mysql_fetch_row($result), $row = mysql_fetch_assoc($result): trả về dòng kết quả hiện thời của câu lệnh select và chuyển con trỏ tới dòng tiếp theo (như vậy lệnh gọi mysql_fetch_row hoặc mysql_fetch_assoc tiếp đó sẽ trả về dòng tiếp theo); hoặc giá trị FALSE nếu như không còn dòng nào để trả về nữa. Kết quả trả về từ 2 hàm này là 1 array.
  • mysql_error($conn): trả về thông báo lỗi của MySQL server nếu như một lệnh trước đó có lỗi.

Để hiểu rõ hơn công dụng của các hàm trên, đồng thời phân biệt sự khác nhau giữa 2 hàm mysql_fetch_row và mysql_fetch_assoc, ta cung xem xét các ví dụ sau.

Các ví dụ của ta sẽ sử dụng table có tên là member với các trường và dữ liệu như sau:

usernamepassword
abc123
def456

 

Ví dụ 1: dùng mysql_fetch_row()

<?php $SERVER = "localhost"; $USERNAME = "root"; $PASSWORD = ""; $DBNAME = "test"; $conn = mysql_connect($SERVER, $USERNAME, $PASSWORD); if ( !$conn ) {  //Không kết nối được, thoát ra và báo lỗi die("Connect error MySQL server: ".mysql_error($conn)); } //end if //chọn CSDL để làm việc mysql_select_db($DBNAME, $conn) or die("Không thể chọn được CSDL: ".mysql_error($conn));   $sql = "SELECT * FROM member"; $result = mysql_query($sql, $conn); if ( !$result ) die("Không thực hiện được lệnh SQL: ".mysql_error($conn)); echo "Số lượng row tìm được: ".mysql_num_rows($result)."<br>n";      while ( $row = mysql_fetch_row($result) ) {            echo "Username = ".$row[0]."<br>n";            echo "Password = ".$row[1]."<br>n"; }  //end while//nên luôn giải phóng bộ nhớ sau khi lấy hết các row trả về từ câu lệnh SELECT    mysql_free_result($result); //đóng kết nối mysql_close($conn);   ?>

Hàm mysql_fetch_row() sẽ trả về 1 array mà phần tử thứ [0] sẽ tương ứng với cột đầu tiên của table, phần tử thứ [1] sẽ tương ứng với cột thứ hai của table…Chương trình trên sẽ in ra ra 4 dòng:

Username = abc Password = 123 Username = def Password = 456

Ví dụ 2: dùng mysql_fetch_assoc()

<?php $SERVER = "localhost"; $USERNAME = "root"; $PASSWORD = ""; $DBNAME = "test"; $conn = mysql_connect($SERVER, $USERNAME, $PASSWORD); if ( !$conn ) { //Không kết nối được, thoát ra và báo lỗi die("Connect error MySQL server: ".mysql_error($conn)); } //end if //chọn CSDL để làm việc mysql_select_db($DBNAME, $conn) or die("Không thể chọn được CSDL: ".mysql_error($conn)); $sql = "SELECT * FROM member"; $result = mysql_query($sql, $conn); if ( !$result )die("Không thực hiện được lệnh SQL: ".mysql_error($conn)); echo "Số lượng row tìm được: ".mysql_num_rows($result)."<br>n";   while ( $row = mysql_fetch_assoc($result) ) {         echo "Username = ".$row['username']."<br>n";         echo "Password = ".$row['password']."<br>n"; } //end while //nên luôn giải phóng bộ nhớ sau khi lấy hết các row trả về từ câu lệnh SELECT mysql_free_result($result);  //đóng kết nối mysql_close($conn);   ?>

Hàm mysql_fetch_assoc() sẽ trả về 1 array mà các phần tử sẽ được truy cập qua tên, với tên được lấy từ tên các cột của table. Chương trình ví dụ 2 cũng sẽ in ra ra 4 dòng:

Username = abc Password = 123 Username = def Password = 456

THỰC THI 1 CÂU LỆNH UPDATE, INSERT hoặc DELETE

Hàm mysql_query cũng được dùng để thực thi các câu lệnh DELETE, INSERT hoặc UPDATE, nhưng lúc này hàm sẽ trả về TRUE nếu câu lệnh thực hiện thành công và FALSE trong trường hợp ngược lại. Để lấy số lượng các row được chèn với lệnh INSERT hoặc bị thay đổi bởi lệnh UPDATE, PHP cung cấp cho ta hàm mysql_affected_rows. Ta hãy xem ví dụ sau:

<?php $SERVER = "localhost"; $USERNAME = "root"; $PASSWORD = ""; $DBNAME = "test"; $conn = mysql_connect($SERVER, $USERNAME, $PASSWORD); if ( !$conn ) { //Không kết nối được, thoát ra và báo lỗi die("Connect error MySQL server: ".mysql_error($conn));} //end if //chọn CSDL để làm việc mysql_select_db($DBNAME, $conn) or die("Không thể chọn được CSDL: ".mysql_error($conn)); $sql = "INSERT INTO member (username, password) VALUES ('xyz', '000')"; $result = mysql_query($sql, $conn); //chèn thêm 1 dòng vào table if ( !$result ) die("Không thực hiện được lệnh SQL: ".mysql_error($conn));echo "Số lượng row được chèn: ".mysql_affected_rows($conn)."<br>n"; //ta chỉ chèn 1 dòng nên hàm mysql_affected_rows sẽ trả về 1   $sql = "UPDATE member SET password='111' WHERE username='xyz'"; $result = mysql_query($sql, $conn); //đổi password của accoutn xyz if ( !$result ) die("Không thực hiện được lệnh SQL: ".mysql_error($conn));echo "Số lượng row được thay đổi: ".mysql_affected_rows($conn)."<br>n"; //ta thay đổi 1 dòng nên hàm mysql_affected_rows sẽ trả về 1 $sql = "DELETE FROM member"; $result = mysql_query($sql, $conn); //xoá hết tất cả các account if ( !$result ) die("Không thực hiện được lệnh SQL: ".mysql_error($conn)); echo "Số lượng row được xoá: ".mysql_affected_rows($conn)."<br>n"; //ta xoá tất cả 3 dòng nên hàm mysql_affected_rows sẽ trả về 3 //đóng kết nối mysql_close($conn); ?>

LƯU Ý VẤN ĐỀ BẢO MẬT VỚI LỖI SQL INJECTION

Nếu bạn cần cung cấp 1 tham số cho câu lệnh SQL, nhất là các tham số từ trình duyệt do người dùng nhập vào, bạn hãy lưu ý đề phòng lỗi bảo mật SQL Injection. Giả sử bạn muốn thay đổi mật mã của account xyz, mật mã mới được người dùng nhập vào và lưu vào trong biến $newPwd, đoạn mã đổi password có thể tương tự như sau:

<?php //... $sql = "UPDATE member SET password='$newPwd' WHERE username='xyz'"; mysql_query($sql, $conn); //... ?>

Giả sử người dùng nhập vào mật mã mới là zzz, câu lệnh SQL sẽ trở thành
UPDATE member SET password=’zzz’ WHERE username=’xyz’
Hoàn toàn hợp lệ và đúng đắn, không có gì phải thắc mắc hết.

Nhưng giả sử người dùng nhập vào mật mã mới là zzz’#, câu lệnh SQL sẽ trở thành
UPDATE member SET password=’zzz’#’ WHERE username=’xyz’
Nhưng gì phía sau ký tự # sẽ được MySQL xem là chú thích và sẽ bỏ qua, như vậy câu lệnh SQL của chúng ta trên thực tế sẽ tương đương với:
UPDATE member SET password=’zzz’
Vậy là xong! Sau khi chạy câu lệnh này, password của tất cả các account đều là zzz hết, tất hiên là account admin cũng sẽ bị đổi password thành zzz và lúc này hậu quả tiếp theo ra sao chắc bạn cũng đã rõ!

Để tránh bị SQL injection, khi đưa các tham số vào câu lệnh SQL, bạn nên luôn nhớ và áp dụng 2 điều sau:

  • Nếu tham số là số (số nguyên hoặc số thực), cộng thêm 0 vào tham số trước khi đưa vào câu lệnh SQL. Tức là:
    $thamso+=0;
    $sql = “…$thamso…”;
  • Nếu tham số là chuỗi, sử dụng hàm mysql_real_escape_string trước khi đưa tham số vào câu lệnh SQL. Tức là:
    $thamso = mysql_real_escape_string($thamso, $conn);
    $sql = “…’$thamso’…”;

TRƯỚC KHI KẾT THÚC

Đến đây, bạn đã nắm được các bước cơ bản để làm việc với CSDL MySQL Server:
– Kết nối vào MySQL Server với server address, username và password
– Chọn CSDL để làm việc
– Thao tác với CSDL, Thực thi các lệnh SQL…
– Đóng kết nối khi kết thúc

Trong thực tế, đôi lúc chương trình của bạn cần thực hiện thêm nhiều thao tác nâng cao hơn thế, lúc này bạn đừng quên tham khảo MySQL Manual mục các hàm về MySQL.

CÁC HÀM PHP ĐƯỢC DÙNG TRONG VÍ DỤ