Sqlalchemy没有主键(key) 向表中添加数据
sqlalchemy 如果写入操作是必须要有主键才可以操作的,我讲一下如果表中没有主键怎么绕过,保存数据。
一、重写sqlalchemy常用方法
# Engine
engine_oarcle = create_engine("oracle+cx_oracle://{}:{}@{}/{}".format(
'user',
'pass',
'127.0.0.1',
'orcl'), coerce_to_unicode=True, max_overflow=100, pool_size=100, pool_recycle=3600)
#自己写的一个数据类
class Connect(object):
def __init__(self, engine):
self.engine = engine
self.session = None
self.connect_session()
def connect_session(self):
try:
self.engine.connect()
except Exception:
raise Exception("数据库连接失败")
dbSession = orm.sessionmaker(bind=self.engine)
self.session = dbSession()
# 我重写了一下add_all方法,在批量提交的时候,可以分批讲行提交
def add_all(self, records):
'''
指添加记录
:param records:
:return:
'''
if len(records) == 0:
return
post_count = 10000
record_count = len(records)
post = math.ceil(record_count / post_count)
for i in range(post):
begin_index = i * post_count
if i + 2 <= post:
end_index = (i + 1) * post_count
else:
end_index = record_count
# TODO 暂时先这么处理 解决不能重复提交的问题
self.session.identity_map._dict = {}
self.session.add_all(records[begin_index:end_index])
self.save()
def add(self, record):
self.session.add(record)
def save(self):
try:
self.session.commit()
except Exception as e:
self.session.rollback()
print(e)
# 执行sql语句
def execute_ext(self, sql):
return self.session.execute(sql)
# 返加是数据 []
def execute(self, sql):
try:
return self.session.execute(sql).fetchall()
except Exception as e:
self.session.rollback()
# 返回一条数据元组()
def oneexecute(self, sql):
try:
return self.session.execute(sql).first()
except Exception as e:
self.session.rollback()
def query(self, query):
return self.session.query(query)
def close(self):
self.session.close()
新建表:在oracle中创建数据表(table1)
- 大家注意表中并没有给定主键
create table table1
(
name1 VARCHAR2(50),
name2 VARCHAR2(50),
name3 VARCHAR2(50)
)
生成models
- 把
primary_key=True
赋给表中任一字段,我这里给的是name1
这一步是必须要做的,name1这个字段不能为空值,如果办空,就不能保存数据。
from sqlalchemy import Column, DateTime, Numeric, String
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
metadata = Base.metadata
class Table1(Base):
__tablename__ = 'Table1'
# 把 primary_key=True 给任意一个字段
name1 = Column(String(50), primary_key=True)
name2 = Column(String(50))
name3 = Column(String(50))
如果没有主键的情况下,如果向表中添加数据,如果不是分批提交,那么基本上是没有问题,如果向我上面代码中要分批提交数据,如果第二批数据中被设为key字段有重复值,导致数据提交不上去。
我们可以在第一次提交之前加上 self.session.identity_map._dict = {}
这句代码就可以成功提交
def add_all(self, records):
'''
指添加记录
:param records:
:return:
'''
if len(records) == 0:
return
post_count = 10000
record_count = len(records)
post = math.ceil(record_count / post_count)
for i in range(post):
begin_index = i * post_count
if i + 2 <= post:
end_index = (i + 1) * post_count
else:
end_index = record_count
# TODO 暂时先这么处理 解决不能重复提交的问题
self.session.identity_map._dict = {}
self.session.add_all(records[begin_index:end_index])
self.save()
测试
dbsession =Connect(engine_oarcle)
for i in range(10000):
record = Table1()
record.name1 = "Name_" + str(i)
record.name2 = "Name2_" + str(i)
record.name3 = "Name3_" + str(i)
records.append(record)
for i in range(10000):
record = Table1()
record.name1 = "Name_" + str(i)
record.name2 = "Name2_" + str(i)
record.name3 = "Name3_" + str(i)
records.append(record)
for i in range(10000):
record = Table1()
record.name1 = "Name_" + str(i)
record.name2 = "Name2_" + str(i)
record.name3 = "Name3_" + str(i)
records.append(record)
dbsession.add_all(records)
如果没有加 self.session.identity_map._dict = {}
会报如下错误
New instance <Table1 at 0x18c8771bda0> with identity key (<class '__main__.Table1'>, ('Name_0',), None) conflicts with persistent instance <Table1 at 0x18c846b5a58>
New instance <Table1 at 0x18c8826f278> with identity key (<class '__main__.Table1'>, ('Name_0',), None) conflicts with persistent instance <Table1 at 0x18c846b5a58>