2010-03-30 11 views
26

Sto riscontrando problemi nell'utilizzo di parametri nella sezione ORDER BY del mio SQL. Non emette alcun avviso, ma non stampa nulla.Come si impostano i parametri ORDER BY utilizzando l'istruzione PDO preparata?

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

I :my_param opere, ma non :order o :direction. Non viene evaso internamente correttamente? Sono bloccato inserendolo direttamente in SQL? In questo modo:

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

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

C'è una costante PDO::PARAM_COLUMN_NAME o qualche equivalente?

Grazie!

+0

Vedere anche [Le istruzioni PDO PHP possono accettare il nome tabella come parametro?] (Http://stackoverflow.com/q/182287/157957) – IMSoP

risposta

12

Io non credo che si può:

  • utilizzare segnaposto in una clausola order by
  • nomi delle colonne
  • Bind: è possibile associare solo i valori - o variabili, e hanno il loro valore iniettato nella dichiarazione preparata .
+3

Per essere onesti - è ** È ** possibile associare * valori * (non identificatori) in una clausola 'ORDER BY' – zerkms

+1

Questo è parzialmente a destra. È possibile utilizzare solo segnaposti obbligatori per fornire ** valori **. Non è * mai * possibile utilizzare segnaposti bind per fornire ** identificatori ** (come nomi di tabelle, nomi di colonne), parole chiave SQL ** ** o qualsiasi altra parte della sintassi SQL diversa da un ** valore **. (In sostanza, un segnaposto di bind può prendere il posto di letterale stringa, un letterale di data o un periodo letterale numerico, ma come sottolinea lo zerkms, poiché è possibile utilizzare letterali come parti di un'espressione in una clausola 'ORDER BY', ** è ** infatti possibile utilizzare segnaposti bind come parte delle espressioni in una clausola 'ORDER BY'. – spencer7593

38

Qui viene la domanda mostra che ampiamente amava le istruzioni preparate non è la pallottola d'argento, hehe :)

Sì, sei bloccato inserendolo direttamente nella SQL Con alcune precauzioni, naturalmente. Ogni operatore/identificatore deve essere codificato nello script, in questo modo:

$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"; 

Lo stesso vale per la direzione.

Si noti che bindParam non esegue l'escape, poiché non è necessario eseguire alcuna operazione di escape. è vincolante.

+0

Se si dispone di una matrice di stringhe valide e si digita nuovamente ciò che si ha come' $ input = (stringa) $ input; 'to **' (string) '** puoi quindi semplicemente controllare' if (in_array ($ input, $ valid_orderbys_array)) 'dovrebbe fondamentalmente fare lo stesso. –

-1

Se non sbaglio completamente, Pascal ha ragione.
L'unico legame possibile in PDO è il binding dei valori, come hai fatto con il parametro ': my_param'.
Tuttavia, non c'è niente di male in:

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

L'unica cosa da prendere atto sarebbe il corretto fuga di $order e $direction, ma dal momento che li impostare manualmente e non li impostato tramite l'input dell'utente, Penso che tu sia tutto pronto.

+0

Se non avesse intenzione di cambiare la colonna orderby e direzione, quindi mi aspetto che non ci sarebbe alcun punto nel farli essere variabili. – Kzqai

4

Non penso che tu possa ottenere ASC/DESC come parte dell'istruzione preparata, ma la colonna è possibile.

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

Dal ASC/DESC è solo due valori, si può facilmente convalidare e scegliere tra loro come valori hardcoded.

È anche possibile utilizzare le funzioni ELT (FIELD (,,,,,,,,,,,) per questo, ma l'ordine verrà sempre eseguito come stringa, anche se si tratta di una colonna numerica.

0

Sfortunatamente, suppongo che non sia possibile farlo con dichiarazioni preparate. Non può essere memorizzato nella cache poiché le diverse colonne possono avere valori che possono essere ordinati con speciali strategie di ordinamento.

Creare query utilizzando escape standard ed eseguirlo direttamente.

-1

Creare una condizione if-else.
Se (ascCondion) quindi associare i valori ma il codice ORDINE duramente dalla columnName ASC
Else
Bind i valori ma il codice ORDINE duramente dalla nomecolonna DECR

7

E 'possibile uso istruzioni preparate in ORDER BY clausola, purtroppo è necessario passare l'ordine di colonna insted del nome ed è necessario impostare PDO_PARAM_INT con tipo.

In MySQL è possibile ottenere l'ordine delle colonne con questa query: Codice

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

E 'possibile . È possibile utilizzare il numero anziché il nome del campo nella clausola 'ordinare per'. Questo è un numero che inizia da 1 e si trova nell'ordine dei nomi dei campi nella query. E puoi concatenare una stringa in per ASC o DESC. Ad esempio "Seleziona col1, col2, col3 da tab1 ordina per?" + StrDesc + "limite 10,5". strDesc = "ASC"/"DESC".

Problemi correlati