Skip to main content

MySQLdb用户指南

介绍

MySQLdb是提供Python数据库API的流行的MySQL数据库服务器的线程兼容接口。

安装

README 文件具有完整的安装说明。

_mysql

如果要编写跨数据库移植的应用程序,请使用 MySQLdb,并避免直接使用此模块。 _mysql 提供了一个主要实现MySQL C API的接口。有关更多信息,请参阅 MySQL documentation。这个模块的文档是故意弱,因为你可能应该使用更高级别的MySQLdb模块。如果真的需要它,请根据需要使用标准的MySQL文档和音译。

MySQL C API翻译

MySQL C API已经以面向对象的方式包装。唯一实现的MySQL数据结构是 MYSQL (数据库连接句柄)和 MYSQL_RES (结果句柄)类型。一般来说,以 MYSQL *mysql 作为参数的任何函数现在都是连接对象的方法,任何以 MYSQL_RES *result 为参数的函数都是结果对象的方法。不需要MySQL数据结构的函数作为模块中的函数实现。需要其他MySQL数据结构之一的函数通常不会实现。已弃用的函数未实现。在所有情况下,从名称中删除 mysql_ 前缀。列出的大多数 conn 方法也可用作MySQLdb连接对象方法。它们的使用是非便携式的。

MySQL C API函数映射

C API

_mysql

mysql_affected_rows()

conn.affected_rows()

mysql_autocommit()

conn.autocommit()

mysql_character_set_name()

conn.character_set_name()

mysql_close()

conn.close()

mysql_commit()

conn.commit()

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_character_set_info()

conn.get_character_set_info()

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_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_rollback()

conn.rollback()

mysql_row_seek()

result.row_seek()

mysql_row_tell()

result.row_tell()

mysql_select_db()

conn.select_db()

mysql_set_character_set()

conn.set_character_set()

mysql_ssl_set()

_mysql.connect()ssl 选项

mysql_stat()

conn.stat()

mysql_store_result()

conn.store_result()

mysql_thread_id()

conn.thread_id()

mysql_thread_safe_client()

conn.thread_safe_client()

mysql_use_result()

conn.use_result()

mysql_warning_count()

conn.warning_count()

CLIENT_*

MySQLdb.constants.CLIENT.*

CR_*

MySQLdb.constants.CR.*

ER_*

MySQLdb.constants.ER.*

FIELD_TYPE_*

MySQLdb.constants.FIELD_TYPE.*

FLAG_*

MySQLdb.constants.FLAG.*

一些_mysql示例

好吧,所以你想使用 _mysql 反正。这里有些例子。

最简单的可能的数据库连接是:

import _mysql
db=_mysql.connect()

这将使用标准UNIX套接字(或Windows上的命名管道),您的登录名(来自USER环境变量),无密码,并且不使用 USE 创建到本地计算机上运行的MySQL服务器的连接。您需要提供更多信息。:

db=_mysql.connect("localhost","joebob","moonpie","thangs")

这创建了通过UNIX套接字(或命名管道),用户名“joebob”,密码“moonpie”在本地机器上运行的MySQL服务器的连接,并选择初始数据库“thangs”。

我们甚至还没有开始接触 connect() 可以采取的所有参数。因此,我更喜欢使用关键字参数:

db=_mysql.connect(host="localhost",user="joebob",
                  passwd="moonpie",db="thangs")

这完全是最后一个例子做的,但是可以说更容易阅读。但由于默认主机是“localhost”,如果你的登录名真的是“joebob”,你可以缩短到这个:

db=_mysql.connect(passwd="moonpie",db="thangs")

UNIX套接字和命名管道不能通过网络工作,因此如果您指定除localhost以外的主机,将使用TCP,如果需要,您可以指定奇数端口(默认端口为3306):

db=_mysql.connect(host="outhouse",port=3307,passwd="moonpie",db="thangs")

如果真的需要,您可以通过指定完整的主机名或127.0.0.1与TCP连接到本地主机。

一般来说,在你的代码中加入密码不是一个好主意:

db=_mysql.connect(host="outhouse",db="thangs",read_default_file="~/.my.cnf")

这做了前面的例子,但从~/.my.cnf(类UNIX系统)获取用户名和密码和其他参数。有关更多详情,请参阅 option files

所以现在你有一个打开的连接为 db,并想要做一个查询。嗯,MySQL没有游标,没有参数替换,所以你必须传递一个完整的查询字符串到 db.query():

db.query("""SELECT spam, eggs, sausage FROM breakfast
         WHERE price < 5""")

这里没有返回值,但可以引发异常。异常在单独的模块 _mysql_exceptions 中定义,但 _mysql 导出它们。读取DB API规范 PEP-249 以了解它们是什么,或者您可以使用catch-all MySQLError

此时,您的查询已执行,您需要获取结果。你有两个选择:

r=db.store_result()
# ...or...
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.columnhow=2 表示与 how=1 相同,除了键是 always table.column;这是为了与旧的 Mysqldb 模块兼容。

好了,为什么我们得到一个1元组与元组里面?因为我们隐式要求一行,因为我们没有指定 maxrows

另一个奇怪的是:假设这些是数字列,为什么它们作为字符串返回?因为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_LONGINTEGER 列,其对应于C long,其也是用于正常Python整数的类型。但要注意:如果它真的是一个 UNSIGNED INTEGER 列,这可能会导致溢出。因此,MySQLdb 实际上使用 long() 进行转换。但我们现在就忽略这个潜在的问题。

然后,如果你使用 db=_mysql.connect(conv=my_conv...),结果将回来 ((3, 2, 0),),这是你会期望的。

MySQLdb

MySQLdb是一个围绕 _mysql 的薄Python包装器,它使它与Python DB API接口(版本2)兼容。实际上,为了效率的缘故,实现API的大量代码在 _mysql 中。

DB API规范 PEP-249 应成为使用此模块的主要指南。只有与规范和其他数据库相关的东西的偏差将在这里记录。

功能和属性

只有几个顶级函数和属性在MySQLdb中定义。

连接(参数...)

用于创建与数据库的连接的构造函数。返回连接对象。参数与MySQL C API相同。此外,还有一些额外的关键字对应于您在连接前将通过 mysql_options()。注意,一些参数必须指定为关键字参数!根据需要,每个参数的默认值为NULL或零。有关更多详细信息,请参阅MySQL文档。重要参数有:

主办

要连接的主机的名称。默认值:通过UNIX套接字使用本地主机(如果适用)

用户

用户认证为。默认值:当前有效用户。

密码

密码进行身份验证。默认值:无密码。

db

数据库使用。默认值:无默认数据库。

港口

MySQL服务器的TCP端口。默认值:标准端口(3306)。

unix_socket

UNIX套接字的位置。默认值:对远程主机使用默认位置或TCP。

转换

类型转换字典。默认值:MySQLdb.converters.conversions 的副本

压缩

启用协议压缩。默认值:无压缩。

connect_timeout

如果连接在给定的秒数内未完成,则中止。默认值:no timeout(?)

named_pipe

使用命名管道(Windows)。默认值:不。

init_command

连接时发送到服务器的初始命令。默认值:无。

read_default_file

MySQL配置文件读取;请参阅 mysql_options() 的MySQL文档。

read_default_group

要读取的默认组;请参阅 mysql_options() 的MySQL文档。

cursorclass

cursor() 使用的游标类,除非被覆盖。默认值:MySQLdb.cursors.Cursor这必须是关键字参数。

use_unicode

如果为True,则使用配置的字符集将CHAR和VARCHAR和TEXT列作为Unicode字符串返回。最好在服务器配置或客户端配置(使用read_default_file读取)中设置默认编码。如果在连接后更改字符集(MySQL-4.1及更高版本),则需要在connection.charset中输入正确的字符集名称。

如果为False,则类似文本的列将作为普通字符串返回,但您始终可以编写Unicode字符串。

这必须是关键字参数。

字符集

如果存在,连接字符集将更改为此字符集,如果它们不相等。支持更改字符集需要MySQL-4.1及更高版本的服务器;如果服务器太旧,将引发UnsupportedError。此选项意味着use_unicode = True,但您可以使用use_unicode = False覆盖此选项,但您可能不应该。

如果不存在,则使用默认字符集。

这必须是关键字参数。

sql_mode

如果存在,会话SQL模式将设置为给定的字符串。有关sql_mode的更多信息,请参阅MySQL文档。仅适用于4.1和更新的服务器。

如果不存在,会话SQL模式将不会更改。

这必须是关键字参数。

ssl

此参数采用字典或映射,其中键是 mysql_ssl_set MySQL C API调用使用的参数名称。如果设置此选项,它将启动到服务器的SSL连接;如果客户端中没有SSL支持,则会引发异常。 这必须是关键字参数。

apilevel

字符串常量,说明受支持的DB API级别。 ‘2.0’

线程安全

整数常量,说明接口支持的线程安全级别。这被设置为1,这意味着:线程可以共享模块。

MySQL协议不能一次处理使用相同连接的多个线程。一些早期版本的MySQLdb使用锁定来实现线程安全2.虽然这不是很难完成使用标准的Cursor类(使用 mysql_store_result()),它是复杂的SSCursor(使用 mysql_use_result();后者必须确保所有在另一个查询可以被执行之前已经读取了行,由于事务在游标执行查询时启动,而在Connection对象执行 COMMITROLLBACK 时结束,因此进一步复杂化了两个线程根本不能共享一个事务正在进行中的连接,除了不能在查询执行期间共享它。这使代码过于复杂到它不值得的地方。

这样做的一般结果是:不要在线程之间共享连接。这真的不值得你的努力或我的,最后,可能会损害性能,因为MySQL服务器为每个连接运行一个单独的线程。你当然可以做一些事情,如缓存池中的连接,并将这些连接一次一个线程。如果你让两个线程同时使用连接,MySQL客户端库可能会upchuck和死亡。你被警告了。

对于线程应用程序,请尝试使用连接池。这可以使用 Pool module 来完成。

字符集

连接使用的字符集。在MySQL-4.1及更高版本中,可以(但不推荐)使用SQL语句更改连接的字符集。如果您这样做,您还需要更改此属性。否则,您会收到编码错误。

paramstyle

字符串常量,说明接口期望的参数标记格式的类型。设置为’format’= ANSI C printf格式代码,例如’... WHERE name =%s’。如果一个映射对象用于conn.execute(),那么接口实际上使用’pyformat’= Python扩展格式代码,例如。 ‘... WHERE name =%(name)s’。然而,API目前不允许在paramstyle中规定多个样式。

请注意,传递给execute()的查询字符串中的任何文字百分号都必须转义,即%%。

参数占位符可以使用 只要 来插入列值。他们可以将 用于SQL的其他部分,例如表名,语句等。

转换

控制类型如何从MySQL转换为Python或反之亦然的字典或映射。

如果密钥是MySQL类型(来自 FIELD_TYPE.*),则该值可以是:

  • 一个可调用的对象,它接受一个字符串参数(MySQL值),返回一个Python值

  • 2元组的序列,其中第一值是来自 MySQLdb.constants.FLAG 的标志的组合,并且第二值是如上所述的函数。测试序列,直到字段上的标志与第一个值的标志匹配。如果两个值都为None,则默认转换完成。目前,这只用于区分TEXT和BLOB列。

如果键是Python类型或类,那么值是一个可调用的Python对象(通常是一个函数),它接受两个参数(要转换的值和转换字典),将此类型的值转换为SQL文字字符串值。

对于大多数类型,这是用合理的默认值初始化的。创建Connection对象时,可以将自己的类型转换器字典作为关键字参数传递。否则,它使用 MySQLdb.converters.conversions 的副本。几个非标准类型作为字符串返回,这就是MySQL如何返回所有列。有关更多详细信息,请参阅内置模块文档。

连接对象

连接对象由 connect() 函数返回。

承诺()

如果数据库和表支持事务,则提交当前事务;否则此方法不会成功。

rollback()

如果数据库和表支持事务,则回滚(取消)当前事务;否则提出 NotSupportedError

游标([cursorclass])

MySQL不支持游标;但是,光标容易模拟。您可以提供替代游标类作为可选参数。如果不存在,则默认为创建连接对象时给定的值,或标准 Cursor 类。还可以在用法部分中查看附加的提供的游标类。

在连接对象上定义了许多特定于MySQL的方法。有关它们的更多信息,请参阅使用 pydoc 的内部文档。

光标对象

callproc(procname,args)

使用args中的参数序列调用存储过程procname。返回原始参数。存储过程支持仅适用于MySQL-5.0及更高版本。

兼容性说明: PEP-249 指定如果有OUT或INOUT参数,则返回修改的值。这不是始终可能与MySQL。存储过程参数必须作为服务器变量传递,并且只能使用SELECT语句返回。由于存储过程可能返回零个或多个结果集,因此MySQLdb不可能确定在修改的参数可访问之前是否有要提取的结果集。

参数作为@ _ * procname * _ * n 存储在服务器中,其中 *n 是参数的位置。也就是说,如果你使用cursor.callproc(’foo’,(a,b,c)),参数就可以被一个SELECT语句作为@ _foo_0,@ _foo_1和@ _foo_2访问。

兼容性说明: 看来,执行CALL语句的纯粹动作产生一个空结果集,它出现在可能由存储过程生成的任何结果集之后。因此,您将总是需要使用nextset()来推进结果集。

关()

关闭光标。未来运营提高 ProgrammingError。如果使用服务器端游标,在完成操作后和创建新游标之前关闭游标非常重要。

信息()

返回关于最后一个查询的一些信息。通常你不需要检查这个。如果有任何MySQL警告,将导致通过Python警告模块发出警告。默认情况下,警告会在控制台上显示一条消息。但是,可以过滤这些或导致警告作为异常引发。请参阅 mysql_info() 的MySQL文档和Python警告模块。 (非标)

setinputsizes()

什么也没有,成功。

setoutputsizes()

什么也没有,成功。

nextset()

将光标移动到下一个结果集,丢弃当前结果集中的剩余行。如果没有其他结果集,则返回None;否则返回一个真值。

注意MySQL不支持多个结果集直到4.1。

一些例子

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”。

为什么是元组?因为DB API要求您将任何参数作为序列传递。由于解析器的设计,(max_price)被解释为使用代数分组,只是作为max_price而不是一个元组。添加逗号(即(max_price))迫使它创建一个元组。

现在,结果:

>>> c.fetchone()
(3L, 2L, 0L)

_mysql 示例非常不同,这返回一个单一的元组,这是行,并且值被正确转换默认...除了...与L’的是什么?

如前所述,MySQL INTEGER列完全转换为Python整数,UNSIGNED INTEGER可能溢出,因此这些值将转换为Python长整数。

如果你想要更多的行,你可以使用 c.fetchmany(n)c.fetchall()。这些正是你认为他们做的。在 c.fetchmany(n) 上,n 是可选的,默认为 c.arraysize,通常为1.这两个方法都返回一个行序列,如果没有更多的行,则返回一个空序列。如果你使用奇怪的游标类,行本身可能不是元组。

注意,与上述相反,当没有更多的行要获取时,c.fetchone() 返回 None

你唯一可能使用的其他方法是当你必须做一个多行插入:

c.executemany(
      """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,浮动),虽然我们仍然只使用 %s。还要注意,我们只包括一行的格式字符串。 MySQLdb选择那些并且为每行重复它们。

使用和扩展

一般来说,除了小应用程序之外,不要直接与DB API交互是明智的。数据库,甚至SQL数据库,功能差异很大,可能具有非标准功能。 DB API很好地提供了一个合理的可移植接口,但是一些方法是不可移植的。具体来说,connect() 接受的参数完全取决于实现。

如果您认为您的应用程序可能需要在几个不同的数据库上运行,作者建议根据个人经验采用以下方法:为应用程序编写一个简化的API,实现应用程序需要执行的特定查询和操作。实现这个API作为一个基类,应该有很少的数据库依赖,然后从这里派生一个子类实现必要的依赖。这样,将应用程序移植到新数据库应该是一个相对简单的事情,创建一个新的子类,假设新数据库是合理的标准。

因为MySQLdb的Connection和Cursor对象是用Python编写的,你可以很容易地导出自己的子类。在MySQLdb游标中有几个Cursor类:

BaseCursor

Cursor对象的基类。这不会提高警告。

CursorStoreResultMixIn

导致Cursor使用 mysql_store_result() 函数获取查询结果。整个结果集存储在客户端。

CursorUseResultMixIn

使光标使用 mysql_use_result() 函数获取查询结果。结果集存储在服务器端,并使用提取操作逐行传输。

CursorTupleRowsMixIn

使游标返回行作为列值的元组。

CursorDictRowsMixIn

使游标返回作为字典的行,其中键是列名称,值是列值。请注意,如果列名不是唯一的,即您正在从共享列名的两个表中进行选择,则其中一些将被重写为 table.column。这可以通过使用SQL AS 关键字来避免。 (这是尚未在SQL查询中使用 * 的另一个原因,特别是涉及 JOIN 的地方。)

光标

默认游标类。这个类由 CursorWarningMixInCursorStoreResultMixInCursorTupleRowsMixIn,BaseCursor 组成,即它提出 Warning,使用 mysql_store_result(),并返回行作为元组。

DictCursor

Cursor,除了它返回行作为字典。

SSCursor

“服务器端”光标。像 Cursor,但使用 CursorUseResultMixIn。仅当您处理潜在的大型结果集时使用。

SSDictCursor

SSCursor,除了它返回行作为字典。

嵌入式服务器

嵌入式服务器支持不是通过网络连接到独立服务器,而是允许您在Python代码或应用程序服务器中运行完整的服务器。

如果你已经构建了MySQLdb嵌入式服务器支持,还有两个额外的功能,你需要使用:

server_init(args,groups)

初始化嵌入式服务器。如果此客户端未链接嵌入式服务器库,则此函数不执行任何操作。

args

命令行参数序列

在默认文件中使用的组序列

server_end()

关闭嵌入式服务器。如果不使用嵌入式服务器,则什么也不做。

有关嵌入式服务器的更多信息,请参阅MySQL文档。

Title:

MySQLdb:MySQL的Python接口

Author:

安迪·达斯曼

Version:

$ Revision $