04·Concept·10 min
Databases and row-level security
A relational database is a set of tables. Each table is a grid: columns describe one kind of thing (an order has a total, a status, a date), and each row is one instance of it.
Keys link tables
Every row has a primary key, usually an id, that nothing else shares. A foreign key is a column that holds another table's id: an order carries the id of the customer who placed it. That one number is how "show me this customer's orders" works, and why deleting a customer with orders is refused unless you say what happens to the orders.
Queries
Apps read and write through queries: find rows where the status is paid, insert a row, update one field, count. A query is built from parts, and the values (the email someone typed, the id in the URL) are sent separately from the query text. That separation is what stops a malicious value from turning into a command; it is called parameterization and it is the standard defense against SQL injection.
Row-level security
Access control usually lives in app code: "if the user is not the owner, do not show this." Row-level security (RLS) moves that rule into the database itself. A policy on the orders table can say "a session may read a row only if the row's customer id matches the session's user id." Then every query, from any page or script, is filtered by that policy. A bug in one page cannot leak another customer's rows, because the database never returns them.
RLS is about rows. Column-level rules (hide the cost price from customers) and table-level rules (only staff may read the payouts table) sit alongside it.
Where DontCode fits
Each project has its own isolated database schema; the users table is managed by the platform and protected. Public API queries are structured objects, never raw SQL, and every value is parameterized on the server. Schema changes go through migrations that are validated before they run and rolled back if they fail.
Check your understanding
1.What is a foreign key?
2.A page has a bug and asks for all orders instead of the current user's. With an RLS policy in place, what does the user see?
3.Why are query values sent separately from the query text?
4.Which query ignores RLS policies?