2009-10-25 11 views
8

Używam gotowych instrukcji w PHP/PDO. Podstawowe pytania działać dobrze, przekazując wartość klauzuli WHERE:Które tokeny można sparametryzować w instrukcjach przygotowanych przez PDO?

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

jednak Mam sytuacji, gdzie trzeba przekazać zmienne do nazw pól. To zapytanie (z odpowiednim wiążący) działa prawidłowo:

SELECT :field FROM episode WHERE id=:id 

Ten daje błąd:

SELECT title FROM :field WHERE id=:id 

ten jeden nie daje błąd, ale nie zwraca żadnych wierszy:

SELECT title FROM episode WHERE :field=:id 

Co zatem powinno działać w przygotowanych oświadczeniach? Czy mogę "sparametryzować" nazwy pól, nazwy tabel i tak dalej?

Odpowiedz

10

Nie można sparametryzować nazw tabel, nazw kolumn ani niczego w klauzuli IN (dzięki c0r0ner dla pointing out the IN clause restriction).

Zobacz this question, a następnie this comment in the PHP manual.

+0

Dzięki za odpowiedź. Okazuje się, że pierwsze wysłane przeze mnie zapytanie nie działa - jeśli powiążesz, powiedz "tytuł" do ": pole", to po prostu wybierze ciąg "tytuł", a nie wartość pola. Dziwne, że nie ma metody wiązania kolumn/tabel, ponieważ teraz muszę dodać dodatkowe zabezpieczenie, które powinno obsługiwać PDO:/ – DisgruntledGoat

+0

Myślenie kryjące się za tym prawdopodobnie polega na tym, że naprawdę nie powinno się pozwolić użytkownicy bezpośrednio wybierają pola/tabele, które wywołuje zapytanie. Ale zgadzam się, że dodaje trochę dodatkowej pracy do końca. –

+0

Widzę twój punkt widzenia. Używam go jednak w sytuacji, w której tylko ja określam tabele, ale w sposób abstrakcyjny, np. 'displayTable ('epizod')'. Chyba nie muszę się martwić o parametry/bezpieczeństwo w tym przypadku. – DisgruntledGoat

1

@ Josh Leitzel

To myślenie jest bardzo restrykcyjne (i jest moim zdaniem tylko wymówka dla bycia zbyt leniwy, aby wdrożyć solidne rozwiązanie), zwłaszcza dynamiczne struktury drzewa wyrażona w bazie danych.

Rozważmy następujący przykład:

Mój projekt ma logiczną strukturę:

Hierarchia firma wyrażonego w jednostkach. Każda jednostka może być traktowana w ogólnym przypadku bycia członkiem hierarchii lub członkiem określonego poziomu hierarchii. Sama hierarchia jest zdefiniowane w tabeli jako pojedynczej gałęzi drzewa w następujący sposób:

entity_structure (
    id 
    name 
    parent_entity_structure_id 
); 

a same jednostki są wyrażone jako:

entities (
    id 
    name 
    entity_structure_id 
    parent_id 
); 

Dla ułatwienia mam wbudowany algorytm, który tworzy płaski widok drzewa. Poniższy konkretny przykład przedstawia to, co oznacza:

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 

Spowodowałoby następujące płaskie przedstawienie produkowane:

entity_tree (
    entity_id 
    division_id 
    area_id 
    store_id 
) 

jednostek, które znajdują się na poziomie podziału musiałby division_id, area_id i store_id NULL , Obszar area_id i store_id jako NULL, itp.

To miło, że pozwala na zapytanie wszystkich dzieci w dziale za pomocą instrukcji podobnej do poniższej:

SELECT * FROM entity_tree WHERE division_id = :division_id; 

Jednak to zakłada, że ​​znam poziom struktury podmiotu, którego szukam.Byłoby miło zrobić:

SELECT * FROM entity_tree WHERE :structure = :entity_id; 

wiem, że to nie jest trudne, aby dowiedzieć się poziom struktura pojedynczego podmiotu, ale zakładamy, mam zapętlenie poprzez zbiór jednostek, które nie wszyscy mogą być na tym samym poziomie . Jak to jest teraz muszę budować oddzielne kwerendy dla każdego poziomu hierarchii, ale czy mogę parametryzacji pól mogłem wykonać następujące czynności:

$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); 
} 

powodując czystszego kodu i tylko jeden przygotowane oświadczenie.

Cały przykład nie wykorzystuje danych wprowadzonych przez użytkownika.

Po prostu coś do rozważenia.

+0

Jaki jest sens? Równie łatwo można użyć zmiennych regularnych w tym przypadku, ponieważ nie ma danych wprowadzanych przez użytkownika. Nie ma tu możliwości wstrzyknięcia. Powinienem to również opublikować jako komentarz do mojej odpowiedzi, ponieważ nie jest to odpowiedź na pytanie PO. (Rozumiem, że nie byłbyś w stanie to dopasować, po prostu zauważając to.) –

1

Nie można sparametryzować niczego w ramach klauzuli IN.

+0

Dzięki, zapomniałem o tym. Dodam to do mojej odpowiedzi. –

Powiązane problemy