我正在编写一个脚本来同步Adwords帐户和Sqlalchemy的本地数据库。 我正在关注Adwords API的对象层次结构,因此我的第一个表格是“广告系列”,第二个表格是“广告组”
这是我如何定义两者:
class Campaign(Base):
__tablename__ = 'aw_campaigns'
id = Column(Integer, primary_key=True)
name = Column(String(99))
impressions = Column(Integer)
serving_status = Column(String(99))
start_date = Column(String(99))
status = Column(String(99))
def __init__(self, id, name, impressions, serving_status, start_date, status):
self.id = id
self.name = name
self.impressions = impressions
self.serving_status = serving_status
self.start_date = start_date
self.status = status
class Adgroup(Base):
__tablename__ = 'aw_adgroups'
id = Column(Integer, primary_key=True) # , primary_key=True
name = Column(String(99))
camp_id = Column(Integer, ForeignKey('aw_campaigns.id')) # , ForeignKey('aw_campaigns.id')
camp_name = Column(String(99))
ctr = Column(Float)
cost = Column(Float)
impressions = Column(Integer)
clicks = Column(Integer)
status = Column(String(99))
def __init__(self, id, name, camp_id, camp_name, ctr, cost, impressions, clicks, status):
self.id = id
self.name = name
self.camp_id = camp_id
self.camp_name = camp_name
self.ctr = ctr
self.cost = cost
self.impressions = impressions
self.clicks = clicks
self.status = status
我查询API,然后为Adgroup表中的行构建对象列表:
adgr_query = 'SELECT CampaignId, CampaignName, Clicks, Cost, Impressions, Ctr, Id, KeywordMaxCpc, Name, Settings, Status'
adgr_page = ad_group_serv.Query(adgr_query)[0]['entries']
adgr_ins = [Adgroup(i['id'],
i['name'],
i['campaignId'],
i['campaignName'],
i['stats']['ctr'],
i['stats']['cost']['microAmount'],
i['stats']['impressions'],
i['stats']['clicks'],
i['status']) for i in adgr_page if int(i['id']) not in adgr_exist]
但是当我提交时,我收到错误:
(IntegrityError) (1062, "Duplicate entry '2147483647' for key 'PRIMARY'")
问题在于我不知道该值来自何处。
'2147483647' in [i['id'] for i in adgr_page]
>>> False
'2147483647' in str(adgr_page)
>>> False
我真的被困在这上面了。
答案 0 :(得分:1)
看起来你在某处有整数溢出。
症状:2147483647是2 ** 31-1 - 表示32位用于存储该号码。
AdGroup.Id字段的类型为xsd:long,长度为64位。
Python本身对整数值的大小没有限制,但数据库可能有这样的限制。
简短解决方案:
尝试使用BigInteger sqltype类型id = Column(BigInteger, primary_key=True)
,同样使用来自AdWords API的camp_id和其他xsd:long值。 SQLAlchemy有可能选择数据库特定的大整数列类型。或者您可以使用String(64)作为id的类型。但在这种情况下,您需要额外的步骤来生成主键。
您对AdWords API的查询返回了多少条目?有超过2 ** 32条记录吗?我对此表示怀疑 - 您的数据库不太可能处理~4200万条记录。
解决方案2 - 长期
虽然我建议不要信任外部源的主键完整性,并依赖数据库使用自动增量生成主键,并依赖SQLAlchemy根据数据库生成的主键处理外键密钥:
class Adgroup(Base):
__tablename__ = 'aw_adgroups'
id = Column(Integer, Sequence('adgroup_seq'), primary_key=True) # , primary_key=True
adGroupId = Column(String(64))
campaignId = Column(Integer,ForeignKey('aw_campaigns.id'))
campaign = relationship("Campaign", backref = "adgroup")
...
class Campaign(Base):
__tablename__ = 'aw_campaigns'
id = Column(Integer, Sequence('adgroup_seq'), primary_key=True)
campaignId = Column(String(64))
...
看起来您可能需要通过campaignId和adGroupId进行查找 - 因此您可以在其上添加索引。
然后,您可以创建广告系列和广告组对象,只需添加它们之间的关系即可。代码将取决于您想要使用的关系类型 - 一对多或多对多。查看sqlalchemy relationship manual了解详情。
ag = AdGroup(**kwargs)
camp = Campaign(**kwargs)
ag.campaign = camp
session.add(ag)