2011-01-10 4 views
6

Почему доктрина (1.2) использует WHERE IN вместо LIMIT?Почему доктрина использует WHERE IN вместо LIMIT?

Этот код:

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

Возвращает что-то вроде этого:

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

Вместо этого:

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

Это behaivor же для любого LIMIT значения. Это генерирует очень длинные запросы для высоких значений LIMIT.

Бонусный вопрос: Как знает Доктрина, какие идентификаторы использовать? (Отправляя другой запрос в БД ??)

+0

Какую базу данных вы используете? –

+0

@Matt Gibson: MySQL –

+0

Нечетный; Я только что сделал что-то подобное с Doctrine Symfony 1.4, которое я _think_ является версией 1.2.3, и он использует предложение LIMIT для MySQL, как и следовало ожидать. –

ответ

4

Это потому, что LIMIT работает с строками базы данных, а не с «объектами». Когда вы вводите $q->limit(10), вы хотите получить десять объектов, а не десять строк из базы данных.

Рассмотрим следующий запрос (продукты и категории имеют много-ко-многим):

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; 

Для извлечения 10 продуктов (объектов) Ваш запрос будет иметь для выборки по меньшей мере 20 строк. Вы не можете использовать причину LIMIT 10 (например, только 3 продукта будут возвращены). Вот почему вам нужно выяснить, какие продукты следует получать (ограничение распространяется на продукты), а затем извлекать фактические данные.

Это приведет к следующим запросам:

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

Второй запрос может возвращать 20, 423 или 31 строк. Как вы можете видеть, это не значение от limit().

PS. Doctrine2 намного яснее в этом случае, поскольку он использует метод setMaxResults() вместо limit(), который менее запутан.

+0

откуда вы получаете эту информацию? согласно ручному пределу() является частью DQL и используется до гидратации –

+0

Я знаю, что из моего собственного опыта и изучения источников. И да, вы правы - 'LIMIT' является частью DQL (' limit() 'метод поступает из' QueryBuilder'), и, как вы можете видеть, он используется до гидратации (второй запрос (тот, который фактически гидратирован) У меня даже есть предложение «LIMIT»)). – Crozin

+0

Это звучит странно для меня. Я (и мои коллеги) считал, что LIMIT применяется к числу строк, возвращаемых запросом (после процесса все соединения, подзапросы и т. Д.). –

0

Использование Учение 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; 

Я получаю результат:

SELECT t.id_table AS t__id_table FROM table t LIMIT 10 

Есть ли может быть что-то еще происходит в вашем коде?

+0

Мы только что узнали, что WHERE IN используется только при использовании JOIN. Извините за смущение. –

Смежные вопросы