2011-01-10 6 views
6

Perché doctrine (1.2) utilizza WHERE IN anziché LIMIT?Perché la dottrina usa WHERE IN invece di LIMIT?

Questo codice:

Doctrine_Query::create() 
    ->from('Table t') 
    ->limit(10) 
    ->getSqlQuery(); 

ritorni qualcosa di simile:

SELECT t.id_table AS t__id_table FROM table AS t WHERE t__id_table IN (1,2,3,4,10,12,18,20,21,25); 

Invece di questo:

SELECT t.id_table AS t__id_table FROM table AS t LIMIT 10; 

Questa behaivor è lo stesso per qualsiasi valore LIMIT. Ciò genera query molto lunghe per i valori alti LIMIT.

Domanda bonus: come sa Doctrine, quali ID usare? (Inviando un'altra query a DB ??)

+0

Quale database back-end stai utilizzando? –

+0

@Matt Gibson: MySQL –

+0

Dispari; Ho appena fatto qualcosa di simile con Doctrine di Symfony 1.4, che io _think_ è la versione 1.2.3, e usa la clausola LIMIT per MySQL, come ci si aspetterebbe. –

risposta

4

Questo perché LIMIT funziona su righe di database non su "oggetti". Quando si digita $q->limit(10) si desidera ottenere dieci oggetti, non dieci righe dal database.

Considerare seguente query (prodotti e categorie hanno molti-a-molti):

SELECT p.*, c.* FROM product p 
INNER JOIN product_category_ref pcr ON p.id = pcr.prodcut_id 
INNER JOIN category c ON c.id = pcr.category_id 
WHERE p.price < 123; 

per andare a prendere 10 prodotti (oggetti) la query dovrà prendere almeno 20 righe. Non è possibile utilizzare la causa LIMIT 10 (per esempio) solo 3 prodotti verrebbero restituiti. Ecco perché è necessario scoprire quali prodotti devono essere recuperati (il limite si applica ai prodotti) e successivamente recuperare i dati effettivi.

che si tradurrà in seguenti interrogazioni:

SELECT p.id FROM product p WHERE p.price < 123; 
SELECT ..... WHERE p.id IN (...); 

seconda query potrebbe restituire 20, 423 o 31 righe. Come puoi vedere, non è un valore da limit().

PS. Doctrine2 è molto più chiaro in quel caso poiché usa il metodo setMaxResults() invece di limit() che è meno confuso.

+0

da dove prendi queste informazioni? secondo manuale limit() è parte di DQL e viene utilizzato prima dell'idratazione –

+0

Lo so dalla mia stessa esperienza e studio delle fonti. E sì, hai ragione - 'LIMIT' è parte di DQL (il metodo 'lim()' proviene da 'QueryBuilder') e come puoi vedere è usato prima dell'idratazione (la seconda query (quella che è effettivamente idratata) non lo fa 'anche avere clausola 'LIMIT'))). – Crozin

+0

Mi sembra strano. Io (ei miei colleghi) pensavamo che il LIMIT fosse applicato al numero di righe che viene restituito dalla query (dopo il processo tutti i join, sottoquery ecc.). –

0

Utilizzando Dottrina 1.2.3:

<?php 

include(dirname(__FILE__).'/Doctrine.php'); 
spl_autoload_register(array('Doctrine', 'autoload')); 

$dbh = new PDO('mysql:dbname=testdb;host=127.0.0.1', 'testdb', 'testdb'); 
$conn = Doctrine_Manager::connection($dbh); 

class Table extends Doctrine_Record { 
    public function setTableDefinition() { 
    $this->hasColumn('id_table', integer, 10, array('primary' => true)); 
    } 
} 

$q = Doctrine_Query::create() 
    ->from('Table t') 
    ->limit(10) 
    ->getSqlQuery(); 

echo $q; 

ottengo il risultato:

SELECT t.id_table AS t__id_table FROM table t LIMIT 10 

C'è forse qualcos'altro succedendo nel vostro codice?

+0

Abbiamo appena saputo che WHERE IN viene utilizzato solo quando si utilizza JOIN. Ci scusiamo per la confusione. –