'SQLAlchemy IntegrityError duplicate key violates unique-constraint

This problem has been doing my head in for far too long and I cannot find any solution in other questions.

In SQLAlchemy I am creating a schema (2 tables) which are linked by keys. When I INSERT data into the tables, I get a UNIQUE-CONSTRAINT error:

    (IntegrityError) ERROR:  duplicate key violates UNIQUE-CONSTRAINT e_data_pkey
    DETAIL:  KEY (id)=(2) already exists.
    'INSERT INTO e_data (id, iso3, year, value) VALUES (%(id)s, %(iso3)s, %(year)s, %(value)s)' 
  ({'iso3': 'ABW', 'id': 1, 'value': 5.5, 'year': 2009}, 
   {'iso3': 'ZZZ', **'id': 2,** 'value': 9.9, 'year': 1977}, 
   {'iso3': 'ZZY', **'id': 2**, 'value': 9.876, 'year': 1971})

Obviously, the class is allocating the same ID to each instance in the list.

Shouldn't the IDs be auto-generated by SQLAlchemy and why is this error occurring? I have adapted this example from other sources, so it should be easily implemented.

Does anyone see the problem? Here's the code I am using:

from sqlalchemy import *
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import relation, sessionmaker

Base = declarative_base()

class E_data(Base):
    __tablename__ = 'e_data'

    id = Column(Integer, ForeignKey('e_indicator.id'), primary_key=True) 
    iso3 = Column(String(3), nullable=False)
    year = Column(Integer)
    value = Column(FLOAT)

    eind = relation("E_indicator", backref='e_data', lazy=False)

    def __init__(self, iso3=None, year=None, value=None):
        self.iso3 = iso3
        self.year = year
        self.value = value
    def __repr__(self):
        return "E_Data (%r, %r, %r, %r)" % (self.iso3, self.year, self.value, self.eind)

class E_indicator(Base):
    __tablename__ = 'e_indicator'

    id = Column(Integer, primary_key=True)
    name = Column(String(50), nullable=False, unique=True)

    def __init__(self, name=None):
        self.name = name

    def __repr__(self):
        return "E_indicator (%r)" % (self.name)

engine = create_engine('postgresql://postgres:password@localhost/world')
Base.metadata.create_all(engine)

Session = sessionmaker(bind=engine)
session = Session()

#INSERT INTO DB
Session = sessionmaker(bind=engine)
session = Session()

m1 = E_data("ABW", 2009, 5.5)
m1.eind = E_indicator("GDP_TEST")

d2 = E_indicator("GDP THE OTHER WAY ROUND")
d2.e_data = [E_data("ZZZ", 1977, 9.9), E_data("ZZY", 1971, 9.876)]


#try:
session.add(m1)
session.add(d2)
session.commit()
#except:
    #session.rollback()

Thanks for any advice.



Solution 1:[1]

and sorry but both you suggestions did not solve my problem. The only way I could make it work to specify a primaryjoin condition like this:

eind = relation("E_indicator", backref='e_data', primaryjoin="E_indicator.id==E_data.id")

This solved the issue. I hope this will help someone.

Cheers, A

Solution 2:[2]

My problem was that I inserted 4 initial records when the app runs for the first time. Somehow Postgres has restarted the counter, I still do not know why, and after my 5th try and every future try it works.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Arne
Solution 2 elano7