Dạy thiết kế web - Hướng dẫn thiết kế web, Kỹ thuật thiết kế website

Không suy nghĩ thấu đáo: CSDL & SQL

Xem kết quả: / 2
Bình thườngTuyệt vời 
Số cách người ta truy cập cơ sở dữ liệu (CSDL - database) và lấy kết quả nhiều đến mức thực sự ngạc nhiên. Những thí dụ tôi đã gặp bao gồm những tổ hợp lệnh if và vòng lặp do.. while, các câu gọi nhiều lần, và các hàm sql_result() trong vòng for.
Những người này có nghĩ họ đang làm gì không?

Việc viết các mã trật-hoặc-trúng (hit-or-miss code) chứng minh sự thiếu tập trung. Những cá nhân đó xác định nỗ lực của họ dùng để hoàn thành công việc hơn là để hoàn thành đúng công việc, kết quả là làm cho các ông chủ quăng thời gian và tiền bạc ra đường.

Sự lấy mẫu không chính xác là một thí dụ hay về vấn đề này. Vài người viết lệnh không dành thời gian để nghĩ thấu đáo. Đúng là không chỉ có duy nhất một cách “đúng” để lấy mẫu dữ liệu, nhưng nó có rất nhiều cách không đúng.

Phần này bao gồm các chủ đề:

  •    Áp dụng sai các hàm về CSDL
  •     Dùng sai SQL: không lấy những thứ bạn cần
  •     Dùng PHP để sắp xếp kết quả

1. Dùng sai các hàm CSDL
Một đoạn mã PHP đã dùng cú pháp sau để lấy kết quả từ CSDL (presented below using a generalized set of SQL functions):

Mã lệnh (PHP)

if (!($row = sql_fetch_row ($result))) {
print "An error occurred: no rows found";
exit;
}

do {
print "$row[0]: $row[1]\n
\n";
} while ($row = sql_fetch_row ($result));

Chú ý: Ở trên, và các thí dụ sau nữa, $result diễn tả handle hoặc pointer đến một tập kết quả truy vấn.. Nói cách khác, một truy vấn đã được gửi và một tập kết quả đã được trả về. Các thí dụ sẽ nói về vấn đề thao với với kết quả trả về.

Có một vài vấn đề với đoạn mã trên:
Nó kiểm tra các trường hợp “không tìm thấy” ("no incidents" case) bằng cách lấy một dòng
Nó không lưu kết quả vào mảng liên kết (associative array)
1.1. Kiểm tra trường hợp không tìm thấy: cách làm sai
Bằng cách dùng sql_fetch_row(), PHP chủ trương một cách tiếp cận hàm ẩn cho việc xác định có kết quả tìm thấy hay không. Một cách khác trực tiếp và tường minh là đếm số dòng của kết quả bằng sql_num_rows() như dưới đây:

Mã lệnh (PHP)

<?php
if (sql_num_rows ($result) <= 0) {
print "An error occurred: no rows found";
exit;
}

while ($row = sql_fetch_row ($result)){
print "$row[0]: $row[1]\n
\n";
}
?>


1.2. Từ bỏ vòng lặp Do..While
Trước hết và trên hết, vòng lặp thô tục do..while không bao giờ cần nữa vì khi dùng sql_num_row(), chúng ta không phải lấy dòng đầu tiên của kết quả khi muốn kiểm tra kết quả trống.

Thí dụ cũ đã diễn tả một thí dụ mà trong đó, nếu kết quả không rỗng, dòng đầu tiên đã được lấy bằng hàm sql_fetch_row() trong câu lệnh if. Cấu trúc do..while cần thiết trong trường hợp này vì khi đó, bộ đếm của CSDL đã tăng lên và chuyển sang dòng kế tiếp. Do đó, bạn phải xử lí (lệnh do)dòng đầu tiên vì nó đã được lấy. Các lệnh tiếp theo lấy các dòng kế, và cứ thế.

Tại sao vòng do..while bị coi như thô tục, xấu xa (nasty)?
Trong thí dụ trên, chỉ có 1 lệnh in kết quả trong vòng lặp. Hãy tưởng tượng, nếu có 10 lệnh, người đọc mã phải tìm điều kiện while sau các câu lệnh đó. Một công việc phiền toái.
Điều kiện While bắt đầu cấu trúc thường xuyên hơn là kết thúc. Một nhà nghiên cứu sẽ phải cẩn thận hơn để không nhầm lẫn điều kiện while cuối với điều kiện while đầu.
1.3. Giữ mọi thứ gọn gàng và đơn giản

Với trường hợp kết quả rỗng, sql_num_rows()đưa đến ngay kết quả, trong khi sql_fetch_row() thì không
sql_fetch_row() nói rằng "Tôi tìm thấy 0 dòng trong tập kết quả. Điều này nghĩa là có 0 kết quả” (I found no rows in the result set. This must mean that there are none.)
sql_num_rows() nói rằng “Số dòng trong kết quả là 0” (The number of rows in the result set is 0).
Nhưng điều đó thực sự tạo nên sự khác biệt nào?

Xét cùng một sự so sánh, nhưng bây giờ là trong ngữ cảnh của điều kiện if và của biểu thức, trong đoạn lệnh giả (Pseudo-code):
if(!($row = sql_fetch_row($result))){Print Error}:
lấy 1 dòng trong tập kết quả
nếu kết quả rỗng, gán cho $row giá trị zero (0); 0 có giá trị logic là False, do đó !(0) = True; in thông báo lỗi.
nếu không rỗng, lấy dòng đầu tiên và gán nó vào $row; $row không phải là zero và có giá trị là True. Do đó !(True) = False, và tiếp tục với cấu trúc do..while.
if((sql_num_rows($result)<= 0){Print Error}:
đếm số dòng trong tập kết quả.
Nếu nhỏ hơn hay bằng 0, in thông báo lỗi.
Nếu không, tiếp tục.
Biểu thức nào dể hiểu hơn? Rõ ràng là cách đếm sẽ trực tiếp và gọn gàng hơn.

Sự khác biệt thực tế là gì? Với một lệnh if đơn giản, chúng ta không thu được lợi nhều.

Tuy nhiên, với hơn 10 000 dòng lệnh, hãy dành thời gian nghĩ đến cách rõ ràng nhất, nó sẽ tiết kiệm cho người phân tích chương trình nhiều giờ suy nghĩa. Lợi ích khác có thể kể đến là chương trình của bạn sẽ nhanh hơn và dễ phát triển hơn.

1.4. Khi mà DBMS của bạn không hỗ trợ sql_num_row()
Vài DBMS có thể không hỗ trợ hàm sql_num_row(). Tôi xin chia sẻ với bạn nếu DBMS của bạn là một trong số đó. Bạn sẽ phải tìm trong kết quả rỗng bằng cách lấy dòng. Tuy nhiên, trong trường hợp này, nó nên dùng một biến boolean như sau:

Mã lệnh (PHP)

<?php
$found = false;

while ($row = sql_fetch_array($result)){
$found = true;
}

if (!$found){
print "Error";
}
?>


1.5. Lấy kết quả: hãy chọn cách có ích

Vấn đề thứ hai trong đoạn mã này là nó dùng sql_fetch_row() để lấy tập kết quả. Hàm sql_fetch_row() chỉ trả về mảng đánh chỉ số, trong khi đó sql_fetch_array() trả về mảng đánh chỉ số và mảng dùng chuỗi.

Mã lệnh (PHP)

$row = sql_fetch_array ($result);
print $row[1]; // Second column
print $row[name]; // The name column


Chú ý: Có nhiều quy ước khác nhau về việc dùng dấu nháy khi thêm một đối số kiểu chuỗi. Trong thí dụ về tên cột ở trên, và suốt bài viết này, nó sẽ được bỏ.

Từ quan điểm của nhà phát triển, hàm nào có lợi hơn? Mảng dùng chuỗi giúp cho người đọc hiểu được bạn đang lấy cái gì chỉ thông qua việc đọc mã, như thí dụ đúng dưới đây:

Mã lệnh (PHP)

<?php
if (sql_num_rows ($result) <= 0) {
print "An error occurred: no rows found";
exit;
}

while ($row = sql_fetch_array ($result)) {
print "$row[name]: $row[phone_number]\n
\n";
}
?>


1.6. Khi nào sql_fetch_row($result) nên được dùng
Tôi không thực sự là fan của the sql_fetch_row(). Tuy nhiên, có một tình huống mà dùng nó không giảm khả năng dễ đọc: khi người dùng định nghĩa câu truy vấn.

Các thí dụ cho đến lúc này đều đề cập đến những câu truy vấn được biết trước. Đôi khi bạn để cho người dùng tự định nghĩa câu truy vấn. Trường hợp này bạn sẽ không biết các cột trong kết quả.

Do đó, dùng hàm sql_fetch_row() kèm với count() sẽ xử lí hiệu quả các cột trong một hàng:

Mã lệnh (PHP)

<?php
for ($i = 0; $i < count($row); $i++){
print "Column". ($i + 1). $row[$i]. "\n<BR>\n";
}
?>


2. Dùng sai SQL: không lấy những gì bạn cần

Như là vấn đề của thực hành, đơn giản là sẽ sai lầm khi dùng PHP xử lí mọi dòng của CSDL. Tôi đã bắt gặp người ta dùng PHP để chạy một chương trình tìm kiếm đơn giản trên 2MB dữ liệu và tự hỏi tại sao cái ngôn ngữ này chạy lâu thế. Lấy 2MB dữ liệu từ CSDL có thể làm bạn chờ mãi mãi.

Ngôn ngữ truy vấn chuẩn (Standard Query Language - SQL) được thiết kế đặc biệt để truy vấn và lấy dữ liệu từ các bảng của bạn. Ý tưởng là dùng nó để lọc dữ liệu không cần thiết, để lại các thông tin liên quan cho PHP xử lí.

Nếu bạn lấy nhiều dữ liệu hơn cần thiết, đó là dấu hiệu chắc chắn rằng mã SQL đang dùng chưa được tối ưu hoá.

2.1. Mệnh đề WHERE
Một thí dụ kinh điển về sự hiểu quả của SQL liên quan đến mệnh đề where.

Đoạn mã sau sẽ lấy các kết quả và in ra tên và số điện thoại của người có id là 5:

Mã lệnh (PHP)

<?php
//
// The connection is established and $conn is
// defined as the connection handle before this
// code.

$statement = "SELECT name, phone, id FROM samp_table";
$result = @sql_query ($statement, $conn);

if (!$result) {
die (sprintf ("Error [%d]: %s",
sql_errno (), sql_error ()));
}

if (@sql_num_rows ($result) <= 0) {
die ("No results retrieved from Database");
}

while ($row = @sql_fetch_array ($result)){
if ($row[id] & 5) {
print "Name: $row[name]\n
\n";
print "Phone: $row[phone]\n
\n";
break;
}
}
?>


Đoạn mã trên chưa được tối ưu: chúng ta đang dùng PHP để tìm kiếm trong toàn bộ CSDL! Nếu như điều này không quan trọng đối với các CSDL nhỏ, khi kích thước CSDL tăng lên bạn sẽ cảm thấy một cú đấm nặng nề về hiệu năng.

Lời giải rất đơn giản: sửa câu SQL để chứa mệnh đề WHERE:

Mã lệnh (PHP)
$statement = "SELECT name, phone FROM samp_table";
$statement .= " WHERE id='5'";


Mệnh đề WHERE cho phép bạn tìm kiếm chọn lọc hơn. Giới hạn chọn lọc của mệnh đề where chính là một hàm với đối số của nó. Trong thí dụ trên đối số là "id=5".

Bây giờ chúng ta đã chọn được dữ liệu cần thiết, bạn chỉ việc dùng PHP để in ra sau đó:

Mã lệnh (PHP)

if (@sql_num_rows ($result) != 1) {
die ("Incorrect number of results retrieved from DB");
}

$row = @sql_fetch_array ($result);
print "Name: $row[name]\n
\n";
print "Phone Number: $row[phone]\n
\n";

3. Dùng PHP sắp xếp kết quả

Nhiều người lấy dữ liệu ở tình trạng không có thứ tự, nhưng rồi đoạn mã PHP tiếp theo lại sắp thứ tự chúng. Nên chớ rằng sắp xếp bằng SQL nhanh hơn PHP.

Dùng cú pháp ORDER BY của SQL để sắp xếp thay vì hàm ksort() của PHP.

Thí dụ dưới đây dùng ksort() để sắp xếp theo tên:

Mã lệnh (PHP)

$statement = "SELECT name, email, phone FROM some_table ";
$statement .= "WHERE name IS LIKE '%baggins'";

$result = @sql_db_query ($statement, "samp_db", $conn);

if (!$result) {
die (sprintf ("Error [%d]: %s",
sql_errno (),sql_error ()));
}

while ($row = @sql_fetch_array ($result)){
$matches[ $row[name] ] = array ($row[email],
$row[phone]);
}

ksort ($matches);

Nhưng tại sao không sắp xếp dữ liệu ngay vào lúc nó được định nghĩa? Nó giúp chúng ta đỡ phải duyệt qua tập kết quả lần thứ hai.

Do vậy, bỏ hàm ksort() ra khỏi chương trình trên và thay đoạn mã SQL bằng đoạn dưới đây, có dùng dùng cú pháp ORDER BY:

Mã lệnh (PHP)

$statement = "SELECT name, email, phone FROM some_table ";
$statement .= "WHERE name IS LIKE '%baggins' ORDER BY name";
 
Nguồn http://zensoft.vn/showArticle.aspx?ID=10684
 
 
 

Khắc phục lỗi

Công cụ thiết kế website

Top 10 Add-on “hot” cho Firefox Top 10 Add-on “hot” cho Firefox Firefox vẫn nổi tiếng với hệ ...
Tool upload và download từ server Tool upload và download từ server FTP Commander 7.40 - chương trình ...
Một số trang web cung cấp tool online Một số trang web cung cấp tool online 1. Web 2.0 Badges – Tạo badges ...
Tool hỗ trợ làm flash mạnh mẽ nhất Tool hỗ trợ làm flash mạnh mẽ nhất Với SWiSH Max2 bạn có thể ...
Firebug -kiểm tra website Firebug -kiểm tra website Firebug là một công cụ chủ ...

Ebook

Ebooks Flash CS3 (english) Foundation Flash CS3 for Designers What you’ll ...
24h học Action scipts Dưới đây là tài liệu dùng để học action ...
Ebook học JavaScript Ebook học JavaScript bao gồm cả Tiếng Anh và ...
Ebook web nghe nhạc trực tuyến Bạn đang có ý định làm một website nghe ...
Tài liệu tiếng việt về PHP Biên soạn bởi: Mr. Cảnh Phúc Hiệu trưởng ...

Tin tức

Những tên miền Những tên miền "nguy hiểm nhất thế giới" Đó là những tên miền quốc gia Cameroon (.cm), ...
Tạo website trực tuyến, chuyên nghiệp, miễn phí Tạo website trực tuyến, chuyên nghiệp, miễn phí Nhằm phục vụ cho nhu cầu học tập, trao đổi, ...
Thiết kế Website và Làm thế nào để có 1 website ? Thiết kế Website và Làm thế nào để có 1 website ? Để có một website bạn phải tiến hành những ...
Các loại website Các loại website Có rất nhiều loại website nhưng có thể phân ...
Domain là gì ? Domain là gì ? Tên miền (Domain name) là định danh của website ...

Thăm dò

Bạn quan tâm về website ở điểm nào ?