1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714
|
<!DOCTYPE linuxdoc system>
<article>
<title>MySQLdb: a Python interface for MySQL
<author>Andy Dustman
<date>$Id: MySQLdb.sgml,v 1.7 2001/07/11 18:13:09 adustman Exp $
<abstract>MySQLdb is an thread-compatible interface to the popular
MySQL database server that provides the Python database API.
<sect>Introduction
<P>This module should be <ref id="MySQLmodule" name="mostly
compatible"> with an older interface written by Joe Skinner and
others. However, the older version is a) not thread-friendly (database
operations could cause all other threads to block), b) written for
MySQL 3.21 (does not compile against newer versions without patches),
c) apparently not actively maintained. MySQLdb is a completely new
module, distributed free of charge under the GNU Public License.
<p>
<sect1>Platforms
<p>
<sect2>Linux/UNIX
<p>
This module is developed on RedHat Linux (currently 7.1) for Intel. It
should build without much trouble on most platforms by using the
<tt/setup.py/ script. Supposedly it builds on MacOS X. Be aware that
you need the Distutils package which comes with Python 2.0. If you
don't have it (i.e. you have Python 1.5.2), you can find it over at
<htmlurl url="http://www.python.org/" name="www.python.org">.
<sect2>Windows (3.11, 95, 98, NT, 2000, CE, BSOD, XYZ, etc.)
<p>
Windows is <em/not/ a supported platform. However, the <tt/setup.py/
script reportedly gets the job done. There is probably a link on the
web page for getting a precompiled Windows installer from someone or
other. Be aware that this is a user-contributed package; the author
cannot help you with compiling and running under Windows.
<sect1>Python
<p>
MySQLdb requires Python 1.5.2 or newer. Earlier versions will not
work, because support for C <tt/long long/ is required by MySQL. If
you have an earlier version of Python, upgrade to 1.5.2 or beyond.
Current development is done with Python 2.1, but Python 1.5.2 will be
supported for the forseeable future.
<sect1>MySQL
<p>
<sect2>MySQL-3.22
<p>
Only versions 3.22.32 and up are guaranteed to work. Some older
versions may work; if you have an older version you should seriously
consider upgrading to get the bug fixes and particularly the security
updates.
MySQL-3.22 seems to have a problem trying to insert <tt/TIME/ values
with fractional seconds. Values like 12:56:13.00 are returned as
344:13:00, apparently interpreting the original input as 12 days, 56
hours, 13 minutes, 0 seconds. (12 days and 56 hours is 344 hours.) To
avoid this problem, use the <tt/DateTimeDelta/ type.
<sect2>MySQL-3.23
<p>
MySQL-3.23 is now stable (3.23.37 as of this writing). MySQLdb
supports transactions if the <em/server/ supports them. Even then,
this does not guarantee that transactions will work. For that, you
must use a transaction-safe table (TST). Current TSTs are BDB and
InnoDB. GEMINI tables are slated for MySQL-4.0. Note that MySQL
generally operates in <tt/AUTOCOMMIT/ mode by default, and MySQLdb
assumes that <tt/AUTOCOMMIT/ is on by default. To change this, use the
<tt/SET AUTOCOMMIT=0/ SQL statement.
<sect1>DateTime <p>If you have the <htmlurl
url="http://www.lemburg.com/files/python/mxDateTime.html"
name="mx.DateTime"> package installed (recommended), MySQLdb will use
it for date-related objects. Otherwise, these will be returned to
Python as strings. You can also modify the type conversion
dictionary to return these as other object classes, if you prefer.
<sect1>MySQLmodule<label id="MySQLmodule">
<p>
MySQLmodule, the older MySQL interface by Joe Skinner and others, is
also a split C/Python interface. <tt/MySQL/, the C portion, has an
interface similar to perl's DBI internally. In addition, there is
Python portion, <tt/Mysqldb/, which provides a DB API v1.0 interface,
written by James Henstridge. MySQLdb-0.2.2 and up include
<tt/CompatMysqldb/, which is an adaptation of <tt/Mysqldb/ to
<tt/_mysql/. It should be considered experimental.
In contrast, MySQLdb's C portion, <tt><ref id="_mysql"></tt>, is
designed to mimic the MySQL C API in an object-oriented way; you
should not expect to move from <tt/MySQL/ to <tt/_mysql/ without a
fair amount of work. <tt><ref id="MySQLdb"></tt> provides a DB API
v2.0 interface, which has some changes from the v1.0 interface. Things
to watch out for in particular:
<table>
<tabular ca="foo">
Operation | Mysqldb | MySQLdb
@ Connecting | <tt>db = Mysqldb.Mysqldb("db@host user pass")</tt>
| <tt>db = MySQLdb.connect(db='db', host='host', user='user', passwd='pass')</tt>
@ Implicit cursor | <tt>db.execute(SQL)</tt> |
implicit cursors dropped from DB API v2.0; always use <tt>c = db.cursor()</tt>
@ Fetch row as dictionary | <tt>c.fetchDict()</tt>,
keys are "<em/table.column/" |
not standard; alternate cursor class <tt>DictCursor</tt>
provides a dictionary interface,
keys are "<em/column/" or "<em/table.column/" if there are two columns
with the same name; use SQL <tt/AS/ to rename fields.
@ Transactions | <tt>db.commit()</tt> and <tt>db.rollback()</tt>
both exist and silently do nothing <ref id="rollback" name="(danger!)">
| <tt>db.commit()</tt> and <tt>db.rollback()</tt> work if the MySQL
server can perform transactions; otherwise <tt>db.rollback()</tt>
always fails
<caption>Mysqldb to MySQLdb changes</tabular></table>
<sect1>Zope and ZMySQLDA
<p>I wrote a <htmlurl url="http://dustman.net/andy/python/ZMySQLDA"
name="ZMySQLDA"> for use with MySQLdb. It's adapted from ZOracleDA
from Digital Creations, makers of Zope.
<sect1>Documentation
<p>The web page documentation may be slightly ahead of the latest
release and may reflect features of the next release. <sect1>FAQs
<p>A FAQ is available at <htmlurl
url="http://dustman.net/andy/python/MySQLdb/faq/MySQLdb-FAQ.html">.
<sect>_mysql module<label id="_mysql">
<P>
If you want to write applications which are portable across databases,
avoid using this module directly. <tt>_mysql</tt> provides an
interface which mostly implements the MySQL C API. For more
information, see the MySQL documentation. The documentation for this
module is intentionally weak because you probably should use the
higher-level <ref id="MySQLdb"> module. If you really need it, use the
standard MySQL docs and transliterate as necessary.
<sect1>MySQL C API translation
<p>
The MySQL C API has been wrapped in an object-oriented way. The only
MySQL data structures which are implemented are the <tt>MYSQL</tt>
(database connection handle) and <tt>MYSQL_RES</tt> (result handle)
types. In general, any function which takes <tt>MYSQL *mysql</tt> as
an argument is now a method of the connection object, and any function
which takes <tt>MYSQL_RES *result</tt> as an argument is a method of
the result object. Functions requiring none of the MySQL data
structures are implemented as functions in the module. Functions
requiring one of the other MySQL data structures are generally not
implemented. Deprecated functions are not implemented. In all cases,
the <tt>mysql_</tt> prefix is dropped from the name. Most of the
<tt>conn</tt> methods listed are also available as MySQLdb Connection
object methods. Their use is non-portable.
<table>
<tabular ca="MySQL C API function mapping">
C API | <tt>_mysql</tt>
@ <tt>mysql_affected_rows()</tt> | <tt>conn.affected_rows()</tt>
@ <tt>mysql_close()</tt> | <tt>conn.close()</tt>
@ <tt>mysql_connect()</tt> | <tt>_mysql.connect()</tt>
@ <tt>mysql_data_seek()</tt> | <tt>result.data_seek()</tt>
@ <tt>mysql_debug()</tt> | <tt>_mysql.debug()</tt>
@ <tt>mysql_dump_debug_info</tt> | <tt>conn.dump_debug_info()</tt>
@ <tt>mysql_escape_string()</tt> | <tt>_mysql.escape_string()</tt>
@ <tt>mysql_fetch_row()</tt> | <tt>result.fetch_row()</tt>
@ <tt>mysql_get_client_info()</tt> | <tt>_mysql.get_client_info()</tt>
@ <tt>mysql_get_host_info()</tt> | <tt>conn.get_host_info()</tt>
@ <tt>mysql_get_proto_info()</tt> | <tt>conn.get_proto_info()</tt>
@ <tt>mysql_get_server_info()</tt> | <tt>conn.get_server_info()</tt>
@ <tt>mysql_info()</tt> | <tt>conn.info()</tt>
@ <tt>mysql_insert_id()</tt> | <tt>conn.insert_id()</tt>
@ <tt>mysql_num_fields()</tt> | <tt>result.num_fields()</tt>
@ <tt>mysql_num_rows()</tt> | <tt>result.num_rows()</tt>
@ <tt>mysql_options()</tt> | <tt>_mysql.connect()</tt>
@ <tt>mysql_ping()</tt> | <tt>conn.ping()</tt>
@ <tt>mysql_query()</tt> | <tt>conn.query()</tt>
@ <tt>mysql_real_connect()</tt> | <tt>_mysql.connect()</tt>
@ <tt>mysql_real_query()</tt> | <tt>conn.query()</tt>
@ <tt>mysql_real_escape_string()</tt> | <tt>conn.escape_string()</tt>
@ <tt>mysql_row_seek()</tt> | <tt>result.row_seek()</tt>
@ <tt>mysql_row_tell()</tt> | <tt>result.row_tell()</tt>
@ <tt>mysql_select_db()</tt> | <tt>conn.select_db()</tt>
@ <tt>mysql_stat()</tt> | <tt>conn.stat()</tt>
@ <tt>mysql_store_result()</tt> | <tt>conn.store_result()</tt>
@ <tt>mysql_thread_id()</tt> | <tt>conn.thread_id()</tt>
@ <tt>mysql_use_result()</tt> | <tt>conn.use_result()</tt>
@ <tt>CLIENT_*</tt> | <tt>MySQLdb.constants.CLIENT.*</tt>
@ <tt>CR_*</tt> | <tt>MySQLdb.constants.CR.*</tt>
@ <tt>ER_*</tt> | <tt>MySQLdb.constants.ER.*</tt>
@ <tt>FIELD_TYPE_*</tt> | <tt>MySQLdb.constants.FIELD_TYPE.*</tt>
@ <tt>FLAG_*</tt> | <tt>MySQLdb.constants.FLAG.*</tt>
<caption>MySQL C API function mapping
</tabular>
</table>
<sect1>Some _mysql examples
<P>Okay, so you want to use <tt/_mysql/ anyway. Here are some examples.
<p>The simplest possible database connection is:
<code>
import _mysql
db=_mysql.connect()
</code>
This creates a connection to the MySQL server running on the local
machine using the standard UNIX socket (or named pipe on Windows),
your login name (from the USER
environment variable), no password, and does not <tt/USE/ a database.
Maybe this will work for you, if you have set up a configuration file,
i.e. (<tt>~/.my.cnf</tt>). Chances are you need to supply more
information.
<code>
db=_mysql.connect("localhost","joebob","moonpie","thangs")
</code>
This creates a connection to the MySQL server running on the local
machine via a UNIX socket (or named pipe), the user name
"joebob", the password "moonpie", and selects the initial database
"thangs".
<P>We haven't even begun to touch upon all the parameters <tt/connect()/
can take.
For this reason, I prefer to use keyword parameters:
<code>
db=_mysql.connect(host="localhost",user="joebob",
passwd="moonpie",db="thangs")
</code>
This does exactly what the last example did, but is arguably easier
to read. But since the default host is "localhost", and if your
login name really was "joebob", you could shorten it to this:
<code>
db=_mysql.connect(passwd="moonpie",db="thangs")
</code>
UNIX sockets and named pipes don't work over a network, so if you specify a host other
than localhost, TCP will be used, and you can specify an odd port
if you need to (the default port is 3306):
<code>
db=_mysql.connect(host="outhouse",port=3307,passwd="moonpie",db="thangs")
</code>
<p>If you really had to, you could connect to the local host with TCP
by specifying the full host name, or 127.0.0.1.
<p>
There are some other parameters you can use, and most of them aren't
needed, except for one, which we'll get to momentarily. For the rest,
read the built-in documentation. Python 2.1's <tt/pydoc/ module is
great for this.
<P>So now you have an open connection as <tt/db/ and want to do a
query. Well, there are no cursors in MySQL, and no parameter
substitution, so you have to pass a complete query string to
<tt/db.query()/:
<code>
db.query("""SELECT spam, eggs, sausage FROM breakfast
WHERE price < 5""")
</code>
There's no return value from this, but exceptions can be raised. The
exceptions are defined in a separate module, <tt/_mysql_exceptions/,
but <tt/_mysql/ exports them. Read the <htmlurl
url="http://www.python.org/topics/database/DatabaseAPI-2.0.html"
name="DB API specification"> to find out what they are, or you can use
the catch-all <tt/MySQLError/.
<P>At this point your query has been executed and you need to get the
results. You have two options:
<code>
r=db.store_result()
# ...or...
r=db.use_result()
</code>
Both methods return a result object. What's the difference?
<tt/store_result()/ returns the entire result set to the client
immediately. If your result set is really large, this could be a
problem. One way around this is to add a <tt/LIMIT/ clause to your
query, to limit the number of rows returned. The other is to use
<tt/use_result()/, which keeps the result set in the server and sends
it row-by-row when you fetch. This does, however, tie up server
resources, and it ties up the connection: You cannot do any more
queries until you have fetched <em/all/ the rows. Generally I
recommend using <tt/store_result()/ unless your result set is really
huge and you can't use <tt/LIMIT/ for some reason.
<P>Now, for actually getting real results:
<CODE>
>>> r.fetch_row()
(('3','2','0'),)
</CODE>
This might look a little odd. The first thing you should know is,
<tt/fetch_row()/ takes some additional parameters. The first one is,
how many rows (<tt/maxrows/) should be returned. By default, it
returns one row. It may return fewer rows than you asked for, but
never more. If you set <tt/maxrows=0/, it returns all rows of the
result set. If you ever get an empty tuple back, you ran out of rows.
<p>The second parameter (<tt/how/) tells it how the row should be
represented. By default, it is zero which means, return as a tuple.
<tt/how=1/ means, return it as a dictionary, where the keys are the
column names, or <tt/table.column/ if there are two columns with the
same name (say, from a join). <tt/how=2/ means the same as <tt/how=1/
except that the keys are <em/always/ <tt/table.column/; this is for
compatibility with the old <tt/Mysqldb/ module.
<P>OK, so why did we get a 1-tuple with a tuple inside? Because we
implicitly asked for one row, since we didn't specify <tt/maxrows/.
<P>The other oddity is: Assuming these are numeric columns, why are
they returned as strings? Because MySQL returns all data as strings
and expects you to convert it yourself. This would be a real pain in
the ass, but in fact, <tt/_mysql/ can do this for you. (And
<tt/MySQLdb/ does do this for you.) To have automatic type conversion
done, you need to create a type converter dictionary, and pass this
to <tt/connect()/ as the <tt/conv/ keyword parameter.
<p>The keys of <tt/conv/ should be MySQL column types, which in the
C API are <tt/FIELD_TYPE_*/. You can get these values like this:
<code>
from MySQLdb.constants import FIELD_TYPE
</code>
By default, any column type that can't be found in <tt/conv/ is
returned as a string, which works for a lot of stuff. For our
purposes, we probably want this:
<code>
my_conv = { FIELD_TYPE.LONG: int }
</code>
This means, if it's a <tt/FIELD_TYPE_LONG/, call the builtin
<tt/int()/ function on it. Note that <tt/FIELD_TYPE_LONG/ is an
<tt/INTEGER/ column, which corresponds to a C <tt/long/, which is also
the type used for a normal Python integer. But beware: If it's really
an <tt/UNSIGNED INTEGER/ column, this could cause overflows. For this
reason, <tt/MySQLdb/ actually uses <tt/long()/ to do the
conversion. But we'll ignore this potential problem for now.
<P>Then if you use <tt/db=_mysql.connect(conv=my_conv...)/, the
results will come back <tt/((3, 2, 0),)/, which is what you would
expect.
<sect>MySQLdb -- DB API interface<label id="MySQLdb">
<p>
MySQLdb is a thin Python wrapper around <tt><ref id="_mysql"></tt>
which makes it compatible with the Python DB API interface (version
2). In reality, a fair amount of the code which implements the API is
in <tt>_mysql</tt> for the sake of efficiency.
<p>
The <htmlurl
url="http://www.python.org/topics/database/DatabaseAPI-2.0.html"
name="DB API specification"> should be your primary guide for using
this module. Only deviations from the spec and other
database-dependent things will be documented here.
<sect1>Functions and attributes
<P>Only a few top-level functions and attributes are defined within
MySQLdb.
<descrip>
<tag><label id="connect()">connect(parameters...)</tag> Constructor
for creating a connection to the database. Returns a Connection
Object. Parameters are the same as for the MySQL C API. In
addition, there are a few additional keywords that correspond to
what you would pass <tt/mysql_options()/ before connecting. Note
that some parameters must be specified as keyword arguments! The
default value for each parameter is NULL or zero, as
appropriate. Consult the MySQL documentation for more
details. The important parameters are:
<descrip>
<tag>host</tag>
name of host to connect to. Default: use the local host
via a UNIX socket (where applicable)
<tag>user</tag>
user to authenticate as. Default: current effective user.
<tag>passwd</tag>
password to authenticate with. Default: no password.
<tag>db</tag>
database to use. Default: no default database.
<tag>port</tag>
TCP port of MySQL server. Default: standard port (3306).
<tag>unix_socket</tag>
location of UNIX socket. Default: use default location or
TCP for remote hosts.
<tag>conv</tag> type conversion dictionary.
Default: a copy of <tt/MySQLdb.converters.conversions/
<tag>compress</tag> Enable protocol compression. Default: no compression.
<tag>connect_timeout</tag> Abort if connect is not completed within
given number of seconds. Default: no timeout (?)
<tag>named_pipe</tag> Use a named pipe (Windows). Default: don't.
<tag>init_command</tag> Initial command to issue to server upon
connection. Default: Nothing.
<tag>read_default_file</tag> MySQL configuration file to read; see
the MySQL documentation for <tt/mysql_options()/.
<tag>read_default_group</tag> Default group to read; see the MySQL
documentation for <tt/mysql_options()/.
<tag>cursorclass</tag> cursor class that <tt/cursor()/ uses,
unless overridden. Default: <tt/MySQLdb.cursors.Cursor/.
<em/This must be a keyword parameter./
</descrip>
<tag>apilevel</tag>
String constant stating the supported DB API level. '2.0'
<tag>threadsafety</tag> Integer constant stating the level of thread
safety the interface supports. As of MySQLdb version 0.9.0, this
is set to 1, which means: Threads may share the module.
<p>The MySQL protocol can not handle multiple threads using the
same connection at once. Some earlier versions of MySQLdb utilized locking
to achieve a threadsafety of 2. While this is not terribly hard
to accomplish using the standard Cursor class (which uses
<tt/mysql_store_result()/), it is complicated by SSCursor (which
uses <tt/mysql_use_result()/; with the latter you must ensure
all the rows have been read before another query can be executed.
It is further complicated by the addition of transactions, since
transactions start when a cursor execute a query, but end when
<tt/COMMIT/ or <tt/ROLLBACK/ is executed by the Connection object.
Two threads cannot share a connection while a transaction is in
progress, in addition to not being able to share it during query
execution. This excessively complicated the code to the point where
it just isn't worth it. <p>The general upshot of this is: Don't
share connections between threads. It's really not worth your effort
or mine, and in the end, will probably hurt performance, since the MySQL
server runs a separate thread for each connection.
You can certainly do things like
cache connections in a pool, and give those connections to one
thread at a time. If you let two threads use a connection simultaneously,
the MySQL client library will probably upchuck and die.
You have been warned.
<tag>paramstyle</tag> String constant stating the type of parameter
marker formatting expected by the interface. Set to 'format' =
ANSI C printf format codes, e.g. '...WHERE name=%s'. If a
mapping object is used for conn.execute(), then the interface
actually uses 'pyformat' = Python extended format codes,
e.g. '...WHERE name=%(name)s'. However, the API does not
presently allow the specification of more than one style in
paramstyle.
Compatibility note: The older MySQLmodule uses a similar
parameter scheme, but requires that quotes be placed around
format strings which will contain strings, dates, and similar
character data. This is not necessary for MySQLdb. It is
recommended that %s (and not '%s') be used for all parameters,
regardless of type. The interface performs all necessary
quoting.
<tag><label id="conversions">conv</tag> A dictionary mapping MySQL types
(from <TT>FIELD_TYPE.*</TT>) to callable Python objects (usually
functions) which convert from a string to the desired type; and
mapping Python types to callable Python objects which convert
values of this type to a SQL literal string value. This is
initialized with reasonable defaults for most types. When
creating a Connection object, you can pass your own type
converter dictionary as a keyword parameter. Otherwise, it uses
a copy of <tt>MySQLdb.converters.conversions</tt>. The dictionary
includes some of the factory functions from the
<tt>DateTime</tt> module, if it is available. Several
non-standard types are returned as strings,
which is how MySQL returns all columns. For more details, see
the built-in module documentation.
<P>As of MySQL-3.23, MySQL supports different character sets in the
server, and a new quoting function, <tt/mysql_real_escape_string()/.
This requires the string quoting function to be a method bound to
the connection object. MySQLdb handles this for you automatically.
However, if you feel the need to do something goofy with your strings,
you will have to modify the dictionary after opening the connection.
In practice, you should never have to worry about this.
</descrip>
<sect1>Connection Objects
<P>Connection objects are returned by the <tt>connect()</tt> function.
<descrip>
<tag>commit()</tag> If the database and the tables support
transactions, this commits the current transaction; otherwise
this method successfully does nothing.
<tag><label id="rollback">rollback()</tag> If the database and tables
support transactions, this rolls back (cancels) the current
transaction; otherwise a <tt>NotSupportedError</tt> is raised.
Compatibility note: The older <ref id="MySQLmodule"> defines this method,
which sucessfully does nothing. This is dangerous behavior, as a
successful rollback indicates that the current transaction was
backed out, which is not true, and fails to notify the
programmer that the database now needs to be cleaned up by other
means.
<tag>cursor([cursorclass])</tag> MySQL does not support cursors;
however, cursors are easily emulated. You can supply an
alternative cursor class as an optional parameter. If this is
not present, it defaults to the value given when creating the
connection object, or the standard <tt/Cursor/ class. Also see
the additional supplied cursor classes in the <ref id="usage">
section.
<tag>begin()</tag> Explicitly start a transaction. Normally you do
not need to use this: Executing a query implicitly starts a new
transaction if one is not in progress. If AUTOCOMMIT is on, you
can use <tt/begin()/ to temporarily turn it off. AUTOCOMMIT will
resume after the next <tt/commit()/ or <tt/rollback/.
</descrip>
<sect1>Cursor Objects
<p>
<descrip>
<tag>callproc()</tag>
Not implemented.
<tag>close()</tag>
Closes the cursor. Future operations raise <tt/ProgrammingError/.
If you are using <ref id="SSCursor" name="server-side cursors">,
it is very important to close the cursor when you are done with
it and before creating a new one.
<tag/insert_id()/
Returns the last <tt/AUTO_INCREMENT/ field value inserted
into the database. (Non-standard)
<tag/info()/ Returns some information about the last query. Normally
you don't need to check this. With the default cursor, any MySQL
warnings cause <tt/Warning/ to be raised. If you are using a
cursor class without warnings, then you might want to use
this. See the MySQL docs for <tt/mysql_info()/. (Non-standard)
<tag>setinputsizes()</tag>
Does nothing, successfully.
<tag>setoutputsizes()</tag>
Does nothing, successfully.
</descrip>
<sect1>Some examples
<p>The <tt/connect()/ method works nearly the same as with <tt/_mysql/:
<code>
import MySQLdb
db=MySQLdb.connect(passwd="moonpie",db="thangs")
</code>
To perform a query, you first need a cursor, and then you can execute
queries on it.
<code>
c=db.cursor()
max_price=5
c.execute("""SELECT spam, eggs, sausage FROM breakfast
WHERE price < %s""", (max_price,))
</code>
In this example, <tt/max_price=5/ Why, then, use <tt/%s/ in the
string? Because MySQLdb will convert it to a SQL literal value, which
is the string '5'. When it's finished, the query will actually say,
"...WHERE price < 5".
<p>Why the tuple? Because the DB API requires you to pass in any
parameters as a sequence.
<p>And now, the results:
<CODE>
>>> c.fetchone()
(3L, 2L, 0L)
</CODE>
Quite unlike the <tt/_mysql/ example, this returns a single tuple,
which is the row, and the values are properly converted by default...
except... What's with the L's?
<P>As mentioned earlier, while MySQL's INTEGER column translates
perfectly into a Python integer, UNSIGNED INTEGER could overflow, so
these values are converted to Python long integers instead. Prior to
Python 1.6, long integers retained the L when converted to strings
with <tt/str()/. In 1.6 and later, <tt/str()/ does not include the L.
Of course, the L always prints when using <tt/repr()/, which is what
has happened here.
<P>When you are finished with a transaction, you should execute either
<tt/db.commit()/ or <tt/db.rollback()/. If your server and tables
don't support transactions, <tt/commit()/ will still work, but
<tt/rollback()/ will raise an exception. Note carefully that these are
methods of the <em/connection/ and not methods of the <em/cursor/,
even though <tt/c.execute(...)/ is what started the transaction.
<P>If you wanted more rows, you could use <tt/c.fetchmany(n)/ or
<tt/c.fetchall()/. These do exactly what you think they do. On
<tt/c.fetchmany(n)/, the <tt/n/ is optional and defaults to
<tt/c.arraysize/, which is normally 100. Both of these methods return
a sequence of rows, or an empty sequence if there are no more rows.
If you use a weird cursor class, the rows themselves might not be
tuples.
<P>Note that in contrast to the above, <tt/c.fetchone()/ returns <tt/None/
when there are no more rows to fetch.
<P>The only other method you are very likely to use is when you have to
do a multi-row insert:
<CODE>
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 )
]
)
</CODE>
Here we are inserting three rows of five values. Notice that there is
a mix of types (strings, ints, floats) though we still only use
<tt/%s/. And also note that we only included format strings for one
row. MySQLdb picks those out and duplicates them for each row.
<footnote>Baked beans are off!</footnote>
<sect>Using and extending<label id="usage">
<P>In general, it is probably wise to not directly interact with the
DB API except for small applicatons. Databases, even SQL databases,
vary widely in capabilities and may have non-standard features. The DB
API does a good job of providing a reasonably portable interface but
some methods are non-portable. Specifically, the parameters accepted
by <tt><ref id="connect()"></tt> are completely implementation-dependent.
If you believe your application may need to run on several different
databases, the author recommends the following approach, based on
personal experience: Write a simplified API for your application which
implements the specific queries and operations your application needs
to perform. Implement this API as a base class which should be have
few database dependencies, and then derive a subclass from this which
implements the necessary dependencies. In this way, porting your
application to a new database should be a relatively simple matter of
creating a new subclass, assuming the new database is reasonably
standard.
For an example of this, see the author's
<htmlurl url="http://dustman.net/andy/python"
name="SQLDict module">, which allows standard queries to be
defined and accessed using an object which looks like a
dictionary, and reads/writes user-defined objects.
Because MySQLdb's Connection and Cursor objects are written in Python,
you can easily derive your own subclasses. There are several Cursor
classes in MySQLdb.cursors:
<p>
<descrip>
<tag>BaseCursor</tag> The base class for Cursor objects.
This does not raise Warnings.
<tag>CursorWarningMixIn</tag> Causes the Warning exception to be raised
on queries which produce warnings.
<tag>CursorStoreResultMixIn</tag> Causes the Cursor to use the
<tt>mysql_store_result()</tt> function to get the query result. The
entire result set is stored on the client side.
<tag><label id="SSCursor">CursorUseResultMixIn</tag> Causes the cursor to use the
<tt>mysql_use_result()</tt> function to get the query result. The
result set is stored on the server side and is transferred row by row
using fetch operations.
<tag>CursorTupleRowsMixIn</tag> Causes the cursor to return rows
as a tuple of the column values.
<tag>CursorDictRowsMixIn</tag> Causes the cursor to return rows
as a dictionary, where the keys are column names and the values
are column values. Note that if the column names are not unique,
i.e., you are selecting from two tables that share column names,
some of them will be rewritten as <em/table.column/.
This can be avoided by using
the SQL <tt>AS</TT> keyword. (This is yet-another reason not to use
<tt/*/ in SQL queries, particularly where <tt/JOIN/ is involved.
<tag>Cursor</tag> The default cursor class. This class is composed
of <tt>CursorWarningMixIn, CursorStoreResultMixIn, CursorTupleRowsMixIn,</tt>
and <tt>BaseCursor</tt>, i.e. it raises <tt>Warning</tt>, uses
<tt>mysql_store_result()</tt>, and returns rows as tuples.
<tag>DictCursor</tag> Like <tt/Cursor/ except it returns rows as
dictionaries.
<tag>SSCursor</tag> A "server-side" cursor. Like <tt/Cursor/ but uses
<tt/CursorUseResultMixIn/.
Use only if you are dealing with potentially large result sets.
<tag/SSDictCursor/ Like <tt/SSCursor/ except it returns rows as
dictionaries.
<tag/XXXCursorNW/> Cursors with the "NW" suffix do not raise Warnings.
</descrip>
<p>For an example of how to use these classes,
read the code. If you need something more exotic than this,
you will have to roll your own.
</article>
|