1

我正在编写一个脚本来同步 Adwords 帐户和使用 Sqlalchemy 的本地数据库。我遵循 Adwords API 的对象层次结构,所以我的第一个表是“campaigns”,第二个是“adgroups”

这是我如何定义两者:

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

我真的坚持这一点。

4

1 回答 1

1

看起来你在某处有整数溢出。

症状:2147483647 是 2**31-1 - 表示使用 32 位来存储数字。

AdGroup.Id 字段的类型为xsd:long,长度为 64 位。

Python 本身对整数值的大小没有限制,但数据库可能有这样的限制。

简短的解决方案:

尝试使用BigInteger sqltype 类型id = Column(BigInteger, primary_key=True),camp_id 和来自 AdWords API 的其余 xsd:long 值相同。SQLAlchemy 有可能会选择数据库特定的大整数列类型。或者您可以使用 String(64) 作为 id 的类型。但在这种情况下,您需要额外的步骤来生成主键。

您对 AdWords API 的查询返回了多少条目?是否有超过 2**32 条记录?我对此表示怀疑——您的数据库不太可能处理约 42 亿条记录。

解决方案 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 进行查找 - 这样您就可以在它们上添加索引。

然后您创建您的 Campaign 和 AdGroup 对象并添加它们之间的关系。该代码将取决于您要使用的关系类型 - 一对多或多对多。查看sqlalchemy 关系手册以获取更多详细信息。

ag = AdGroup(**kwargs)
camp = Campaign(**kwargs)
ag.campaign = camp
session.add(ag)
于 2013-02-07T19:41:30.253 回答