 <p>If you can wait a month Postgres 9.5 will be out and has Row Security. Oracle has it now if you have ten million bucks kicking around. </p> <p>For now, or in other dbs, you can mimic row security:</p> <ol> <li><p>Each protected table gets an "owner" column. By default only the owner can select, update, or delete that row.</p></li> <li><p>Each "child" table also has an owner column, with a cascading foreign key to the parent table. So if change parent.owner, then this changes all children.owners as well</p></li> <li><p>Use updateable CHECK OPTION views to enforce security.</p></li> <li><p>You need to set current_user from your application. <a href="https://stackoverflow.com/questions/2998597/switch-role-after-connecting-to-database/19602050#19602050">Here's how</a> for pg + spring</p></li> </ol> <p>In Postgres:</p> <pre><code>create schema protected; create table protected.foo ( foo_id int primary key, bar text, owner name not null default_current user ); create table protected.foo_children ( foo_child_id int primary key, foo_id int not null references foo(food_id), owner name not null default current_user references foo(owner) on update cascade ); </code></pre> <p>Now some CHECK OPTION views - use security_barrier if postgres:</p> <pre><code>create view public.foo with (security_barrier) as select * from protected.foo where owner = current_user WITH CHECK OPTION; create view public.foo_children with (security_barrier) as select * from protected.foo_children where owner = current_user WITH CHECK OPTION; grant delete, insert, select, update on public.foo to some_users; grant delete, insert, select, update on public.foo_children to some_users; </code></pre> <p>For sharing, you need to add some more tables. The important thing is that you can index the right columns so that you don't kill performance:</p> <pre><code>create schema acl; create table acl.foo ( foo_id int primary key references protected.foo(foo_id), grantee name not null, privilege char(1) not null ); </code></pre> <p>Update your views:</p> <pre><code>create or update view public.foo with (security_barrier) as select * from protected.foo where owner = current_user or exists ( select 1 from acl.foo where privilege in ('s','u','d') and grantee = current_user) ); --add update trigger that checks for update privilege --add delete trigger that checks for delete privilege </code></pre>