Raw SQL execution dengan db.execute(), SQL template literals yang aman dari SQL injection menggunakan sql tag, komposisi query dengan template literals, kapan menggunakan raw SQL vs query builder untuk complex queries yang sulit di-express, serta best practice keamanan.

Setelah di episode 14 kita mempelajari Prepared Statements & Performance — caching SQL, index strategy, dan profiling — pada episode ini kita membahas raw SQL: executing SQL langsung tanpa query builder, dan SQL template literals yang aman dari SQL injection.
Meskipun query builder Drizzle sangat powerful, ada situasi di mana raw SQL lebih cocok — complex queries, window functions, atau SQL-specific features yang belum didukung query builder.
import { sql } from 'drizzle-orm'
const result = await db.execute(
sql`SELECT * FROM users WHERE age > ${25}`
)sql template literal aman dari SQL injection — parameter di-escape otomatis oleh Drizzle.
import { sql } from 'drizzle-orm'
// Parameterized query
const age = 25
const result = await db.execute(
sql`SELECT * FROM users WHERE age > ${age}`
)
// SQL: SELECT * FROM users WHERE age > $1
// Params: [25]import { sql, eq, gt } from 'drizzle-orm'
// Build conditions dynamically
const conditions = sql`${users.age} > ${18}`
const roleCondition = sql` AND ${users.role} = ${'admin'}`
const result = await db.select().from(users).where(
sql`${conditions} ${roleCondition}`
)const result = await db.execute(sql`
SELECT
role,
COUNT(*) as total,
AVG(age) as avg_age
FROM users
GROUP BY role
HAVING COUNT(*) > 5
ORDER BY total DESC
`)| Aspek | Raw SQL | Query Builder |
|---|---|---|
| Use case | Complex queries, window functions | Simple-moderate queries |
| Type safety | Manual | Otomatis dari schema |
| Readability | Tergantung kompleksitas | Sangat readable |
| Performance | Full control | Optimized oleh Drizzle |
| Portability | Database-specific | Cross-database |
const result = await db.execute(sql`
SELECT
name,
age,
ROW_NUMBER() OVER (ORDER BY age DESC) as rank
FROM users
`)Window functions belum didukung penuh oleh query builder — raw SQL diperlukan.
Warning
Jangan gunakan string concatenation untuk raw SQL — ini membuka celah SQL injection. Selalu gunakan template literals (sql...``) yang parameterized. Jika query bisa di-express dengan query builder, lebih baik gunakan query builder untuk type safety.
Pada episode 15 ini, kalian telah memahami Raw SQL & Template Literals:
db.execute(sql...) untuk executing raw SQL.Di episode 16 selanjutnya kita akan mempelajari Zod Integration & Type Validation — generate Zod schemas dari Drizzle schemas, validasi input API route, dan integrasi dengan Hono/ElysiaJS. Sampai jumpa di episode 16!