2010-03-30 30 views
26

Tôi đang gặp sự cố khi sử dụng thông số trong phần ORDER BY trong SQL của tôi. Nó không đưa ra bất kỳ cảnh báo nào, nhưng in ra không có gì.Làm cách nào để đặt các tham số ORDER BY bằng lệnh PDO chuẩn bị?

$order = 'columnName'; 
$direction = 'ASC'; 

$stmt = $db->prepare("SELECT field from table WHERE column = :my_param ORDER BY :order :direction"); 
$stmt->bindParam(':my_param', $is_live, PDO::PARAM_STR); 
$stmt->bindParam(':order', $order, PDO::PARAM_STR); 
$stmt->bindParam(':direction', $direction, PDO::PARAM_STR); 
$stmt->execute(); 

Các :my_param công trình, nhưng không :order hoặc :direction. Có phải nó không được thoát ra một cách chính xác? Tôi có mắc kẹt chèn nó trực tiếp trong SQL? Giống như vậy:

$order = 'columnName'; 
$direction = 'ASC'; 

$stmt = $db->prepare("SELECT * from table WHERE column = :my_param ORDER BY $order $direction"); 

Có hằng số hoặc tương đương PDO::PARAM_COLUMN_NAME không?

Cảm ơn!

+0

Xem thêm [Tuyên bố PDO của PHP có thể chấp nhận tên bảng làm tham số không?] (Http://stackoverflow.com/q/182287/157957) – IMSoP

Trả lời

12

Tôi không nghĩ rằng bạn có thể:

  • Sử dụng placeholders trong một khoản order by
  • tên cột
  • Bind: bạn chỉ có thể liên kết các giá trị - hoặc các biến, và có giá trị của họ tiêm vào báo cáo kết chuẩn bị .
+3

Thành thật mà nói - nó ** CÓ THỂ có thể liên kết * các giá trị * (không phải định danh) trong mệnh đề 'ORDER BY' – zerkms

+1

Điều này là một phần đúng. Bạn chỉ có thể sử dụng trình giữ chỗ liên kết để cung cấp các giá trị **. Không bao giờ có thể sử dụng trình giữ chỗ liên kết để cung cấp ** số nhận dạng ** (như tên bảng, tên cột), từ khóa ** SQL ** hoặc bất kỳ phần nào khác của cú pháp SQL khác với giá trị **. (Về cơ bản, một trình giữ chỗ ràng buộc có thể thay thế các chuỗi ký tự, một chữ cái theo ngày hoặc một chữ số.Theo thời gian, vì các ký tự zerkm chỉ ra, vì có thể sử dụng các chữ như các phần của một biểu thức trong mệnh đề 'ORDER BY', nó ** thực tế là có thể sử dụng các phần giữ chỗ ràng buộc như một phần của các biểu thức trong mệnh đề 'ORDER BY' – spencer7593

38

Ở đây có câu hỏi cho thấy rộng rãi yêu chuẩn bị phát biểu không phải là bạc đạn, hehe :)

Vâng, bạn đang mắc kẹt chèn nó trực tiếp trong SQL Với một số biện pháp phòng ngừa, tất nhiên. Mỗi nhà khai thác/nhận dạng phải được hardcoded trong kịch bản của bạn, như thế này:

$orders=array("name","price","qty"); 
$key=array_search($_GET['sort'],$orders); 
$order=$orders[$key]; 
$query="SELECT * from table WHERE is_live = :is_live ORDER BY $order"; 

Tương tự cho hướng.

Lưu ý rằng bindParam không thoát, vì không cần phải thoát. nó có ràng buộc.

+0

Nếu bạn có một chuỗi các chuỗi hợp lệ và nhập lại những gì bạn đã có như' $ input = (string) $ đầu vào, 'to **' (chuỗi) '** bạn có thể chỉ cần kiểm tra' if (in_array ($ input, $ valid_orderbys_array)) 'về cơ bản nó sẽ làm như vậy. –

-1

Nếu tôi không hoàn toàn nhầm lẫn, Pascal là đúng.
Chỉ ràng buộc duy nhất trong PDO là ràng buộc các giá trị, như bạn đã làm với tham số ': my_param'.
Tuy nhiên, không có thiệt hại thực hiện trong:

$stmt = $db->prepare("SELECT field from table WHERE column = :my_param ORDER BY ".$order ." ".$direction); 
$stmt->bindParam(':my_param', $is_live, PDO::PARAM_STR); 
$stmt->execute(); 

Điều duy nhất cần chú ý đến sẽ là thoát đúng $order$direction, nhưng kể từ khi bạn cài đặt chúng bằng tay và không đặt chúng thông qua người dùng nhập vào, Tôi nghĩ bạn đã sẵn sàng.

+0

Nếu anh ta không thay đổi cột orderby và hướng, sau đó tôi hy vọng sẽ không có bất kỳ điểm nào trong việc có chúng là biến. – Kzqai

4

Tôi không nghĩ rằng bạn có thể nhận được ASC/DESC như là một phần của tuyên bố chuẩn bị, nhưng cột bạn có thể.

order 
    by 
     case :order 
      when 'colFoo' then colFoo 
      when 'colBar' then colBar 
      else colDefault 
     end 
     $direction 

Vì ASC/DESC chỉ có hai giá trị có thể, bạn có thể dễ dàng xác nhận và chọn giữa chúng làm giá trị được mã hóa.

Bạn cũng có thể sử dụng các hàm ELT (FIELD (,,,,,) ,,,,,) cho điều này, nhưng sau đó đặt hàng sẽ luôn được thực hiện dưới dạng chuỗi, ngay cả khi đó là cột số.

0

Không may, tôi đoán bạn không thể làm điều đó với các câu đã chuẩn bị. Nó sẽ làm cho nó không thể lưu trữ được vì các cột khác nhau có thể có giá trị có thể được sắp xếp với các chiến lược phân loại đặc biệt.

Tạo truy vấn bằng cách sử dụng thoát tiêu chuẩn và thực thi trực tiếp.

-1

Tạo điều kiện nếu không.
Nếu (ascCondion) sau đó liên kết các giá trị nhưng TRÌNH TỰ cứng mã THEO ColumnName ASC
khác
Bind các giá trị nhưng TRÌNH TỰ cứng mã THEO ColumnName DESC

7

Có thể sử dụng chuẩn bị báo cáo trong ORDER BY khoản, không may bạn cần vượt qua thứ tự cột được đặt tên và được yêu cầu đặt PDO_PARAM_INT với loại.

Trong MySQL bạn có thể nhận được thứ tự của các cột với các truy vấn này: Mã

SELECT column_name, ordinal_position FROM information_schema.columns 
WHERE table_name = 'table' and table_schema = 'database' 

PHP:

$order = 2; 

$stmt = $db->prepare("SELECT field from table WHERE column = :param ORDER BY :order DESC"); 
$stmt->bindParam(':param', $is_live, PDO::PARAM_STR); 
$stmt->bindParam(':order', $order, PDO::PARAM_INT); 
$stmt->execute(); 
0

Đó là thể. Bạn có thể sử dụng số thay vì tên trường trong mệnh đề 'order by'. Đây là một số bắt đầu từ 1 và theo thứ tự các tên trường trong truy vấn. Và bạn có thể nối một chuỗi vào cho ASC hoặc DESC. Ví dụ: "Chọn col1, col2, col3 từ thứ tự tab1?" + StrDesc + "giới hạn 10,5". strDesc = "ASC"/"DESC".

Các vấn đề liên quan