Skip to content
Back to skills

Supabase Database

ASecurity

Supabase database operations including queries, CRUD operations, RLS policies, and PostgreSQL functions. Use when querying tables, managing data, implementing RLS, or writing database functions.

  • 3 stars
  • 0 votes
  • 0 copies
  • 2 views
  • Added February 8, 2026
databasesjavascripttypescriptgojavabashsqldatabasesecurityperformance

Works with

  • cli

Security analysis

A100/100

Pro scans all 4 files and shows the line behind each finding

Scanned February 12, 2026

npx -y skills add adaptationio/Skrillz --skill supabase-database --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Supabase Database?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Supabase Database
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/adaptationio-supabase-database/badge)](https://www.skillsdirectory.com/skills/adaptationio-supabase-database)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: supabase-database
description: Supabase database operations including queries, CRUD operations, RLS policies, and PostgreSQL functions. Use when querying tables, managing data, implementing RLS, or writing database functions.
---

# Supabase Database Skill

Database operations, queries, and Row Level Security.

## Quick Reference

| Operation | JavaScript | SQL |
|-----------|------------|-----|
| Select all | `supabase.from('table').select('*')` | `SELECT * FROM table` |
| Select columns | `supabase.from('table').select('col1,col2')` | `SELECT col1, col2 FROM table` |
| Filter | `.eq('col', 'value')` | `WHERE col = 'value'` |
| Insert | `.insert({ col: 'value' })` | `INSERT INTO table (col) VALUES ('value')` |
| Update | `.update({ col: 'value' }).eq('id', 1)` | `UPDATE table SET col = 'value' WHERE id = 1` |
| Delete | `.delete().eq('id', 1)` | `DELETE FROM table WHERE id = 1` |

## Basic Queries

### Select

```javascript
// All rows
const { data, error } = await supabase
  .from('users')
  .select('*')

// Specific columns
const { data, error } = await supabase
  .from('users')
  .select('id, name, email')

// With count
const { data, count, error } = await supabase
  .from('users')
  .select('*', { count: 'exact' })
```

### Insert

```javascript
// Single row
const { data, error } = await supabase
  .from('users')
  .insert({ name: 'John', email: 'john@example.com' })
  .select()

// Multiple rows
const { data, error } = await supabase
  .from('users')
  .insert([
    { name: 'John', email: 'john@example.com' },
    { name: 'Jane', email: 'jane@example.com' }
  ])
  .select()
```

### Update

```javascript
const { data, error } = await supabase
  .from('users')
  .update({ name: 'John Doe' })
  .eq('id', 1)
  .select()
```

### Upsert

```javascript
const { data, error } = await supabase
  .from('users')
  .upsert({ id: 1, name: 'John', email: 'john@example.com' })
  .select()
```

### Delete

```javascript
const { error } = await supabase
  .from('users')
  .delete()
  .eq('id', 1)
```

## Filters

### Comparison Operators

```javascript
// Equal
.eq('col', 'value')

// Not equal
.neq('col', 'value')

// Greater than
.gt('col', 10)

// Greater or equal
.gte('col', 10)

// Less than
.lt('col', 10)

// Less or equal
.lte('col', 10)
```

### Pattern Matching

```javascript
// LIKE (case sensitive)
.like('name', '%John%')

// ILIKE (case insensitive)
.ilike('name', '%john%')
```

### List Operations

```javascript
// IN array
.in('status', ['active', 'pending'])

// Contains (array column contains value)
.contains('tags', ['sports', 'news'])

// Contained by (value contained by array column)
.containedBy('tags', ['sports', 'news', 'tech'])

// Overlaps (any match)
.overlaps('tags', ['sports', 'tech'])
```

### Range Operations

```javascript
// Between (exclusive)
.range('price', 10, 100)

// In range type column
.rangeGt('date_range', '2025-01-01')
.rangeLt('date_range', '2025-12-31')
```

### Null Checks

```javascript
// Is null
.is('deleted_at', null)

// Is not null
.not('deleted_at', 'is', null)
```

### Boolean Operators

```javascript
// AND (chain filters)
.eq('status', 'active')
.eq('verified', true)

// OR
.or('status.eq.active,status.eq.pending')

// NOT
.not('status', 'eq', 'deleted')
```

## Ordering & Pagination

```javascript
// Order by
const { data } = await supabase
  .from('posts')
  .select('*')
  .order('created_at', { ascending: false })

// Multiple order
.order('category', { ascending: true })
.order('created_at', { ascending: false })

// Limit
.limit(10)

// Range (pagination)
.range(0, 9)  // First 10 rows

// Single row
.single()

// Maybe single (0 or 1)
.maybeSingle()
```

## Relations (Joins)

### One-to-Many

```javascript
// Users with their posts
const { data } = await supabase
  .from('users')
  .select(`
    id,
    name,
    posts (
      id,
      title,
      content
    )
  `)
```

### Many-to-One

```javascript
// Posts with author
const { data } = await supabase
  .from('posts')
  .select(`
    id,
    title,
    users (
      id,
      name
    )
  `)
```

### Inner Join

```javascript
// Only users with posts
const { data } = await supabase
  .from('users')
  .select(`
    id,
    name,
    posts!inner (
      id,
      title
    )
  `)
```

### Many-to-Many

```javascript
// Posts with tags through junction table
const { data } = await supabase
  .from('posts')
  .select(`
    id,
    title,
    post_tags (
      tags (
        id,
        name
      )
    )
  `)
```

## Row Level Security (RLS)

### Enable RLS

```sql
ALTER TABLE users ENABLE ROW LEVEL SECURITY;
```

### Basic Policies

```sql
-- Users can read their own data
CREATE POLICY "Users can view own data"
ON users FOR SELECT
TO authenticated
USING (auth.uid() = id);

-- Users can insert their own data
CREATE POLICY "Users can insert own data"
ON users FOR INSERT
TO authenticated
WITH CHECK (auth.uid() = id);

-- Users can update their own data
CREATE POLICY "Users can update own data"
ON users FOR UPDATE
TO authenticated
USING (auth.uid() = id)
WITH CHECK (auth.uid() = id);

-- Users can delete their own data
CREATE POLICY "Users can delete own data"
ON users FOR DELETE
TO authenticated
USING (auth.uid() = id);
```

### Helper Functions

```sql
-- Current user ID
auth.uid()

-- Current user role (anon, authenticated, service_role)
auth.role()

-- Full JWT as JSON
auth.jwt()

-- Check specific JWT claim
auth.jwt()->>'email'
auth.jwt()->'app_metadata'->>'role'
```

### Performance Optimization

```sql
-- Wrap auth functions in SELECT for performance
CREATE POLICY "Fast policy"
ON users FOR SELECT
TO authenticated
USING ((SELECT auth.uid()) = user_id);

-- Add indexes for RLS columns
CREATE INDEX idx_posts_user_id ON posts(user_id);
```

## RPC (Remote Procedure Call)

### Define Function

```sql
CREATE OR REPLACE FUNCTION search_users(query text)
RETURNS TABLE(id uuid, name text, email text)
LANGUAGE sql STABLE
AS $$
  SELECT id, name, email
  FROM users
  WHERE name ILIKE '%' || query || '%'
     OR email ILIKE '%' || query || '%'
  ORDER BY name;
$$;
```

### Call Function

```javascript
const { data, error } = await supabase
  .rpc('search_users', { query: 'john' })
```

## TypeScript Types

### Generate Types

```bash
supabase gen types typescript --local > database.types.ts
```

### Use Types

```typescript
import { Database } from './database.types'

type User = Database['public']['Tables']['users']['Row']
type NewUser = Database['public']['Tables']['users']['Insert']
type UpdateUser = Database['public']['Tables']['users']['Update']

const supabase = createClient<Database>(url, key)

const { data } = await supabase
  .from('users')
  .select('*')
// data is User[] | null
```

## References

- [rls-policies.md](references/rls-policies.md) - Complete RLS patterns
- [query-operators.md](references/query-operators.md) - All filter operators
- [postgres-functions.md](references/postgres-functions.md) - Writing SQL functions

Files in this skill

  • SKILL.md6.8 KB
  • references/postgres-functions.md7.4 KB
  • references/query-operators.md7.1 KB
  • references/rls-policies.md7.7 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…