Python MysqlDB с использованием cursor.rowcount с SSDictCursor возвращает неправильный счет - PullRequest
7 голосов
/ 01 февраля 2012

У меня есть следующий код

cur = db.cursor(cursors.SSDictCursor)
cur.execute("SELECT * FROM large_table")
result_count = cur.rowcount
print result_count

Это печатает число 18446744073709551615, что, очевидно, неправильно.Если я удаляю cursors.SSDictCursor, отображается правильный номер.Может кто-нибудь сказать мне, как я могу получить количество записей, возвращенных при сохранении SSDictCursor?

Ответы [ 2 ]

5 голосов
/ 22 марта 2014

Чтобы получить количество записей, возвращаемых SSDictCursor или SSCursor, у вас есть только следующие варианты:

  1. Получить весь результат и сосчитать его, используя len(), что побеждаетцель использования SSDictCursor или SSCursor в первую очередь;

  2. Подсчитывать строки самостоятельно при их итерации по ним, что означает, что вы не будете знать счет до тех пор, пока не нажметеконец (вряд ли будет практичным);или

  3. Запустите дополнительный отдельный запрос COUNT(*).

Я настоятельно рекомендую третий вариант.Это очень быстро, если все, что вы делаете, это SELECT COUNT(*) FROM table;.Это было бы медленнее для некоторых более сложных запросов, но при правильном индексировании оно все равно должно быть достаточно быстрым для большинства целей.


Кроме того, возвращаемое значение, которое вы видите, равно правильно;по крайней мере, что касается API MySQL C.

В соответствии с API-интерфейсом DB Python, определенным в PEP 249, атрибут rowcount равен -1, если количество строк последней операции не может быть определеноинтерфейс .@glglgl объяснил, почему количество строк не может быть определено в их ответе:

Внутренне, SSDictCursor использует mysql_use_result(), что позволяет серверу начать передачу данных до завершения сбора.

Другими словами, сервер не знает, сколько строк он в конечном итоге собирается извлечь.При выполнении запроса MySQLdb сохраняет возвращаемое значение mysql_affected_rows() в атрибуте курсора rowcount.Поскольку счетчик не определен, эта функция возвращает -1 как длинное целое число без знака (my_ulonglong), числовой тип, который доступен в модуле ctypes стандартной библиотеки:

>>> from ctypes import c_ulonglong
>>> n = c_ulonglong(-1)
>>> n.value
18446744073709551615L

Быстрая и грязная альтернатива ctypes, когда вы знаете, что всегда будете иметь дело с 64-разрядным целым числом без знака, это:

>>> -1 & 0xFFFFFFFFFFFFFFFF
18446744073709551615L

Было бы здорово, если быMySQLdb проверил это возвращаемое значение и дал целое число со знаком, которое вы ожидаете увидеть, но, к сожалению, это не так.

3 голосов
/ 01 февраля 2012

С SSDictCursor это значение может быть прочитано только соотв. определяется при использовании курсора.

Внутренне SSDictCursor использует mysql_use_result(), что позволяет серверу начать передачу данных до завершения сбора.

...