2009-10-25 27 views
8

Tôi đang phát xung quanh với các câu lệnh chuẩn bị trong PHP/PDO. Các truy vấn cơ bản hoạt động tốt, chuyển một giá trị đến mệnh đề WHERE:Các mã thông báo nào có thể được tham số hóa trong các câu lệnh chuẩn bị PDO?

$stmt = $db->prepare('SELECT title FROM episode WHERE id=:id'); 
$stmt->bindParam(':id', $id, PDO::PARAM_INT); 
$id = 5; 
$stmt->execute(); 

Tuy nhiên tôi có một tình huống mà tôi cần phải chuyển các biến cho tên trường. Truy vấn này (với phù hợp ràng buộc) hoạt động tốt:

SELECT :field FROM episode WHERE id=:id 

một này đưa ra một lỗi:

SELECT title FROM :field WHERE id=:id 

Cái này không đưa ra một lỗi, nhưng trả về không có hàng:

SELECT title FROM episode WHERE :field=:id 

Vì vậy, những gì mọi thứ nên làm việc trong các báo cáo chuẩn bị? Tôi có thể 'tham số hóa' tên trường, tên bảng và vân vân không?

Trả lời

10

Bạn không thể tham số hóa tên bảng, tên cột hoặc bất kỳ thứ gì trong mệnh đề IN (nhờ c0r0ner cho pointing out the IN clause restriction).

Xem this question và sau đó this comment in the PHP manual.

+0

Cảm ơn bạn đã trả lời. Hóa ra truy vấn đầu tiên tôi đăng không hoạt động - nếu bạn liên kết, giả sử ''title'' thành': field' thì nó chỉ chọn chuỗi' title 'chứ không phải giá trị của trường. Lạ lùng là không có phương pháp để ràng buộc các cột/bảng, vì bây giờ tôi phải thêm một số bảo mật bổ sung, mà PDO được cho là sẽ xử lý cho tôi:/ – DisgruntledGoat

+0

Suy nghĩ đằng sau điều này có thể là bạn thực sự không nên để người dùng trực tiếp chọn trường/bảng mà truy vấn của bạn đang gọi. Nhưng tôi đồng ý rằng nó sẽ bổ sung thêm một chút công sức cho bạn. –

+0

Tôi thấy quan điểm của bạn. Tuy nhiên, tôi đang sử dụng nó trong một tình huống mà chỉ tôi chỉ định các bảng, nhưng theo một cách trừu tượng, ví dụ: 'displayTable ('tập')'. Tôi đoán tôi không thực sự cần phải lo lắng về các thông số/bảo mật trong trường hợp này. – DisgruntledGoat

1

@ Josh Leitzel

Đó suy nghĩ là rất hạn chế (và là theo ý kiến ​​của tôi chỉ là cái cớ cho quá lười biếng để thực hiện một giải pháp mạnh mẽ), đặc biệt là cho các cấu trúc cây động bày tỏ trong một cơ sở dữ liệu.

Hãy xem xét ví dụ sau:

dự án của tôi có một cấu trúc logic:

Một hệ thống phân cấp công ty được thể hiện về mặt thực thể. Mỗi thực thể có thể được xử lý trong trường hợp chung là một thành viên của hệ thống phân cấp hoặc là thành viên của một cấp cụ thể của hệ thống phân cấp. Các hệ thống phân cấp tự nó được định nghĩa trong một bảng như một cành cây đơn như sau:

entity_structure (
    id 
    name 
    parent_entity_structure_id 
); 

và các thực thể tự được biểu diễn như:

entities (
    id 
    name 
    entity_structure_id 
    parent_id 
); 

Để dễ sử dụng tôi đã xây dựng một thuật toán tạo một cái nhìn bằng phẳng của cây. Các ví dụ cụ thể dưới đây minh họa những gì tôi có nghĩa là:

SELECT * FROM entity_structure; 

id  | name    | entity_structure_parent_id 
----------------------------------------------------------- 
1  | Company   | null (special one that always exists) 
2  | Division   | 1 
3  | Area    | 2 
4  | Store    | 3 

Điều này sẽ dẫn đến việc đại diện phẳng sau được sản xuất:

entity_tree (
    entity_id 
    division_id 
    area_id 
    store_id 
) 

Đối tượng mà là ở cấp bộ phận sẽ phải division_id, area_id và store_id như NULL , Diện tích area_id và store_id là NULL, v.v.

Điều tốt đẹp về điều này là nó cho phép bạn truy vấn tất cả các con của một bộ phận sử dụng câu lệnh tương tự như sau:

SELECT * FROM entity_tree WHERE division_id = :division_id; 

Tuy nhiên điều này giả định rằng tôi biết mức cấu trúc của thực thể tôi đang truy vấn.Nó sẽ được tốt đẹp để làm:

SELECT * FROM entity_tree WHERE :structure = :entity_id; 

Tôi biết nó không phải là khó để tìm ra mức độ cấu trúc của một thực thể duy nhất, nhưng giả sử tôi đang lặp thông qua một tập hợp các thực thể có thể không phải tất cả có cùng cấp . Như bây giờ tôi phải xây dựng một truy vấn riêng biệt cho mỗi cấp độ của hệ thống phân cấp, nhưng nếu tôi có thể parameterize lĩnh vực tôi có thể làm như sau:

$children = array(); 
$stmt = $pdo->prepare('SELECT entity_id FROM entity_tree WHERE :structure = :entityId'); 
foreach ($entities AS $entity) { 
    $stmt->execute(array(
     ':structure' = $entity->getEntityStructureId(), 
     ':entityId' = $entity->getId() 
    )); 

    $children[$entity->getId()] = $stmt->fetchAll(PDO::FETCH_COLUMN); 
} 

kết quả là mã sạch hơn và chỉ có một tuyên bố chuẩn bị.

Toàn bộ ví dụ không sử dụng đầu vào của người dùng nào.

Chỉ cần một cái gì đó để xem xét.

+0

Tuy nhiên, điểm quan trọng là gì? Bạn có thể dễ dàng sử dụng các biến thông thường trong trường hợp này vì không có đầu vào của người dùng. Không có bất kỳ cơ hội tiêm ở đây. Ngoài ra, điều này nên đã được đăng như một bình luận cho câu trả lời của tôi vì đây không phải là câu trả lời cho câu hỏi của OP. (Tôi nhận ra rằng bạn sẽ không thể phù hợp với nó, chỉ cần lưu ý điều này.) –

1

Bạn cũng không thể tham số hóa bất kỳ điều gì trong mệnh đề IN.

+0

Cảm ơn, tôi quên mất điều đó. Tôi sẽ thêm nó vào câu trả lời của tôi. –

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