Найти - Пользователи
Полная версия: Будни с MySQLdb
Начало » Базы данных » Будни с MySQLdb
1
securelord
Можно ли заменить такой ужас:
cursor.execute('CALL my_proc ('+'\''+var1+'\', '+'\''+var2+'\', '+'\''+var3+'\', '+'\''+var4+'\'); COMMIT;')
на что нибудь более лаконичное? А то как то стремно такой код кому то показывать :)
slivlen
Для вызова процедур у курсора есть функция callproc. Читай доки по DB API 2 и MySQLdb. :)
AlexKiriukha
Цитата с http://www.python.org/dev/peps/pep-0249/
.callproc(procname)

(This method is optional since not all databases provide stored procedures. )

Call a stored database procedure with the given name. The sequence of parameters must contain one entry for each argument that the procedure expects. The result of the call is returned as modified copy of the input sequence. Input parameters are left untouched, output and input/output parameters replaced with possibly new values.

The procedure may also provide a result set as output. This must then be made available through the standard fetchXXX() methods.
Конкретно по MySQL примера не нашёл, но есть по Sybase и по идее должно работать и в MySQL.
import sys
import Sybase
db = Sybase.connect(..., auto_commit=True)
db.execute('''
if exists (select name from sysobjects where name = "sp_test_leak")
begin
    drop procedure sp_test_leak
end
''')
db.execute('''
create procedure sp_test_leak
    @arg int
as
    select @arg
''')
for i in range(200):
    for j in range(1000):
        c = db.cursor()
        c.callproc('sp_test_leak', {'@arg': 12345 })
    sys.stdout.write('%3d\r' % i)
    sys.stdout.flush()
sys.stdout.write('\n')
Пример взят с http://coding.derkeiler.com/Archive/Python/comp.lang.python/2005-04/msg01190.html
Для вообще понятия работы в python с MySQL и не только, IMHO стоит просмотреть http://dustman.net/andy/python/python-and-mysql
slivlen
AlexKiriukha
Конкретно по MySQL примера не нашёл, но есть по Sybase и по идее должно работать и в MySQL.
Не факт :) В cx_Oracle н-р совершенно другой стиль передачи аргументов в хранимые процедуры и функции.
AlexKiriukha
slivlen
Не факт smile В cx_Oracle н-р совершенно другой стиль передачи аргументов в хранимые процедуры и функции.
Возможно, не сталкивался (как и с MySQL). Поэтому проэкспериментировал. База данных world, которая есть где-то на сайте MySQL, mysql-server-5.0.45, MySQL-python-1.2.2

DELIMITER $$
DROP PROCEDURE IF EXISTS getCitiesForCountry$$
CREATE PROCEDURE getCitiesForCountry(IN countryName CHAR(52))
BEGIN
	SELECT City.Name, City.District, City.Population FROM Country c
		LEFT JOIN City ON c.Code = City.CountryCode
		WHERE c.Name = countryName;
END$$
DELIMITER ;

Вот так работает:
import MySQLdb
db = MySQLdb.connect(db = 'world', host = '127.0.0.1', user = 'root', passwd = 'Hm...')
c = db.cursor()
c.callproc('getCitiesForCountry', ('United Kingdom',))
for row in c:
	print 'Name: %s District: %s Population: %s' % (row[0], row[1], row[2])

Правда в исходниках (файл cursors.py) есть такое замечание:
Compatibility warning: The act of calling a stored procedure
itself creates an empty result set. This appears after any
result sets generated by the procedure. This is non-standard
behavior with respect to the DB-API. Be sure to use nextset()
to advance through all result sets; otherwise you may get
disconnected.
slivlen
А как получить значения OUT или INOUT аргументов процедуры?
AlexKiriukha
slivlen
А как получить значения OUT или INOUT аргументов процедуры?
Читаем дальше файл cursors.py:
Compatibility warning: PEP-249 specifies that any modified
parameters must be returned. This is currently impossible
as they are only available by storing them in a server
variable and then retrieved by a query. Since stored
procedures return zero or more result sets, there is no
reliable way to get at OUT or INOUT parameters via callproc.
The server variables are named @_procname_n, where procname
is the parameter above and n is the position of the parameter
(from zero). Once all result sets generated by the procedure
have been fetched, you can issue a SELECT @_procname_0, …
query using .execute() to get any OUT or INOUT values
Таким образом (код взят с http://dev.mysql.com/doc/refman/5.0/en/call.html):
DELIMITER $$
DROP PROCEDURE IF EXISTS p$$
CREATE PROCEDURE p (OUT ver_param VARCHAR(25), INOUT incr_param INT)
BEGIN
  # Set value of OUT parameter
  SELECT VERSION() INTO ver_param;
  # Increment value of INOUT parameter
  SET incr_param = incr_param + 1;
END$$
DELIMITER ;
import MySQLdb
db = MySQLdb.connect(db = 'world', host = '127.0.0.1', user = 'root', passwd = 'password')
c = db.cursor()
c.callproc('p', ('', 12))
c.execute('SELECT @_p_0, @_p_1')
for row in c:
	print 'Version: %s Increment: %s' % (row[0], row[1])
Честно говоря не уверен, что это лучший вариант, но так точно работает.
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB