在Python生态里操作DB2数据库,官方推荐的驱动就是ibm_db模块。它由IBM维护,底层基于CLI(Call Level Interface)实现,支持DB2 LUW、Db2 on Cloud以及z/OS等主流版本。这篇文章从安装讲起,把连接配置、SQL执行、结果集处理这几个环节完整过一遍,帮你避开新手最容易踩的坑。

一、ibm_db模块的安装与常见问题
安装ibm_db最直接的方式是使用pip。在命令行执行pip install ibm_db即可。这个模块自带了各平台预编译的二进制驱动,正常情况下不需要单独安装DB2客户端,这一点比很多老教程方便得多。如果是在内网环境,可以先在有网的机器上执行pip download ibm_db,把whl包拷贝过去再离线安装。
安装完成后,建议先做一次导入验证:
import ibm_db print(ibm_db.__version__)
如果导入时报ImportError: DLL load failed,多半是系统缺少Visual C++运行库(Windows)或者Python版本与预编译包不匹配。ibm_db对Python版本有要求,建议使用官方明确支持的版本。另外在Linux下如果遇到权限问题,可以尝试加--user参数安装到用户目录。
还有一个常见的坑:pip源的问题。某些镜像源同步不及时,可能拉到旧版本包,遇到莫名报错时可以切换到官方源重装一次:pip install ibm_db -i https://pypi.org/simple。
二、建立数据库连接的几种方式
连接DB2最核心的函数是ibm_db.connect()。它接收一个连接字符串和用户名、密码作为参数。连接字符串的格式是DATABASE=数据库名;HOSTNAME=主机;PORT=端口;PROTOCOL=TCPIP,各字段用分号分隔。
import ibm_db
# 拼接连接字符串
conn_str = "DATABASE=SAMPLE;HOSTNAME=192.168.0.1;PORT=50000;PROTOCOL=TCIPC"
conn_str = "DATABASE=SAMPLE;HOSTNAME=192.168.0.1;PORT=50000;PROTOCOL=TCPIP"
try:
conn = ibm_db.connect(conn_str, "db2inst1", "your_password")
print("连接成功")
except Exception as e:
print("连接失败:", e)
连接Db2 on Cloud这类云数据库时,连接方式完全一样,只是需要把HOSTNAME换成云服务给出的地址,PORT通常是50001并启用SSL,此时要加上Security=SSL参数。
如果程序里频繁建立和断开连接,性能会很差,ibm_db提供了连接池支持。用ibm_db.pconnect()建立持久连接,或者在应用启动时初始化连接池,之后每次取连接、用完归还,能明显减少握手开销。另外别忘了ibm_db.conn_error()这个函数,当连接失败时它能拿到具体的错误码和消息,比直接看异常信息更精确。
三、执行SQL与结果集处理
有了连接之后,执行SQL分两步:先用ibm_db.exec_immediate()或先prepare再execute。对于一次性的查询,直接用exec_immediate最简单:
import ibm_db
conn = ibm_db.connect(conn_str, "db2inst1", "your_password")
# 查询员工表
stmt = ibm_db.exec_immediate(conn, "SELECT EMPNO, FIRSTNAME, LASTNAME FROM EMPLOYEE")
row = ibm_db.fetch_tuple(stmt)
while row:
print(row[0], row[1], row[2])
row = ibm_db.fetch_tuple(stmt)
ibm_db.free_result(stmt)
取结果有三种方式,要分清使用场景。fetch_tuple返回按位置索引的元组,适合明确知道列顺序的场合;fetch_assoc返回字典形式,用列名取值,代码可读性更好;fetchboth则两者都支持但内存开销更大。无论用哪种,取完数据后调用free_result释放语句资源是个好习惯,长时间运行的脚本不释放容易积累内存问题。
对于带参数的SQL,一定要用预处理方式,不要手工拼接字符串,否则既有SQL注入风险,还会因为引号转义问题报错。正确写法是用prepare加占位符?:
sql = "SELECT * FROM EMPLOYEE WHERE DEPT = ? AND SALARY > ?"
stmt = ibm_db.prepare(conn, sql)
ibm_db.bind_param(stmt, 1, "D11")
ibm_db.bind_param(stmt, 2, 40000)
ibm_db.execute(stmt)
row = ibm_db.fetch_assoc(stmt)
while row:
print(row["EMPNO"], row["SALARY"])
row = ibm_db.fetch_assoc(stmt)
ibm_db.free_result(stmt)
四、增删改、事务与错误处理
执行INSERT、UPDATE、DELETE同样用上述两种方式,执行后可以通过ibm_db.num_rows()拿到受影响的行数。DB2默认是自动提交的,也就是说每条语句执行完立即生效。但实际业务中经常需要把多条写操作放在一个事务里,要么全成功要么全回滚,这时要关闭自动提交:
# option参数传0表示关闭自动提交
conn = ibm_db.connect(conn_str, "db2inst1", "password", "", 0)
try:
ibm_db.exec_immediate(conn, "UPDATE ACCOUNT SET BALANCE = BALANCE - 100 WHERE ID = 1")
ibm_db.exec_immediate(conn, "UPDATE ACCOUNT SET BALANCE = BALANCE + 100 WHERE ID = 2")
ibm_db.commit(conn) # 提交事务
except Exception as e:
ibm_db.rollback(conn) # 出错回滚
print("事务回滚:", e)
错误处理方面,建议把数据库操作包在try块里,在except中用ibm_db.stmt_error()获取SQLSTATE和错误描述。DB2的SQLSTATE前两位有固定含义,比如23开头是约束冲突,42开头是语法或对象不存在,掌握这些能加快排错速度。
最后提一下与pandas的配合。ibm_db官方提供了ibm_db_dbi子模块,它实现了Python标准的DB-API 2.0接口,用法和sqlite3、pymysql非常相似,还能直接配合pd.read_sql把查询结果变成DataFrame,做数据分析时体验会好很多。如果只是简单查询和写入,用原生ibm_db接口就够;如果要和数据处理工具链打通,切换到ibm_db_dgi会更顺手。用完记得调用ibm_db.close(conn)关闭连接,避免连接数占满。