ALTER TABLE orders ENABLE ROW LEVEL SECURITY;CREATE POLICY tenant_isolation ON orders USING (tenant_id = current_setting('app.tenant_id')::BIGINT);GRANT SELECT, INSERT, UPDATE, DELETE ON orders TO app_role;
Feature
Detail
USING clause
Read filter
WITH CHECK
Write filter
FORCE ROW LEVEL SECURITY
Apply to table owner too
Bypass
BYPASSRLS role attribute
4. Implementing Column-Level Security
Approach
Detail
GRANT on specific cols
GRANT SELECT(name, email) ON users TO ...
Views
Project allowed cols only
Data masking (SQL Server, Oracle)
Built-in static/dynamic masking
Encryption
App-side encrypt sensitive cols
5. Using Database Encryption
Layer
Mechanism
In-transit
TLS (require, verify-full)
At-rest (disk)
LUKS, EBS encryption, TDE
TDE
Transparent Data Encryption (Oracle/SQL Server)
Column-level (DB)
pgcrypto, Always Encrypted
App-level
AES-GCM with envelope keys (KMS)
6. Implementing SQL Injection Prevention
Defense
Detail
Parameterized queries
Always — never concatenate user input
ORM / query builder
Treats inputs as data
Least privilege
App role can't DROP/ALTER
Stored procedures
Defined query shape
Input validation
Allow-list for identifiers (table/col names)
WAF
Second line of defense
Warning: Dynamic SQL is the #1 source of SQLi. If you must build queries dynamically, validate identifiers against an allow-list and bind values as parameters.