python连接数据库

python连接MYSQL、postgres、oracle等的基本操作

python连接mysql

MySQLdb

MySQLdb又叫MySQL-python ,是 Python 连接 MySQL 的一个驱动,很多框架都也是基于此库进行开发,只支持 Python2.x ,而且安装的时候有很多前置条件,因为它是基于C开发的库,在 Windows 平台安装非常不友好,经常出现失败的情况,不推荐使用,取代的是它的衍生版本。

Mysqlclient

MySQLdb的 Fork 版本,完全兼容 MySQLdb,同时支持 Python3.x,是 Django ORM的依赖工具,如果你想使用原生 SQL 来操作数据库,那么推荐此驱动。Mysqlclient是一个C扩展模块,编译安装可能会导致报各种错误。

安装:pip install mysqlclient

如果出错,可以查看这个文档 https://blog.csdn.net/cn_1937/article/details/81533544

python 复制代码
import MySQLdb
# 注意 这里需要额外导入, 不然会报module 'MySQLdb' has no attribute 'cursors'的错误
import MySQLdb.cursors as cors
 
# 打开数据库连接 
db = MySQLdb.connect("localhost", "testuser", "test123", "TESTDB", charset='utf8',
                    cursorclass=cors.DictCursor) 
# 使用cursor()方法获取操作游标  
cursor = db.cursor() 
# SQL 插入语句 
sql="insert into EMPLOYEE values(%s,%s,%s,%s)" 
try: 
   # 执行sql语句 
   cursor.executemany(sql,[('Smith','Tom',15,'M',1500),('Mac', 'Mohan', 20, 'M', 2000)]) 
   # 提交到数据库执行 
   db.commit() 
except: 
   # Rollback in case there is any error 
   db.rollback() 
# 关闭数据库连接 
db.close() 

pymysql包

首先需要安装:pip install pymysql

python 复制代码
import pymysql

db = pymysql.connect(host='localhost', user='root', password='mysql',  #连接到数据库需要指定的最少信息
                     db = 'demo', database='demo', #指定选择的数据库,任选一个都可,前面是简写
                     passwd='mysql', #密码也可以用passwd简写形式
                     autocommit=True, #设置修改自动提交到数据库
                     auth_plugin_map='mysql_native_password') #设置身份认证,8.0版本之后建议加上
cursor = db.cursor() #创建一个指针,之后基本所有的操作都是使用指针来实现
cursor.execute('show databases;') #执行SQL语句
db.commit() #将修改提交到数据库------如果连接时参数autocommit设置为false要加上
cursor.fetchall() #获取上一条SQL语句的执行结果,如查询结果等
cursor.fetchone() #获取执行结果的一行
db.close() #关闭数据库

常用的代码就是上面这几行,所以主要还是在使用SQL语句来实现功能。其中主要有两个注意事项:

  • autocommit参数:这个如果不设置的话,默认为false,那么使用execute函数执行SQL语句时就有数据库没有修改的风险,所以建议加上。
  • auth_plugin_map参数:这个也是一个不容易发现的bug,根据StackOverflow上的介绍,在8.0版本之后的MySQL
    server,加上了一个身份验证的东西,和原来的不一样,如果不加上这个参数,可能会出现重启电脑,虽然服务在运行但是无法通过程序连接到数据库。所以保险起见,还是加上这个比较合适。
python 复制代码
import pymysql

try:
    db = pymysql.connect(host='localhost', user='root', passwd='666666', port=3306, db='Mysql8')
    print('连接成功!')
except:
    print('something wrong!')
cursor = db.cursor()
cursor.execute("DROP TABLE IF EXISTS EMPLOYEE")
sql = """CREATE TABLE EMPLOYEE (
         FIRST_NAME  CHAR(20) NOT NULL,
         LAST_NAME  CHAR(20),
         AGE INT,  
         SEX CHAR(1),
         INCOME FLOAT )"""

cursor.execute(sql)
print('建表成功!')
db.close()

获取操作数据库的异常

在操作数据库时,为了排除异常情况,往往会加上try ... except ...

python 复制代码
try:
	c = cursor.execute(sql) #指针执行SQL语句
except Exception as e:
	self.logger.error(f"The SQL code Execution ERROR: "+str(e))
	return -1

这个句式就能捕捉到sql语句执行时的错误,debug更加方便。

多线程访问数据库 dbutils

当主程序是多线程同时在执行时,且每个线程都需要操作数据,如果只用pymysql实现,相当于一个连接得要一直开着,这样据说运行久了会出问题。因此可以采用dbutils这个第三方模块来实现数据库多连接。

这个第三方模块的原理就是构造一个数据库的连接池,如果有需要连接就直接去池中申请一个连接,然后使用完再释放。

使用前先安装:pip install dbutils,调用方式如下所示

python 复制代码
from dbutils.pooled_db import PooledDB 
创建连接池

PooledDB 基本参数:

  • mincached : 最少的空闲连接数,如果空闲连接数小于这个数,Pool自动创建新连接;
  • maxcached : 最大的空闲连接数,如果空闲连接数大于这个数,Pool则关闭空闲连接;
  • maxconnections : 最大的连接数;
  • blocking : 当连接数达到最大的连接数时,在请求连接的时候,如果这个值是True,请求连接的程序会一直等待,直到当前连接数小于最- 连接数,如果这个值是False,会报错;
python 复制代码
def mysql_connection():
    maxconnections = 15  # 最大连接数
    pool = PooledDB(
        pymysql,
        maxconnections,
        host='localhost',
        user='root',
        port=3306,
        passwd='123456',
        db='test_DB',
        use_unicode=True)
    return pool
# use
>> pool = mysql_connection()
>> con = pool.connection()
python 复制代码
import pymysql
from DBUtils.PooledDB import PooledDB
import numpy as np


class MysqlPool():
    config = {
        'creator': pymysql,
        'host': 'localhost',
        'port': 3306,
        'user': 'root',
        'password': 'root',
        'db': 'xiaogenggou',
        'charset': 'utf8',
        'maxconnections': 70,  # 连接池最大连接数量
        'cursorclass': pymysql.cursors.DictCursor
    }
    pool = PooledDB(**config)

    def __enter__(self):
        self.conn = MysqlPool.pool.connection()
        self.cursor = self.conn.cursor()
        return self

    def __exit__(self, type, value, trace):
        self.cursor.close()
        self.conn.close()


# 执行函数
def execute(database_commands, s_value=None, i=0):
    """

    :param database_commands: 数据库的执行语句
    :param s_value: %s代表的变量名称
    :param i: 执行判断符,当i为1时执行状态判断 ,默认值为0
    """
    # 错误捕获,并报错
    try:
        with MysqlPool() as db:
            # 执行操作命令 database_commands:数据库的查询语句 s_value:当查询语句出现%s时%s对应的值,默认为None
            db.cursor.execute(database_commands, s_value)
            # 向数据库提交命令
            db.conn.commit()
            # 当执行查询操作时打印并返回查询的数据
            if "select" in database_commands and i == 0:
                # 打印查询的全部数据,fetchall()的返回值为list格式的字典集
                print(db.cursor.fetchall())
                # 返回查询的全部数据
                return db.cursor.fetchall()
            elif i == 1:
                return db.cursor.fetchall()
    except Exception as e:
        print("恭喜你,有错,又可以改bug了,开心吗")


# 创建表的函数
def test_create():
    # 编写创建主表main_test的语句
    sql_create_test = "create table test" \
                      "(user_id int auto_increment primary key," \
                      "username varchar(11)," \
                      "sex nvarchar(1)," \
                      "age int(3)," \
                      "state int(1) DEFAULT 1 )"
    # 创建表test
    execute(sql_create_test)


# test_create()


# 删除表
def test_table_drop():
    # 编写删除表的语句
    sql_test_drop = "drop table test"
    # 删除表
    execute(sql_test_drop)


# test_table_drop()


# 向数据表内插入数据
def test_insert(username, sex, age, table="test"):
    """

    :param username: 用户名称
    :param sex: 用户性别
    :param age: 用户年龄
    :param table: 数据表的名称
    """
    # 编写插入语句,%s表示元素的占位符
    sql_insert = "insert into " + table + " (username,sex,age) values(%s,%s,%s)"
    # 表示从左到右每个占位符所表示的元素的内容
    value = (username, sex, age)
    # 插入数据
    execute(sql_insert, value)


'''
for i in range(10):
    value_username = "test" + str(i + 1)
    a = np.random.permutation(2)
    if a[1] == 1:
        value_sex = "男"
    else:
        value_sex = "女"
    value_age = int(20 + a[0])
    test_insert(value_username, value_sex, value_age)
    '''


# 删除user_id对应的元组(用state值为0代替)
def test_delete(user_id):
    # 判断user_id对应的元组的状态
    if state_judgement(user_id) == 0:
        print("该行已被删除")
    else:
        # 编写删除语句
        sql_delete = "update test set state = %s where user_id = %s"
        # 将state的值改为0,代表删除
        value = (0, user_id)
        # 执行删除操作
        execute(sql_delete, value)


'''
for i in range(1, 11):
    u_id = i
    a = np.random.permutation(2)
    print(a[1])
    if a[1] == 0:
        test_delete(u_id)
'''


# 进行元组状态的判断,1表示存在,0表示已被删除
def state_judgement(user_id):
    """

    :param user_id: 判断状态的元组的主键(id)
    :return: 状态判断值
    """
    # 当user_id超出范围时报错
    try:
        # 编写判断的语句,%s表示元素的占位符
        sql_state_judgement = "select state from test where user_id = %s"
        # 表示从左到右每个占位符所表示的元素的内容
        value = user_id
        # 存储返回的list
        ls = execute(sql_state_judgement, value, 1)
        # 返回代表状态的0或1
        return ls[0]["state"]
    except Exception as e:
        print("亲,错了呢")


'''
for i in range(1, 11):
    print(state_judgement(i))
'''


# 更改表test的数据
def test_update(event_attribute, new_value, user_id):
    """

    :param event_attribute: 要更改的属性名
    :param new_value: 更改后的属性内容
    :param user_id: 更改属性的元组的主键(id)
    """
    # 判断user_id对应的元组的状态
    if state_judgement(user_id) == 0 and event_attribute != "state":
        print("该行已被删除")
    else:
        # 编写更新语句,%s表示元素的占位符
        sql_update = "update test set " + event_attribute + " = %s where user_id = %s "
        # 表示从左到右每个占位符所表示的元素的内容
        value = (new_value, user_id)
        # 更改数据
        execute(sql_update, value)


'''
for i in range(1, 11):
    test_update("age", 40 + i, i)
'''


# 查询表test中某一元组的所有的数据
def test_query_all(user_id=None):
    """

    :param user_id: 更改属性的元组的主键(id)
    """
    # 当未指定user_id时查询全部元组的数据
    if user_id is None:
        # 编写查询语句
        sql_query_all = "select * from test where state = 1"
        # 执行查询
        execute(sql_query_all)
    else:
        # 判断user_id对应的元组的状态
        if state_judgement(user_id) == 0:
            print("该行已被删除")
        else:
            # 编写查询根据user_id确定的某一元组的全部数据
            sql_query_all = "select * from test where user_id = %s"
            # 表示从左到右每个占位符所表示的元素的内容
            value = user_id
            # 执行查询
            execute(sql_query_all, value)


# test_query_all()


# 查询副表test中某一元组的某一属性的数据
def test_query(event_attribute, user_id=None):
    """

    :param event_attribute:查询的属性的名称
    :param user_id: 更改属性的元组的主键(id)
    """
    # 当未指定user_id时查询全部元组的数据
    if user_id is None:
        # 编写查询全部元组某一属性的语句
        sql_query = "select " + event_attribute + " from test where state = 1"
        # 执行查询
        execute(sql_query)
    else:
        # 判断user_id对应的元组的状态
        if state_judgement(user_id) == 0:
            print("该行已被删除")
        # 编写查询查询根据user_id确定的某一元组的某一属性的数据
        else:
            sql_query = "select " + event_attribute + " from test where user_id = %s"
            # 表示从左到右每个占位符所表示的元素的内容
            value = user_id
            # 执行查询
            execute(sql_query, value)

# test_query("username")

总结

pymysql 和 mysqlclient 目前是python连接mysql 的主流方式。mysqlclient 速度比pymysql 更快;pymysql更加简单易使用。

python连接oracle

cx_Oracle

安装:cmd终端,执行 pip install cx_Oracle

依赖:oracle客户端,如果本地没有oracle客户的,就需要获取一个。Oracle Instant Client Downloads

解压后就是一个文件夹(instantclient_21_6),免安装。直接放到一个目录,例如:就直接放到C盘:C:\instantclient_21_6,然后把本地oracle客户端目录更新到环境变量;

python 复制代码
import cx_Oracle #导入oracle包
connection =cx_Oracle.connect('aaaaa', 'bbb77', 'xx.xx.xx.xx:1521/SITE') # 数据库连接的用户名、密码、IP、端口和数据库名称。
cursor = connection.cursor() #数据库指针
cursor.execute("""SELECT first_name, last_name FROM employees 
WHERE department_id = :did AND employee_id > :eid""",did = 50,eid = 190)
#或者
sql="select a.* from hs_d.prce a where a.prod_code ='DB3045'" #定义要执行的sql语句
cursor.execute(sql) #执行sql语句
row = cursor.fetchall() #查询回来多条语句
print(row[0]) #打印查询的第一行结果 ---这里如果是测试的话,还可以assert。
print(row[0][2]) #打印结果是:DB3045
assert row[0][2]=="DB3045" #断言返回结果第一行的地3个字段值是"DB3045"

oracledb

python 复制代码
import oracledb
import getpass

userpwd = getpass.getpass("Enter password: ")

connection = oracledb.connect(user="hr", password=userpwd,
                              dsn="dbhost.example.com/orclpdb")
# 其他功能代码

# 关闭连接
connection.close()

或者可以使用以下方法

python 复制代码
username="hr"
userpwd = os.environ.get("PYTHON_PASSWORD")
host = "localhost"
port = 1521
service_name = "orclpdb"

dsn = f'{username}/{userpwd}@{port}:{host}/{service_name}'
connection = oracledb.connect(dsn)

# 其他功能代码

# 关闭连接
connection.close()

使用连接池的方法

python 复制代码
# 初始化连接
pool = oracledb.create_pool(user="hr", password=userpwd, dsn="dbhost.example.com/orclpdb",
                            min=2, max=5, increment=1)
# Acquire 连接到池
connection = pool.acquire()
# 使用连接池
with connection.cursor() as cursor:
    for result in cursor.execute("select * from mytab"):
        print(result)
# 释放连接池
pool.release(connection)
# 关闭连接池
pool.close()

python连接postgres

psycopg2

python 复制代码
# -*- coding: utf-8 -*-
import psycopg2
# 获得连接
conn = psycopg2.connect(database="python", user="postgres", password="123456", host="127.0.0.1", port="5432")
# 获得游标对象,一个游标对象可以对数据库进行执行操作
cursor = conn.cursor()
# sql语句 建表
sql ="""SELECT * FROM student;"""
# 执行语句
cursor.execute(sql)
# 抓取
rows = cursor.fetchall()
print(rows)
# 事物提交
conn.commit()
# 关闭数据库连接
cursor.close()
conn.close()
相关推荐
Open-AI2 分钟前
Python如何判断一个数是几位数
python
IT技术分享社区3 分钟前
C#实战:使用腾讯云识别服务轻松提取火车票信息
开发语言·c#·云计算·腾讯云·共识算法
桀桀桀桀桀桀4 分钟前
数据库中的用户管理和权限管理
数据库·mysql
极客代码6 分钟前
【Python TensorFlow】入门到精通
开发语言·人工智能·python·深度学习·tensorflow
义小深8 分钟前
TensorFlow|咖啡豆识别
人工智能·python·tensorflow
疯一样的码农12 分钟前
Python 正则表达式(RegEx)
开发语言·python·正则表达式
&岁月不待人&34 分钟前
Kotlin by lazy和lateinit的使用及区别
android·开发语言·kotlin
StayInLove38 分钟前
G1垃圾回收器日志详解
java·开发语言
无尽的大道1 小时前
Java字符串深度解析:String的实现、常量池与性能优化
java·开发语言·性能优化
爱吃生蚝的于勒1 小时前
深入学习指针(5)!!!!!!!!!!!!!!!
c语言·开发语言·数据结构·学习·计算机网络·算法