You may prefer to use session.merge() leaving the SELECT and the
subsequent decision to INSERT or UPDATE to SQLAlchemy (see
http://www.sqlalchemy.org/docs/05/session.html?highlight=merge#merging)

The main section of your example should look like this then:

---snip-----------------------
id = 55
val = random.choice(range(1000))
t = T(id, val)
session = Session()
session.merge(t)
session.commit()
---snip-----------------------


In case your table type forces you to use locks, I _think_ this
should be done as shown below (anyone correct me if I am wrong):

---snip-----------------------
id = 55
val = random.choice(range(1000))
t = T(id, val)
session = Session()
session.execute('LOCK TABLES t WRITE')
session.merge(t)
session.commit()
session.execute('UNLOCK TABLES')
---snip-----------------------


Jyotirmoy wrote:
> I want to know what is the best way to write code using sqlalchemy
> that given a value of the primary key inserts a record if no record
> with that key exists or updates the value of the other columns if the
> key already exists.
> 
> I wrote a naive version which get()s the value and add()s if the
> result is None. But the approach fails with many concurrent processes
> since the record may have been inserted between the get and add. I
> could catch the IntegrityError and retry, but if there are other
> processes deleting records as well then there is no guarantee that the
> loop would ever terminate.
> 
> Is there some approach to doing this operation which is guaranteed to
> succeed.
> 
> Here is my naive code:
> 
> from sqlalchemy import Integer,Column, create_engine
> from sqlalchemy.ext.declarative import declarative_base
> from sqlalchemy.orm import sessionmaker
> 
> from time import sleep
> import random
> 
> Base=declarative_base()
> engine=create_engine("mysql://nob...@localhost/concur",echo=True)
> Session = sessionmaker(bind=engine)
> 
> class T(Base):
>     __tablename__ = 't'
> 
>     i = Column(Integer,primary_key=True)
>     j = Column(Integer)
> 
>     def __init__(self,i,j):
>         self.i=i
>         self.j=j
> 
> id=55
> val=random.choice(range(1000))
> session=Session()
> t=session.query(T).get(id)
> sleep(10) #Create a race
> if t is None:
>     t=T(id,100)
>     session.add(t)
> else:
>     t.j=val
> 
> session.commit()


--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"sqlalchemy" group.
To post to this group, send email to sqlalchemy@googlegroups.com
To unsubscribe from this group, send email to 
sqlalchemy+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to