遭瘟的pyodbc——关于存储过程执行

原创 2015年11月21日 13:32:20

由于需要使用django连接SQL Server,烦人的事情随之而来。

首先Django 没有自带针对MSSQL的BackEnds,所以要自己包装,这个很烦很烦,烦到死了,每次部署到新的机器上都要调试很久。

可以见我之前写的这篇文章:Django连接SQL Server配置指引,其实是可以成功的,但是每次都要配置,太过麻烦了。

而且只能连接一个数据库,如果要连接多个数据库,无法避免要使用pyodbc(或者其它第三方包)来连接。

 

pyodbc,运行Query SQL是不在话下的,非常简单,上面说的文章也有说使用方法:

import pyodbc

connection = pyodbc.connect('DRIVER={SQL Server Native Client 10.0};SERVER=127.0.0.1;DATABASE=DB_name;UID=User_Name;PWD=PassWord')
curs = connection.execute('select * from some_table')
curs.fetchone()


但是如果要执行存储过程,就痛苦了。

---------------------------------------

冷静一下。

先说说pyodbc的基本用法:

1. 先导入:from pyodbc import connect;

2. 产生连接实例:Conn = connect(DBCONNECTSTR);

3. 产生游标:cur = Conn.cursor();

4. 执行游标命令:cur.execute()、cur.commit()、cur.rollback()之类;

5. 关闭游标:cur.close();

6. 关闭连接实例:Conn.close()。

 

以上6个步骤都是必要的。

当然,如果仅仅是查询,可以直接使用实例直接运行excute命令就可以了,可以不创建游标,那么3、4、5步都可以省略。

上面这些内容网上一大堆教程,我就不多说了。(DRY=Donot Repeat Yourself)

不过网上很多文章都是误导,例如:Python连接数据库-pyodbc

里面说运行存储过程使用 callproc() 方法。

我勒个去,这个方法完全是她YY出来的。

 

提供 connection 和 cursor 的方法列表:

>>> dir(Conn)

['__class__', '__delattr__', '__doc__', '__enter__', '__exit__', '__format__', '__getattribute__', '__hash__', '__init__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'add_output_converter', 'autocommit', 'clear_output_converters', 'close', 'commit', 'cursor', 'execute', 'getinfo', 'rollback', 'searchescape', 'timeout']

>>> dir(cur)

['__class__', '__delattr__', '__doc__', '__enter__', '__exit__', '__format__', '__getattribute__', '__hash__', '__init__', '__iter__', '__new__', '__reduce__','__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'arraysize', 'close', 'columns', 'commit', 'connection', 'description', 'execute', 'executemany', 'fetchall', 'fetchmany', 'fetchone', 'foreignKeys', 'getTypeInfo', 'next', 'nextset', 'noscan', 'primaryKeys', 'procedureColumns', 'procedures', 'rollback', 'rowIdColumns', 'rowVerColumns', 'rowcount', 'setinputsizes', 'setoutputsize', 'skip', 'statistics', 'tables']

 

常用的方法和标量我都标记为红色了。

回归正题,执行存储过程用哪个方法呢?不用多想了,还是execute(),然后附加 EXEC 当作SQL命令来执行。

try:
    #不关心返回数据存储过程执行方法
    cur.execute('EXEC P_THIS_IS_A_PROCDURE param1,param2,%d,%s' %(p3_int,p4_str))
    print cur.rowcount  #可以得到存储过程影响的行数
    #如果你关心返回值,需要使用这种方式
    rows = cur.execute('SET NOCOUNT ON; EXEC P_THIS_IS_A_PROCDURE param1,param2,%d,%s' %(p3_int,p4_str)).fetchall()
    print cur.rowcount,rows   #聪明的你已经知道,行数肯定是木有的了(-1),后面的rows是一个列表,看你的数据是咋样的了。
    #无论何种方式,都可以最后才commit(其实方式2已经默认包含了commit)
    cur.commit()
except Exception as e:
    print e


上面已经写得比较清楚了,直接执行存储过程就使用EXEC就好了。

如果需要得到返回数据(即存储过程里面有 Select出来的内容),就需要加上SET NOCOUNT ON;参数。参考资料:MSSQL2008 - Pyodbc - Previous SQL was not a query

所以我TMD为了配合pyodbc,存储过程都需要加上一个selet语句,把return值给select出来。

我已经吐了。

变通的方法:

可以写一个外层存储过程,统一调用这个存储过程,把返回值给select出来就好了。

CREATE PROCEDURE P_RUN_PROCDURE_WITH_SELECTRETURN
    @I_ProcName NVARCHAR(1000) ,
    @I_Params NVARCHAR(1000)
AS
    DECLARE @SqlStr NVARCHAR(MAX)
    
    /**
    * 返回值列表:
    * 0  正常退出,存储过程执行成功
    * 1  异常退出,参数校验失败
    * ……这个随便你写了,主要是和你存储过程里面的return相关
    */
    
    SET @SqlStr = 'DECLARE @res INT; EXEC @res = ' + @I_ProcName + ' ' + @I_Params + '; SELECT  @res'
    EXEC(@SqlStr)
    
GO


 调用方法:

EXEC P_RUN_PROCDURE_WITH_SELECTRETURN 'P_DIM_CONSTANT_TOGGLESTATUS','100,''some_string'',123.45'  --带参

EXEC P_RUN_PROCDURE_WITH_SELECTRETURN 'P_DIM_AMB_PATHCREATE',''   --不带参

 

版权声明:本文为sam的原创文章,转载请添加出处:http://blog.csdn.net/samed

pyodbc的简单使用

1、连接数据库 1)直接连接数据库和创建一个游标(cursor) ? 1 2 cnxn = pyodbc.connect('DRIVER={SQL Server};SERVER=l...
  • u013013708
  • u013013708
  • 2016年04月07日 15:55
  • 2963

pyodbc访问数据库(python ODBC访问数据库)

python通过ODBC访问数据库。使用pyodbc,快速达成目标
  • supperman_009
  • supperman_009
  • 2016年07月08日 17:34
  • 7926

python︱用pyodbc连接数据库

直接连接数据库和创建一个游标(cursor) 数据查询(SQL语句为 select …from..where) 1、pyodbc连接import pyodbccnxn = pyodbc.connect...
  • sinat_26917383
  • sinat_26917383
  • 2017年06月29日 17:44
  • 1364

python ODBC库 pyodbc

python ODBC库 pyodbc pyodbc是一个Python模块,能够让你使用 ODBC 连接来自Windows, Linux, OS/X等系统中的大部分数据库。它实际了Pyt...
  • u011822516
  • u011822516
  • 2014年06月29日 19:16
  • 2782

Python模块依赖

用matplotlib软件包绘个图,但发现其还依赖一个库numpy 想测试一个库有没有或者依赖其他的库可以在命令行下执行import命令,如果没有它会打印出所依赖的库,如下图 ma...
  • lanbingg
  • lanbingg
  • 2013年04月07日 18:08
  • 1008

Python连接数据库-pyodbc

1、连接sql server: conn_info = 'DRIVER={SQL Server};DATABASE=%s;SERVER=%s;UID=%s;PWD=%s'%(database, ho...
  • meylovezn
  • meylovezn
  • 2014年06月20日 10:42
  • 12894

python用pyodbc存入SQL SEVER

def save_to_mytsql(result): conn = pyodbc.connect('DRIVER={SQL Server};SERVER=localhost;DATABASE...
  • akon_wang_hkbu
  • akon_wang_hkbu
  • 2017年08月21日 09:55
  • 237

pyodbc模块简单总结整理

连接到数据库 调用connect方法并传入ODBC连接字符串,其会返回一个connect对象。通过connect对象,调用cursor()方法,可以获取一个游标cursor。如下代码示例: i...
  • u010541307
  • u010541307
  • 2016年10月20日 22:11
  • 2165

Python如何执行存储过程,获取存储过程返回值

在Pathon中如何执行存储过程呢?可以使用如下方法:存储过程定义基本如下:ALTER  procedure [dbo].[mysp]         @Station varchar(50),   ...
  • andoring
  • andoring
  • 2011年06月23日 23:32
  • 11382

【python 调用储存过程】python 执行储存过程

# -*- coding:utf-8 -*-import sys reload(sys) sys.setdefaultencoding('utf-8') import pymysql conn=pym...
  • u013421629
  • u013421629
  • 2017年06月07日 15:33
  • 2553
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:遭瘟的pyodbc——关于存储过程执行
举报原因:
原因补充:

(最多只允许输入30个字)