| |
MySQLdb представляет собой поточно-совместимый интерфейс с популярной СУБД MySQL, который обеспечивает Python API для баз данных. Здесь рассматривается его версия 0.9.1 (автор Andy Dustman, andy@dustman.net). Пакет распространяется по лицензии GPL и доступен для закачки с http://sourceforge.net/projects/mysql-python. Цели проекта:
Требования:
Python 1.5.2 или выше:
Distutils 1.0.2 или выше:
MySQL 3.22.19 или выше.
Первое, что Вы будете делать, редактирование скрипта setup.py. Имеются некоторые переменные, которые сообщают где искать MySQL include-файлы и библиотеки. Значения корректны для стандартной установки MySQL в Red Hat Linux (6.2) RPM. Если Вы имеете другую платформу, Вы должны будете вычислить нужные значения самостоятельно. Вам почти никогда не придется изменять это. Если Вы имеете старую версию distutils (до 1.0.2), обновитесь или удалите параметры, относительно которых система возражает.
Обратите внимание, что недавние двоичные дистрибутивы с www.mysql.com включают два набора библиотек пользователей: mysqlclient и mysqlclient_r. Последний хранит поточно-безопасные библиотеки, так что используйте именно его, если потоки Вам нужны.
Если Вы имеете динамические библиотеки пользователей (в Linux .so-файлы), они будут использоваться по умолчанию. Если они не в Вашем стандартном пути загрузчика, Вы должны будете установить или откорректировать системную переменную LD_LIBRARY_PATH (в Linux) или ту, которую Ваша платформа требует. Иначе Вы можете скорректировать setup.py, чтобы компоновать со статической библиотекой. Если Вы используете стандартный пакет RPM, с этим не должно быть особых проблем.
ПРЕДУПРЕЖДЕНИЕ: Если Вы используете двоичный пакет Zope, Вы нуждаетесь в выполнении скрипта setup.py программой python из Zope. Иначе Zope (ZMySQLDA) не может найти _mysql.
Если Вы предпочитаете RPM, Вы можете использовать команду bdist_rpm с setup.py. Это только формирует RPM, но не устанавливает его.
Этот модуль должен быть совместим с более старым интерфейсом, написанным Joe Skinner. Однако, старая версия:
MySQLdb полностью новый модуль, распространяемый бесплатно согласно GNU Public License. Никакой код из той версии не используется в MySQLdb.
Этот модуль разработан на RedHat Linux (в настоящее время 7.1) для Intel.
Это должно формироваться без больших трудностей на большинстве платформ,
используя скрипт setup.py
. Возможно этот модуль работает и под
MacOS X. Вы нуждаетесь в пакете Distutils, который поставляется с Python 2.0.
Если Вы не имеете его (то есть Вы имеете Python 1.5.2), Вы можете скачать
пакет с сайта www.python.org.
Windows не поддерживаемая платформа. Однако, скрипт
setup.py
по сообщениям работает нормально.
MySQLdb требует Python 1.5.2 или новее. Более ранние версии не будут
работать потому, что MySQL нужна поддержка для C long long
. Если
Вы имеете более раннюю версию Python, обновитесь хотя бы до 1.5.2. Текущая
разработка выполнена в Python 2.1, но старый Python 1.5.2 все еще будет
поддержан в обозримом будущем.
Гарантируется работа версии 3.22.32 и выше. Некоторые старые версии могут работать, если Вы имеете старшую версию, Вы должны серьезно подумать об апгрейде в целях исправления ошибок и дыр в защите.
MySQL-3.22 имеет проблему при попытке вставить значения TIME
с дробными секундами. Значения, подобные 12:56:13.00, возвращены как
344:13:00, очевидно интерпретируя первоначальный ввод как 12 дней, 56 часов,
13 минут и 0 секунд (12 дней и 56 часов=344 часа). Чтобы избежать этой
проблемы, используйте тип DateTimeDelta
.
MySQLdb поддерживает транзакции, если их поддерживает сервер. Но
не гарантирует, что транзакции будут работать. Для этого Вы должны
использовать транзакционно-безопасную таблицу (TST). Текущие TST: BDB и
InnoDB. Таблицы GEMINI намечены для MySQL-4.0. Обратите внимание, что MySQL
функционирует в режиме AUTOCOMMIT
по умолчанию, и MySQLdb
считает, что AUTOCOMMIT
включен. Чтобы изменить это, используйте
инструкции SQL SET AUTOCOMMIT=0
.
Если Вы имеете установленный пакет mx.DateTime , MySQLdb использует его для связанных с датой объектов. Иначе они будут возвращены как строки. Вы можете также изменять словарь преобразования типов, чтобы возвратить их как другие объектные классы.
MySQLmodule, старый интерфейс MySQL, разработанный Joe Skinner, является
также интерфейсом C/Python. MySQL
, C-часть, имеет интерфейс,
подобный perl DBI. Кроме того, имеется часть Python, Mysqldb
,
которая обеспечивает интерфейс DB API v1.0, написанный James Henstridge.
MySQLdb-0.2.2 и выше включает CompatMysqldb
, который является
адаптацией Mysqldb
к _mysql
. Это должно
рассмотреться экспериментальным решением.
Напротив, C-часть MySQLdb, _mysql
, разработана в соответствии
с MySQL C API объектно-ориентированным способом. MySQLdb
обеспечивает интерфейс DB API v2.0, который имеет некоторые отличия от
v1.0, в частности такие изменения:
Действие | Mysqldb | MySQLdb |
Соединение | db=Mysqldb.Mysqldb("db@host user pass")
|
db=MySQLdb.connect(db='db', host='host', user='user',
passwd='pass') |
Неявный курсор | db.execute(SQL) |
Неявные курсоры удалены из DB API v2.0. Всегда используйте
c=db.cursor() |
Строка выборок как словарь | c.fetchDict() ,
ключи: "table.column" |
Не стандарт: альтернативный класс DictCursor предоставляет
интерфейс словаря, ключи являются "column" или "table.column
, если имеются два столбца с одним именем. Используйте SQL-оператор
AS для переименования полей. |
Транзакции | db.commit() и
db.rollback() мирно сосуществуют вместе и тихо не делают ничего
(опасно!) |
db.commit() и db.rollback() работают, если
сервер MySQL может выполнять транзакции, иначе db.rollback()
всегда терпит неудачу. |
Был написан пакет ZMySQLDA для использования с MySQLdb. Это адаптируется из ZOracleDA Digital Creations разработчиков системы Zope.
FAQ доступны на http://dustman.net/andy/python/MySQLdb/faq/MySQLdb-FAQ.html.
Если Вы хотите писать прикладные программы, которые переносимы между
базами данных, избегайте использовать этот модуль непосредственно. Модуль
_mysql
обеспечивает интерфейс, который обычно осуществляет MySQL
C API. Для получения большего количества информации обратитесь к документации
на пакет MySQL. Документация для этого модуля преднамеренно слаба потому, что
Вы, вероятно, должны использовать более высокий уровень (модуль MySQLdb).
MySQL C API был обернут объектно-ориентированным способом. Единственные
MySQL структуры данных, которые выполнены в данном интерфейсе, это
MYSQL
(дескриптор подключения базы данных) и
MYSQL_RES
(дескриптор результата). Вообще, любая функция,
которая берет как параметр MYSQL *mysql
, теперь представляет
собой метод объекта подключения, и любая функция, которая берет
MYSQL_RES *result
, теперь метод объекта результата. Функции, не
требующие ни одной структуры MySQL, выполнены как функции в модуле. Функции,
требующие какую-то из других структур данных MySQL, вообще не выполнены. Во
всех случаях префикс mysql_
удален из имени. Большинство
перечисленных методов conn
также доступно как методы объекта
MySQLdb Connection. Их использование не переносимо между базами данных.
C API | _mysql |
mysql_affected_rows() |
conn.affected_rows() |
mysql_close() | conn.close() |
mysql_connect() | _mysql.connect()
|
mysql_data_seek() | result.data_seek()
|
mysql_debug() | _mysql.debug() |
mysql_dump_debug_info |
conn.dump_debug_info() |
mysql_escape_string() |
_mysql.escape_string() |
mysql_fetch_row() | result.fetch_row()
|
mysql_get_client_info() |
_mysql.get_client_info() |
mysql_get_host_info() |
conn.get_host_info() |
mysql_get_proto_info() |
conn.get_proto_info() |
mysql_get_server_info() |
conn.get_server_info() |
mysql_info() | conn.info() |
mysql_insert_id() | conn.insert_id()
|
mysql_list_dbs() | conn.list_dbs()
|
mysql_list_fields() | conn.list_fields()
|
mysql_list_processes() |
conn.list_processes() |
mysql_list_tables() | conn.list_tables()
|
mysql_num_fields() | result.num_fields()
|
mysql_num_rows() | result.num_rows()
|
mysql_options() | _mysql.connect()
|
mysql_ping() | conn.ping() |
mysql_query() | conn.query() |
mysql_real_connect() | _mysql.connect()
|
mysql_real_query() | conn.query()
|
mysql_real_escape_string() |
conn.escape_string() |
mysql_row_seek() | result.row_seek()
|
mysql_row_tell() | result.row_tell()
|
mysql_select_db() | conn.select_db()
|
mysql_stat() | conn.stat() |
mysql_store_result() | conn.store_result()
|
mysql_thread_id() | conn.thread_id()
|
mysql_use_result() | conn.use_result()
|
CLIENT_* | MySQLdb.constants.CLIENT.*
|
CR_* | MySQLdb.constants.CR.* |
ER_* | MySQLdb.constants.ER.* |
FIELD_TYPE_* |
MySQLdb.constants.FIELD_TYPE.* |
FLAG_* | MySQLdb.constants.FLAG.*
|
Допустим, что Вы хотите использовать _mysql
.
Имеются некоторые примеры.
Самое простое подключение к базе данных:
import _mysql db=_mysql.connect()
Это создает подключение к серверу MySQL на локальной машине, используя
стандартый сокет UNIX, Ваше имя входа в систему (из системной переменной
USER), пустой пароль и не применяет команду USE
. Возможно, это
будет работать у Вас, если Вы установили файл конфигурации (~/.my.cnf
). Но скорее всего Вы должны обеспечить большее количество информации:
db=_mysql.connect("localhost","joebob","moonpie","thangs")
Это создает подключение к серверу MySQL на локальной машине, используя TCP на стандартном порте (3306), имя пользовател joebob, пароль moonpie и выбирает начальную базу данных thangs.
Конечно, Вы должны использовать TCP, если работаете с удаленной системой.
Здесь я не рассмотрел часть параметров connect()
, и Вы обратите
внимание, что, если Вы используете позиционные параметры, настроить связь по
TCP не так-то просто. Кроме того, сокеты UNIX быстрее. Я предпочитаю
использовать параметры ключевого слова:
db=_mysql.connect(host="localhost",user="joebob", passwd="moonpie",db="thangs")Это делает точно то же, что делал последний пример, но проще для чтения. Теперь, если Вы действительно хотели использовать сокет UNIX, и Ваше имя входа в систему joebob, Вы могли бы сократить этот пример до:
db=_mysql.connect(passwd="moonpie",db="thangs")Имеются некоторые другие параметры, которые Вы можете использовать, и большинство их не так уж и необходимо, кроме одного, о котором чуть ниже. Во всем остальном обратитесь к встроенной документации. Модуль Python 2.1
pydoc
представляет собой хороший справочник.
Теперь Вы имеете открытое подключение db
и хотите сделать
запрос. Не имеется никаких курсоров в MySQL и никакой подстановки параметров,
так что Вы должны передать полную строку запроса db.query()
:
db.query("""SELECT spam, eggs, sausage FROM breakfast WHERE price < 5""")Не имеется никакого значения возврата, но исключительные ситуации могут быть вызваны. Исключительные ситуации определены в отдельном модуле,
_mysql_exceptions
, но _mysql
экспортирует их.
Читайте спецификацию DB API
(http://www.python.org/topics/database/DatabaseAPI-2.0.html), чтобы выяснить
то, чем они являются, или Вы можете использовать MySQLError
.
В этой точке Ваш запрос был выполнен, и Вы должны получить результаты. Вы имеете два параметра:
r=db.store_result() # ...или... r=db.use_result()Оба метода возвращают объект результата. В чем же разница? А в том, что
store_result()
возвращает весь набор результатов пользователю
немедленно. Если Ваш набор результатов действительно большой, это станет
проблемой. Один путь обхода этого состоит в том, чтобы добавить предложение
LIMIT
к Вашему запросу, чтобы ограничить число возвращенных
строк. Но можно использовать use_result()
, который хранит набор
результатов на сервере и посылает его построчно, когда Вы выбираете. Это
связывает ресурсы сервера и подключение: Вы не можете делать больше запросов,
пока Вы не выбрали все строки. Вообще я рекомендую использовать
store_result()
, если Ваш набор результатов не огромен, и Вы не
можете использовать LIMIT
.
Теперь для фактического получения реальных результатов надо:
>>> r.fetch_row() (('3','2','0'),)Первая вещь, которую Вы должны знать:
fetch_row()
берет
некоторые дополнительные параметры. Первый задает, сколько строк
(maxrows
) должны быть возвращены. По умолчанию, это возвращает
одну строку. Это может возвращать меньшее количество строк, чем Вы просите,
но никогда не больше. Если Вы устанавливаете maxrows=0
, это
возвращает все строки набора результатов. Если Вы когда-либо получаете пустой
набор, значит Вы исчерпали строки.
Второй параметр (how
) сообщает как строка должна
представиться. По умолчанию, это ноль, что означает вернуть как набор.
how=1
значит вернуть данные как словарь, где ключи представляют
собой имена столбца или table.column
, если имеются два столбца с
тем же самым именем. how=2
аналогично how=1
, кроме
того, что ключи всегда table.column
, это для
совместимости со старым модулем Mysqldb
.
Другая причуда: известно, что обрабатываются числовые столбцы, почему они
возвращены как строки? Потому, что MySQL возвращает все данные как строки
просто по определению и ожидает, что Вы преобразуете их непосредственно. Как
я понимаю, все данные в базе хранятся именно как строки, как бы они не
выглядели снаружи. Это было бы реальной проблемой, но фактически
_mysql
может делать это для Вас. MySQLdb
делает это
для Вас сам. Чтобы иметь автоматическое выполненное преобразование типов, Вы
должны создать словарь конвертера типов и передать его в
connect()
как параметр ключевого слова conv
.
Ключи в conv
должны быть типами столбцов MySQL, которые в C
API являются FIELD_TYPE_*
. Вы можете получать эти значения так:
from MySQLdb.constants import FIELD_TYPE
По умолчанию любой тип столбца, который не может быть найден в
conv
, возвращен как строка, которая пригодна для самых разных
применений. Для наших целей нужно:
my_conv = {FIELD_TYPE.LONG: int}Это означает, если это
FIELD_TYPE_LONG
, обработать это
встроенной int()
. Обратите внимание, что
FIELD_TYPE_LONG
представляет собой столбец INTEGER
,
который соответствует C long
, который является также типом,
используемым для нормального целого числа в Python. Но остерегайтесь: если
это столбец UNSIGNED INTEGER
, это может вызвать переполнение. По
этой причине MySQLdb
фактически использует long()
,
чтобы сделать преобразование.
Затем, если Вы используете
db=_mysql.connect(conv=my_conv...)
, результаты возвратятся в
виде ((3, 2, 0),)
, который является тем, что и ожидается.
MySQLdb представляет собой тонкую обертку на Python вокруг
_mysql
. MySQLdb делает его
совместимым с интерфейсом Python DB API (version 2). В действительности код,
который осуществляет API, находится в _mysql
ради эффективности.
Только несколько высокопоставленных функций и атрибутов определены внутри MySQLdb.
mysql_options()
перед соединением.
Обратите внимание, что некоторые параметры должны быть определены как
параметры ключевого слова! Значение по умолчанию для каждого параметра: NULL
или 0, зависит от типа. Важные параметры:
MySQLdb.converters.conversions
.
mysql_options()
.
mysql_options()
.
cursor()
, если не
перекрыт. Значение по умолчанию: MySQLdb.cursors.Cursor
. Это
должно быть параметром ключевого слова.Протокол MySQL не может обрабатывать много потоков, использующих то же
самое подключение, сразу. Более ранние версии MySQLdb использовали
блокировку, чтобы достигнуть threadsafety=2. Несмотря на то, что это не
должно активно использовать стандартный класс Cursor (который используется в
mysql_store_result()
), это усложнено SSCursor (который
используется в mysql_use_result()
. Здесь Вы должны
гарантировать, что все строки прочитались прежде, чем другой запрос сможет
быть выполнен. Это далее усложнено добавлением транзакций, начинающихся
когда курсор выполняет запрос, и завершающихся выполнением
COMMIT
или ROLLBACK
объектом Connection. Два потока
не могут совместно использовать подключение, в то время как транзакция
происходит, в дополнение к неспособности совместно использовать его в течение
выполнения запроса. К сожалению, это чрезмерно усложнило код.
Общий результат этого: совместно не используйте подключения разными потоками. Это не стоит прилагаемых усилий и в результате, вероятно, причинит вред эффективности, так как сервер MySQL выполняет отдельный поток для каждого подключения. Вы можете, конечно, делать кэширование подключений через специальный пул, и давать подключения с одним потоком одновременно. Если Вы позволяете двум потокам использовать подключение одновременно, библиотека пользователей MySQL, вероятно, будет сваливаться.
Примечание о совместимости: старые версии MySQLmodule используют подобную схему задания параметра, но требуют, чтобы кавычки были помещены вокруг строк формата, которые будут содержать строки, даты и подобные символьные данные. Это не требуется для MySQLdb. Рекомендуется, чтобы %s (но не '%s') использовался для всех параметров, независимо от типа. Интерфейс выполняет все необходимое цитирование сам.
FIELD_TYPE.*
) к
вызываемым объектам Python (обычно функциям), которые преобразовываются из
строк в нужные типы. Это инициализировано с приемлемыми значениями по
умолчанию для большинства типов. При создании объекта Connection Вы можете
передать Ваш собственный словарь конвертера типа как параметр ключевого
слова. Иначе это использует копию MySQLdb.converters.conversions
.
Словарь включает некоторые из функций модуля DateTime
, если это
доступно. Несколько ненормативных типов возвращены как строки,
Начиная с MySQL-3.23, MySQL поддерживает различные наборы символов на
клиенте и сервере, а также новую функцию цитирования
mysql_real_escape_string()
. Это требует, чтобы функция
цитирования строки была методом, связанным с объектом connection. MySQLdb
обрабатывает это для Вас автоматически. Однако, если Вы чувствуете
потребность сделать что-то особое со строками, Вы должны изменить словарь
после открытия подключения.
Объекты Connection возвращены функцией connect()
.
NotSupportedError
.
Примечание совместимости: старые версии MySQLmodule определяют этот метод, так что он не далет ничего. Это опасное поведение, поскольку успешная обратная перемотка указывает, что текущая транзакция отменена.
Cursor
.
begin()
для его
временного отключения. AUTOCOMMIT продолжит работу после следующего вызова
commit()
или rollback
.ProgrammingError
. Если Вы используете
курсоры стороны сервера, очень важно
закрыть курсор, когда Вы с ним закончили, но перед созданием нового курсора.
AUTO_INCREMENT
,
вставленное в базу данных.
Warning
. Если Вы
используете класс курсора без предупреждений, рекомендую проверять
info(). Подробности в документации MySQL на mysql_info()
.
Метод connect()
работает почти также, как и с
_mysql
:
import MySQLdb db=MySQLdb.connect(passwd="moonpie",db="thangs")Чтобы выполнить запрос, Вы сначала нуждаетесь в курсоре, а затем Вы можете выполнять запросы на нем.
c=db.cursor() max_price=5 c.execute("""SELECT spam, eggs, sausage FROM breakfast WHERE price < %s""", (max_price,))
В этом примере max_price=5
. Почему затем в строке
использована опция %s
? Потому, что MySQLdb преобразует это в
литеральное значение SQL, которое является строкой '5'. Когда это закончено,
запрос будет фактически таким: "...WHERE price < 5".
Так, а теперь результаты:
>>> c.fetchone() (3L, 2L, 0L)В отличие от примера с
_mysql
, это возвращает одиночный блок
результатов, который является строкой, и значения правильно преобразованы.
Как упомянуто ранее, в то время как столбец MySQL INTEGER транслируется в
Python integer, UNSIGNED INTEGER может вызвать переполнение, так что эти
значения преобразованы в Python long integer. До Python 1.6 long integer
сохраняли L, когда были преобразованы в строки с помощью
str()
. В 1.6 и позже str()
не включает L. Конечно,
L всегда выводится при использовании repr()
.
Когда Вы закончили работу с транзакцией, Вы должны выполнить
db.commit()
или db.rollback()
. Если сервер и
таблицы не поддерживает транзакции, commit()
будет работать, но
rollback()
вызовет исключительную ситуацию. Обратите внимание,
что это методы connection, а не cursor, даже при том, что
транзакция запускается через c.execute(...)
.
Если Вы хотели получить большее количество строк, Вы могли бы использовать
c.fetchmany(n)
или c.fetchall()
. На
c.fetchmany(n)
параметр n
факультативный и имеет
значение по умолчанию c.arraysize
(обычно 100). Оба этих метода
возвращают последовательность строк, или пустую последовательность, если
строки уже кончились.
Обратите внимание, что в отличие от вышеупомянутого,
c.fetchone()
вернет None
, когда не имеется больше
строк для выборки.
Единственный другой метод, который Вы, очень вероятно, используете, это многострочная вставка:
c.execute("""INSERT INTO breakfast (name, spam, eggs, sausage, price) VALUES (%s, %s, %s, %s, %s)""", [ ("Spam and Sausage Lover's Plate", 5, 1, 8, 7.95 ), ("Not So Much Spam Plate", 3, 2, 0, 3.95 ), ("Don't Wany ANY SPAM! Plate", 0, 4, 3, 5.95 )])
Здесь мы вставляем три строки по пять значений в каждой. Обратите
внимание, что имеется смесь типов (строки, int, float), хотя все еще
используется только %s
. А также обратите внимание, что включили
только строки формата для одной строки. MySQLdb выбирает и дублирует их
для каждой строки.
Базы данных, даже SQL-базы данных, изменяются по возможностям очень сильно
и могут иметь ненормативные свойства. DB API делает хорошую работу по
обеспечению приемлемо переносимого интерфейса, но некоторых методов там нет.
Специфические параметры для connect()
полностью зависимы от реализации.
Если Вы полагаете, что Ваша прикладная программа должна выполниться на нескольких различных базах данных, автор рекомендует следующий подход, основанный на персональном опыте: пишите упрощенный API для Вашей прикладной программы, который осуществляет специфические запросы и операции, которые Ваша прикладная программа должна выполнить. Выполните этот API как основной класс, который должен иметь немного зависимостей от базы данных, а затем получите подкласс, который осуществляет необходимые зависимости. Таким образом, перенос Вашей прикладной программы к новой базе данных должен быть относительно простым вопросом создания нового подкласса для базы данных.
В качестве примера рекомендую изучить модуль SQLDict (http://dustman.net/andy/python), который позволяет стандартным запросам работать, используя объект, который напоминает словарь, а также читать и писать определяемые пользователем дополнительные объекты.
Поскольку объекты MySQLdb Connection и Cursor написаны на Python, Вы можете легко получать Ваши собственные подклассы. Имеются несколько классов Cursor в MySQLdb.cursors:
mysql_store_result()
,
чтобы получить результат запроса. Весь набор результатов сохранен
на стороне пользователя.
mysql_use_result()
,
чтобы получить результат запроса. Набор результатов сохранен на стороне
сервера и передается построчно.
AS
CursorWarningMixIn, CursorStoreResultMixIn,
CursorTupleRowsMixIn
и BaseCursor
, то есть он создает
исключительную ситуацию Warning
, использует
mysql_store_result()
и возвращает строки как блоки.
Cursor
за исключением того, что возвращает
строки как словари.
Cursor
, но использует
CursorUseResultMixIn
. Используйте только, если Вы имеете дело с
потенциально большими наборами результатов.
SSCursor
за исключением того, что возвращает
строки как словари.
_mysql.so
Имеются некоторые общие ошибки, которые случаются в ходе построения
пакета. Этот раздел покрывает только проблемы UNIX/Linux, поскольку я не
делаю пакетов под Windows. Файлы типа .so
представляют собой
динамические библиотеки в Linux и большинстве других вариантов UNIX. Windows
использует расширение .dll
.
Вы имеете динамические библиотеки MySQL, и по умолчанию Ваш компилятор
линкует _mysql.so
с ними, но они не в пути загрузчика, когда Вы
запускаете Python. Вы имеете два базисных параметра:
/etc/ld.so.conf
или Вы можете добавить каталог к системной переменной
LD_LIBRARY_PATH
перед запуском Python.
LD_LIBRARY_PATH=/path/to/mysql/libs python ... # Bourne-ish shell
PyLong_FromUnsignedLongLong()
сначала появляется в
Python 1.5.2, так что Вы компонуете с более старой версией. Вы можете также
иметь больше, чем одну установленную версию. Получите Python 1.5.2 (а лучше
посвежее) с python.org.
Библиотеки пользователей MySQL-3.23 требуют libz для сжатия gzip. Скрипт setup.py должен бы добавить это автоматически.
Путь для include-файлов (-I) к Вашим MySQL include-файлам ошибочен.
Поправьте скрипт setup.py. Другой вариант: Вы не имеете набора разработчика
для MySQL. Если Вы используете Red Hat RPM, Вы нуждаетесь в RPM-пакете
MySQL-devel
, чтобы откомпилировать _mysql.so
.
Однако, если Вы компонуетесь со статическими библиотеками MySQL, Вы можете
устанавливать _mysql.so
на системе, которая не имеет библиотек
пользователей MySQL (libmysqlclient
).
А я не использую Windows. Скрипт setup.py, как предполагается, работает. Может также быть связь с каким-либо сторонним пакетом.
Вероятно, Вы установили двоичную версию Zope, которая приходит со своим собственным интерпретатором Python. Вы должны компилировать MySQLdb с той специфической установкой Python. Выясните, где находятся двоичные модули python и используйте это, чтобы выполнить setup.py.
Вообще-то они должны быть преобразованы в длинные целых числа, чтобы
избежать переполнения на столбцах UNSIGNED INT. Решения: используйте атрибут
fmt=%d
на элементах dtml-var
или поставьте
Zope 2.4, который приходит с Python 2.1, который не добавляет L.
Z метода SQL имеют параметр max_rows
. Если это установлено к
значению, отличному от нуля, ZMySQLDA автоматически добавляет предложение
LIMIT к инструкции SELECT. Это сильно повышает эффективность, особенно, если
набор результатов мог бы быть большим. Если это сталкивается с чем-то,
установите max_rows
в ноль, и это не будет добавлять предложение
LIMIT. В частности, Вы, вероятно, должны будете сделать это при вставке строк
со столбцами AUTO_INCREMENT, поскольку обычно Вы используете
SELECT, чтобы получить LAST_INSERT_ID(), а LIMIT может блокировать это.
MySQLdb представляет собой модуль, соответствующий спецификации Python Database API 2.0 (http://www.python.org/topics/database/DatabaseAPI-2.0.html), так что Вы должны быть знакомы с этой спецификацией. Здесь указаны отличия: http://dustman.net/andy/python/MySQLdb/doc/MySQLdb.html.
MySQLdb теперь поддерживает транзакции, если сервер поддерживает транзакционно-безопасные таблицы (TST), и Вы используете их. Если Ваш сервер не поддерживает их, rollback всегда будет терпеть неудачу потому, что система не в состоянии выполнить Ваши инструкции. Даже если Ваш сервер поддерживает транзакционно-безопасные таблицы, rollback будет терпеть неудачу, если Вы изменили любую не-TST таблицу.
cursor.commit()
, который пытается завершить транзакцию
всегда работает нормально потому, что MySQL по существу всегда в
режиме auto-commit mode (если Вы не его не выключили).
С одной стороны, никак. Не делайте этого, если Вы можете избежать этого. Ваша программа не будет переносима к другим базам данных.
Но если Вас эта переносимость не интересует, то почти все специальные обращения API выполнены в объекте _mysql, и объект связи в MySQLdb может также вызывать их.
Хорошо, это может быть необходимо в каком-то случае. ZMySQLDA делает это потому, что Zope-модуль ZRDB сам по себе API, а слишком много уровней API имеют тенденцию к разброду и шатанию. С этим поделать что-либо трудно. Кроме того, было фактически довольно просто сделать это именно таким способом, да и эффективность малость повысилась.
Закладки на сайте Проследить за страницей |
Created 1996-2024 by Maxim Chirkov Добавить, Поддержать, Вебмастеру |