@melpomene
First: If you occasionally prod the SQL connection (say, once per minute), then MySQL itself will not time out the connection like it wants to. You would absolutely use @query, though I have never in my life seen sql() hang the game. This doesn't mean that it can't, but that I personally am willing to risk it. I'm a rebel.
Secondly: You say using SQL properly "too much work for what I want to do" and yet you're trying to create a cross-object data storage system. We all know the real reason is "why not?".
Thirdly: These are the reference shortcut that solves the 'who is calling this code?' issue:
%# - calling dbref
%@ - referencing dbref
So if you want someone to be able to run a +command and have that object have permissions, you'd do something like: gte( bittype( %@ ), 5 )
.
Fourthly: For WoD I created something called 'stat path' that pretty much uses the attribute name as the index. I don't use lookup id technique because I want to code for non-coders too, so I have:
&_attribute.strength: 3
&_merit.language_(french): 1
It is not the best technique, but I can kill a lot of birds with one stone, especially when I'm doing something such as deciding to search merits before gifts for partial name-matching 'sim'.
I don't think there's a wrong way to do it as long as your structure is normalized and consistent, but I wanted to say you aren't alone in your thinking.