Now I'm looking at "what database system to use?" The biggest problem I've experienced, in dealing with ORM, is: how do you get an entire object hierarchy with a single query? Examples are "an area, all of the map data for this area, all of the NPCs on the map for this area, all of the items the NPCs on the map for this area are holding" or "a character, all of the stuff the character is holding, all of the stuff contained in the stuff the character is holding." If you store the top-level objects as binary blobs and unpack in your game code, this problem is solved.
Otherwise, you're in the classic problem of recursively descending a tree in a query (this is discussed in depth in The Art of SQL, and Vadim Tropashko has also written a broad view of the subject with his own proposal). The latest versions of the SQL standard offer a way to do this ("recursive with"), and some RDBMS's implement it, but it's never very fast and it always looks a little ugly1.
Another problem frequently faced with common object/relational maps is figuring out which tables the data is in - this is particularly a problem when your object model uses inheritance, so you've got classes that share some data, but don't share other data. Again, this problem is largely solved when storing objects as binary blobs. You can a) put all the information for all possible objects in a particular inheritance hierarchy in a single table, or b) put all the information for each class in its own table (often repeating columns across tables that share a common ancestor), or c) split it up so that each class's table has just its new properties, plus a pointer to its parent class's table. All of these approaches have problems.
Picking the right database system involves picking what solutions to use for these problems.
SQL Server is a possibility, we have fairly recent experience with it and it can definitely work. It also supports recursive with syntax, so that you can recursively descend a tree in a single query. SQL Server also has the advantage that there are a lot of very good pre-existing tools to remotely manage a SQL Server database above and beyond what Windows itself offers for remote management. So, managing SQL Server machines is not as bad as other kinds of Windows-based servers, but there are still gaps.
Versant is interesting because of how completely it solves object/relational mappings and recursive tree traversal, but on the other hand ad-hoc queries against a Versant database are... less than optimal. It involves writing quite a bit more code, and quite a bit less work is done in the database kernel - so it has to be done after retrieving potentially enormous result sets. In a lot of ways, Versant has many of the same pros and cons as storing binary blobs in the database, and in my mind represents the state of the art in binary blobs.
PostgreSQL is interesting because it provides table inheritance out of the box; I'm still playing around with ways of turning that into a solid implementation of approach c), but I'm not there yet. Recursive with is currently only proposed for PostgreSQL 8.4, although there are community-supplied stored procedures to implement (opaque to the planner/optimizer) Oracle-style "connect by."
I haven't looked past those three yet. Oracle is used by some in the game industry, but I'm a little wary of their cost and baseline performance. MySQL... I'll be frank, I haven't seriously considerid MySQL for any task in quite some time.
1. There's also the materialized path and nested set models of handling tree structures. Nested sets are horrendously expensive for any data change (many, many rows have to be updated when a leaf node is added to or removed from the tree). This is simply not acceptable for a tree structure such as a character with a frequently-changing inventory.
Materialized paths are less expensive than nested sets on updates (you only need to deal with sibling nodes), but still significantly more expensive than the adjacency model afforded by recursive with or connect by. I suspect that with a large enough number of separate trees (characters, maps, etc.) a materialized path will also start choking.


The only example queries you mention wanting to run is to find all the NPCs and objects in and area, and all of a player's object. Just to raise the specter of the Dread Pirate Denormalization, each of these can be easily addressed with an added column. But probably you have other queries you haven't mentioned.
Can you explain how you propose adding a single column to simplify the tree-traversal query? To be clear, this is not a two-level hierarchy: it's unknown at the start how deep the hierarchy is. For instance, a map might have NPCs littered about it, but each NPC might have quests to give, loot to drop, or they might be represented as characters with their own hierarchy of items and skills and so on.
Inheritance is the real impedance mismatch between OO and SQL. I don't have a nice solution to offer, except that I've become deeply suspicious of inheritance. On Walraven, a cutlass inherited from sword inherited from weapon inherited from object, and it was a bit silly tracking down bugs and data. I'm starting to think that mixins are a better idea, but it doesn't really help with the SQL.
I agree that inheritance is a real mismatch between OO and SQL, but I am not so deeply suspicious of it. Among other things, good debuggers take care of a lot of the trouble in tracking down problems across a class hierarchy. Inheritance is also not the only way to solve problems: containment, "has a" instead of "is a," solves some problems better (and some worse) than inheritance.
You like blobs a lot more than I do. I think I'll leave it at that :)
Storing object hierarchies as binary blobs is a solution to problems you don't have, and it costs things you can't give up. I'm not a fan of blobs, which is why I'm looking at other solutions... but I know that they can and do work if you can accept their constraints.
They do work, in that you can store data and retrieve data. I just don't like the tradeoffs involved (e.g. I'd rather forbid nesting containers beyond a certain depth rather than switch to a blob).
Incidentally, that is also not a concern on my current project, which gives me the ability to look at other (more database-aware) approaches.