2009-04-15 25 views
23

Trang web của tôi khá rộng rãi và gần đây tôi đã chuyển sang PHP5 (gọi cho tôi là người viết tắt muộn).CHỌN * TỪ trong MySQLi

Tất cả các truy vấn MySQL của tôi trước khi được xây dựng như vậy:

"SELECT * FROM tablename WHERE field1 = 'value' && field2 = 'value2'"; 

này đã làm cho nó rất dễ dàng, đơn giản và thân thiện.

Tôi hiện đang cố gắng chuyển sang mysqli vì lý do bảo mật rõ ràng và tôi đang gặp khó khăn trong việc tìm cách thực hiện cùng một truy vấn SELECT * FROM khi yêu cầu đối số cụ thể.

Tuyên bố này có phải là điều của quá khứ không?

Nếu có, làm cách nào để xử lý truy vấn có hàng tấn cột liên quan? Tôi có thực sự cần phải loại tất cả chúng ra mỗi lần?

Trả lời

32
"SELECT * FROM tablename WHERE field1 = 'value' && field2 = 'value2'"; 

trở thành

"SELECT * FROM tablename WHERE field1 = ? && field2 = ?"; 

được truyền cho $mysqli::prepare:

$stmt = $mysqli->prepare(
    "SELECT * FROM tablename WHERE field1 = ? && field2 = ?"); 
$stmt->bind_param("ss", $value, $value2); 
// "ss' is a format string, each "s" means string 
$stmt->execute(); 

$stmt->bind_result($col1, $col2); 
// then fetch and close the statement 

comments OP:

vì vậy nếu tôi có 5 thông số, tôi có thể có khả năng có " sssis "hoặc một cái gì đó (tùy thuộc vào loại đầu vào?)

Phải, một Bộ xác định kiểu mỗi ? tham số trong báo cáo kết quả chuẩn bị, tất cả trong số họ thuộc vị trí (specifier đầu tiên áp dụng cho ? đầu tiên được thay thế bằng tham số thực tế đầu tiên (đó là tham số thứ hai để bind_param)).

mysqli sẽ xử lý việc thoát và trích dẫn (tôi nghĩ).

+2

vì vậy nếu tôi có 5 tham số, tôi có thể có khả năng có "sssis" hoặc một cái gì đó (tùy thuộc vào loại đầu vào?) – johnnietheblack

+1

chính xác là – OverlordvI

2

Tuyên bố này có phải là điều của quá khứ không?

Có. Không sử dụng SELECT *; đó là một cơn ác mộng bảo trì. Có rất nhiều chủ đề khác trên SO về lý do tại sao cấu trúc này là xấu và cách tránh nó sẽ giúp bạn viết các truy vấn tốt hơn.

Xem thêm:

+0

okay ... i hoàn toàn tin tưởng bạn, nhưng im gặp khó khăn trong việc tìm kiếm chúng bằng cách nào đó, và tôi có thể học hỏi từ họ im chắc chắn. coudl bạn cho tôi một liên kết? cảm ơn :) – johnnietheblack

+0

Tôi nghĩ câu hỏi là về các biến liên kết. Tôi thấy không có vấn đề lớn với "SELECT *" (nếu bạn cần nhiều hơn chỉ là khóa chính hoặc các cột được lập chỉ mục khác). – Thilo

+0

Vâng, các công cụ tìm kiếm không thích truy vấn "SELECT *" nhiều; Tôi đã chỉnh sửa bài đăng của mình bằng một vài liên kết (liên kết đầu tiên đặc biệt hữu ích). – kquinn

2

Bạn vẫn có thể sử dụng nó (mysqli chỉ là một cách để giao tiếp với máy chủ, ngôn ngữ SQL chính nó là mở rộng, không thay đổi). Tuy nhiên, Prepared statements an toàn hơn - vì bạn không cần phải trải qua những rắc rối khi thoát đúng giá trị của bạn mỗi lần. Bạn có thể để chúng như chúng được, nếu bạn muốn nhưng rủi ro của con heo đất sql được giảm nếu bạn chuyển đổi.

+0

Đôi khi bạn thậm chí cần * sử dụng cũ. Mysql không thể làm nhiều chèn trong một tuyên bố chuẩn bị ví dụ. – soulmerge

+0

không thể? không phải là điều mà hầu hết mọi người cần phải làm? – johnnietheblack

+0

Không, nó không thể làm một cái gì đó như INSERT INTO A (a, b) GIÁ TRỊ (1,2), (3,4), (5,6). Và * nếu * (và chỉ nếu) tốc độ là một vấn đề (không nên trong 99% các trường hợp - nhưng chúng ta chỉ có một trong một dự án gần đây), hãy xem xét điều này: các câu lệnh chuẩn bị cần 3 thông tin liên lạc cho 1 truy vấn (chuẩn bị, đặt var, thực hiện) – soulmerge

6

Trong khi bạn đang chuyển đổi, chuyển sang PDO thay vì mysqli, Nó giúp bạn viết mã agnositc cơ sở dữ liệu và có các tính năng tốt hơn cho các câu lệnh đã chuẩn bị.

http://www.php.net/pdo

Bindparam cho PDO: http://se.php.net/manual/en/pdostatement.bindparam.php

$sth = $dbh->prepare("SELECT * FROM tablename WHERE field1 = :value1 && field2 = :value2"); 
$sth->bindParam(':value1', 'foo'); 
$sth->bindParam(':value2', 'bar'); 
$sth->execute(); 

hay:

$sth = $dbh->prepare("SELECT * FROM tablename WHERE field1 = ? && field2 = ?"); 
$sth->bindParam(1, 'foo'); 
$sth->bindParam(2, 'bar'); 
$sth->execute(); 

hoặc thực hiện với các thông số như một mảng:

$sth = $dbh->prepare("SELECT * FROM tablename WHERE field1 = :value1 && field2 = :value2"); 
$sth->execute(array(':value1' => 'foo' , ':value2' => 'bar')); 

Sẽ dễ dàng hơn nếu bạn muốn ứng dụng của mình có thể chạy trên các cơ sở dữ liệu khác nhau trong tương lai.

Tôi cũng nghĩ bạn nên đầu tư một chút thời gian vào việc sử dụng một số lớp học từ Zend Framwework trong khi làm việc với PDO. Hãy xem Zend_Db và cụ thể hơn [Zend_Db_Factory] [2]. Bạn không cần phải sử dụng tất cả các khung công tác hoặc chuyển đổi ứng dụng của bạn sang mô hình MVC, nhưng việc sử dụng khung công tác và đọc trên đó là thời gian được sử dụng tốt.

+1

tuyệt vời, iv không bao giờ nghe nói về PDO, bệnh kiểm tra nó ra – johnnietheblack

50

Điều này đã được một tháng trước, nhưng tốt thôi.

Tôi có thể sai, nhưng đối với câu hỏi của bạn, tôi có cảm giác rằng bind_param không thực sự là vấn đề ở đây. Bạn luôn cần phải xác định một số điều kiện, có thể là trực tiếp trong chuỗi truy vấn, bằng cách sử dụng bind_param để đặt các trình giữ chỗ ?. Đó không thực sự là một vấn đề.

Sự cố tôi đã sử dụng các truy vấn MySQLi SELECT * là phần bind_result. Đó là nơi nó trở nên thú vị. Tôi đã xem bài đăng này từ Jeffrey Way: http://jeff-way.com/2009/05/27/tricky-prepared-statements/ (Liên kết này không còn hoạt động nữa). Kịch bản về cơ bản lặp qua các kết quả và trả về chúng như là một mảng - không cần biết có bao nhiêu cột, và bạn vẫn có thể sử dụng các câu lệnh đã được chuẩn bị sẵn sàng.

Trong trường hợp này nó sẽ giống như thế này:

$stmt = $mysqli->prepare(
    'SELECT * FROM tablename WHERE field1 = ? AND field2 = ?'); 
$stmt->bind_param('ss', $value, $value2); 
$stmt->execute();

Sau đó sử dụng đoạn mã từ trang web:

$meta = $stmt->result_metadata(); 

while ($field = $meta->fetch_field()) { 
    $parameters[] = &$row[$field->name]; 
} 

call_user_func_array(array($stmt, 'bind_result'), $parameters); 

while ($stmt->fetch()) { 
    foreach($row as $key => $val) { 
    $x[$key] = $val; 
    } 
    $results[] = $x; 
}

$results bây giờ chứa tất cả các thông tin từ SELECT *. Cho đến nay tôi thấy đây là một giải pháp lý tưởng.

+5

Cảm ơn, đây là vấn đề chính xác cùng tôi đã có, câu trả lời chấp nhận sẽ không làm việc với SELECT * – 0plus1

+1

Giải pháp tốt nhất, cảm ơn. – catalin87

+1

Tuyệt vời. cảm ơn bạn và bằng cách gửi lại - echo json_encode ($ results); , Tôi lấy lại những gì tôi muốn HOÀN TOÀN. –

0

Tôi đang tìm kiếm một ví dụ tốt đẹp và đầy đủ về cách liên kết nhiều tham số truy vấn với bất kỳ truy vấn SELECT, INSERT, UPDATE và DELETE nào. Alec đề cập đến câu trả lời của ông là cách kết nối kết quả, đối với tôi hàm get_result() after execute() cho các truy vấn SELECT hoạt động tốt và có thể truy xuất tất cả các kết quả đã chọn vào một mảng các mảng kết hợp.

Dù sao, tôi đã kết thúc việc tạo hàm mà tôi có thể tự động liên kết bất kỳ số lượng tham số nào với truy vấn được parametrized (sử dụng hàm call_user_func_array) và nhận kết quả thực hiện truy vấn.Dưới đây là các chức năng với tài liệu hướng dẫn của nó (xin vui lòng đọc trước khi nó trước khi sử dụng - đặc biệt là tham số $paremetersTypes - Type specification chars là quan trọng để hiểu) sử dụng

 /** 
    * Prepares and executes a parametrized QUERY (SELECT, INSERT, UPDATE, DELETE) 
    * 
    * @param[in] $dbConnection mysqli database connection to be used for query execution 
    * @param[in] $dbQuery parametrized query to be bind parameters for and then execute 
    * @param[in] $isDMQ boolean value, should be set to TRUE for (DELETE, INSERT, UPDATE - Data manipulaiton queries), FALSE for SELECT queries 
    * @param[in] $paremetersTypes String representation for input parametrs' types as per http://php.net/manual/en/mysqli-stmt.bind-param.php 
    * @param[in] $errorOut A variable to be passed by reference where a string representation of an error will be present if a FAUILURE occurs 
    * @param[in] $arrayOfParemetersToBind Parameters to be bind to the parametrized query, parameters need to be specified in an array in the correct order 
    * @return array of feched records associative arrays for SELECT query on SUCCESS, TRUE for INSERT, UPDATE, DELETE queries on SUCCESS, on FAIL sets the error and returns NULL 
    */ 
    function ExecuteMySQLParametrizedQuery($dbConnection, $dbQuery, $isDMQ, $paremetersTypes, &$errorOut, $arrayOfParemetersToBind) 
    { 
     $stmt = $dbConnection->prepare($dbQuery); 

     $outValue = NULL; 

     if ($stmt === FALSE) 
      $errorOut = 'Failed to prepare statement for query: ' . $dbQuery; 
     else if (call_user_func_array(array($stmt, "bind_param"), array_merge(array($paremetersTypes), $arrayOfParemetersToBind)) === FALSE) 
      $errorOut = 'Failed to bind required parameters to query: ' . $dbQuery . ' , parameters :' . json_encode($arrayOfParemetersToBind); 
     else if (!$stmt->execute()) 
      $errorOut = "Failed to execute query [$dbQuery] , erorr:" . $stmt->error; 
     else 
     { 
      if ($isDMQ) 
       $outValue = TRUE; 
      else 
      { 
       $result = $stmt->get_result(); 

       if ($result === FALSE) 
        $errorOut = 'Failed to obtain result from statement for query ' . $dbQuery; 
       else 
        $outValue = $result->fetch_all(MYSQLI_ASSOC); 
      } 
     } 

     $stmt->close(); 

     return $outValue; 
    } 

:

$param1 = "128989"; 
    $param2 = "some passcode"; 


    $insertQuery = "INSERT INTO Cards (Serial, UserPin) VALUES (?, ?)"; 
    $rowsInserted = ExecuteMySQLParametrizedQuery($dbConnection, $insertQuery, TRUE, 'ss', $errorOut, array(&$param1, &$param2)); // Make sure the parameters in an array are passed by reference 

    if ($rowsInserted === NULL) 
     echo 'error ' . $errorOut; 
    else 
     echo "successfully inserted row"; 


    $selectQuery = "SELECT CardID FROM Cards WHERE Serial like ? AND UserPin like ?"; 
    $arrayOfCardIDs = ExecuteMySQLParametrizedQuery($dbConnection, $selectQuery, FALSE, 'ss', $errorOut, array(&$param1, &$param2)); // Make sure the parameters in an array are passed by reference 

    if ($arrayOfCardIDs === NULL) 
     echo 'error ' . $errorOut; 
    else 
    { 
     echo 'obtained result array of ' . count($arrayOfCardIDs) . 'selected rows'; 

     if (count($arrayOfCardIDs) > 0) 
      echo 'obtained card id = ' . $arrayOfCardIDs[0]['CardID']; 
    } 
+0

http://php.net/manual/en/mysqli-result.fetch-all.php –

+0

Thông báo lỗi dưới dạng tham số hàm chỉ là một điều kì quái. lỗi phải là lỗi. http://php.net/manual/en/function.trigger-error.php –

+0

$ isDMQ và $ paremetersTypes phải là tùy chọn –