On Dec 15, 2010, at 5:14 PM, Russell Warren wrote: > Why does Session.merge only look at primary key and not all unique > keys?
Well the theory of operation regarding merge() is based on that of the identity map, which is linked to object/row identity. Consider that it also cascades along relationship paths. It would be a difficult operation to define if it had to choose among multiple ways to determine the "identity" of each object along the cascade chain. > > Leaving aside some irritating DBMS restrictions on PKs and some > automatic indexing that tends to happen, the PK is not fundamentally > different than other unique keys It is fundamentally different in that a database row within a reasonable schema has only one "identity". The usage of surrogate primary keys perhaps pollutes this concept to some degree. > and I don't see why SQLA > distinguishes them from an integrity/relationship perspective. SQLA at the ORM level doesn't really know about any other attributes being "unique" and it would incur excessive complexity to implement that as built-in, where "complexity" here means the bookkeeping associated with storing, retrieving, and modifying items in the identity map would become a much more time consuming affair (for some recent insight into my epic battle with time consumption, see http://techspot.zzzeek.org/2010/12/12/a-tale-of-three-profiles/ ). It also would refer to all those unintended side effects of doing such, such as two objects that are swapping attribute values, etc. The database does a perfectly good job of maintaining UNIQUE constraints so we leave that whole affair out of the Python side. > In > databases where it is already frustrating that they have funky PK > restrictions it is tough to make merge() work the way it seems it > should. For example, in the code below this post, Sqlite requires the > autoincrementing field to be the PK, and you can't composite it with > another field... with these restrictions I can't get merge() to work > the way "it should". > I was looking for a clean way in SQLAlchemy to do an "insert if not > exists" pattern, and merge() looked perfect, but I can't make it work > at the moment. The generic "insert if not exists" pattern that is extensible to whatever attributes you want is at: http://www.sqlalchemy.org/trac/wiki/UsageRecipes/UniqueObject . > > I'm also aware that in the sample code the 'name' field should really > just be the "primary" key and the problem goes away, mmm the consensus I've noted for the past several years, as well as with my own experiences, is that we're better off with surrogate primary keys. SQLA does support natural primary keys fully, and note that foreign keys which reference natural primary keys are entirely valid. Mutation of these keys is supported naturally through ON UPDATE CASCADE and ON DELETE CASCADE. But I find myself usually never using them (well actually I did a yearlong project a year ago that was all on natural PKs and it was really not worth it). -- You received this message because you are subscribed to the Google Groups "sqlalchemy" group. To post to this group, send email to sqlalch...@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.