# NoSQL Database Examples
# 1. Document Store (MongoDB-style)
= {
mongodb_example "_id": "507f1f77bcf86cd799439011",
"name": "John Doe",
"email": "john@example.com",
"age": 30,
"address": {
"street": "123 Main St",
"city": "Yerevan"
},"hobbies": ["coding", "chess"],
"posts": [
"title": "My First Post", "date": "2024-01-01"},
{"title": "Learning NoSQL", "date": "2024-01-02"}
{
]
}
# 2. Key-Value Store (Redis-style)
= {
redis_example "user:1001": "{'name':'John','email':'john@example.com'}",
"session:abc123": "{'user_id':1001,'expires':'2024-12-31'}",
"cache:trending": "['post1','post2','post3']"
}
# 3. Graph Database (Neo4j-style)
= """
graph_example (john:Person {name:'John', age:30})-[:FRIENDS_WITH]->(jane:Person {name:'Jane'})
(john)-[:WORKS_AT]->(company:Company {name:'TechCorp'})
(jane)-[:LIVES_IN]->(city:City {name:'Yerevan'})
"""
16 DBs (Supabase)
ีฌีธึีฝีกีถีฏีกึีซ ีฐีฒีธึีดีจ, ีีฅีฒีซีถีกีฏี Karine Avetisyan
Song reference - ToDo
๐ ีีฏีกึีกีฃีซึ
๐ ิฑีดีขีธีฒีปีกีฏีกีถ ีถีตีธึีฉีจ
๐บ ีีฅีฝีกีถีตีธึีฉีฅึ
๐ก ีีถีกีตีซีถ
๐ ีีตีธึีฉีจ
๐๏ธ Database Types Overview
๐ SQL Databases (Relational)
- Structure: Tables with rows and columns, strict schema
- Query Language: SQL (Structured Query Language)
- ACID Properties: Atomicity, Consistency, Isolation, Durability
๐ ACID Properties Explained
ACID guarantees reliable database transactions:
A - Atomicity โ๏ธ
- โAll or Nothingโ - A transaction either completes fully or not at all
- If any part fails, the entire transaction is rolled back
- Example: Bank transfer - both debit and credit must succeed, or neither happens
C - Consistency ๐ฏ
- โData Integrityโ - Database stays in a valid state before and after transactions
- All rules, constraints, and relationships are maintained
- Example: Account balance canโt be negative if thereโs a constraint
I - Isolation ๐
- โConcurrent Safetyโ - Multiple transactions donโt interfere with each other
- Each transaction sees a consistent view of the database
- Changes made by one transaction are not visible to others until they are committed.
- It ensures that the result of concurrent transactions is the same as if they were run one after another.
- Example: Two people trying to buy the last item - only one transaction succeeds
D - Durability ๐พ
- โPermanent Changesโ - Once committed, data survives system crashes
- Changes are written to persistent storage
- Example: Your bank deposit is safe even if the server crashes
Popular SQL Databases:
- PostgreSQL - Advanced, open-source
- MySQL - Fast, widely used
- SQLite - Lightweight, serverless
- Oracle - Enterprise-grade
- SQL Server - Microsoftโs solution
๐ NoSQL Databases (Non-Relational)
- Structure: Flexible, schema-less documents/key-value pairs
- Query Language: Varies by type
- Scalability: Horizontal scaling, eventual consistency
NoSQL Types:
1. Document Stores
- MongoDB, CouchDB
- Store JSON-like documents
- Flexible schema
2. Key-Value Stores
- Redis, DynamoDB
- Simple key-value pairs
- High performance
3. Graph Databases
- Neo4j, ArangoDB
- Nodes and relationships
- Complex connections
โ๏ธ SQL vs NoSQL Comparison
Feature | SQL | NoSQL |
---|---|---|
Schema | Fixed, predefined | Flexible, dynamic |
Scaling | Vertical (upgrade hardware) | Horizontal (add servers) |
Consistency | ACID guaranteed | Eventual consistency |
Queries | Complex SQL joins | Simple key lookups |
Transactions | Full ACID support | Limited transactions |
Data Structure | Structured, relational | Semi/unstructured |
Learning Curve | Steeper (SQL syntax) | Easier (JSON-like) |
๐ฏ When to Use Each?
Choose SQL When:
- โ Complex relationships between data
- โ
Need ACID transactions
- โ Structured, well-defined data
- โ Complex reporting queries
- โ Mature ecosystem needed
Choose NoSQL When:
- โ Rapid development needed
- โ Flexible/changing data structure
- โ Massive scale required
- โ Simple read/write operations
- โ Document-based data
๐ง Specialized Databases
๐ Search Engines
- Elasticsearch - Full-text search, analytics
- Solr - Enterprise search platform
๐ Time Series
- InfluxDB - IoT, monitoring data
- TimescaleDB - PostgreSQL extension for time series
๐ง Vector Databases
- Pinecone - ML embeddings, AI applications
- Weaviate - Vector search with ML
๐ In-Memory
- Redis - Caching, real-time analytics
- Memcached - Simple key-value caching
๐ Multi-Model
- ArangoDB - Document + Graph + Key-Value
- Azure Cosmos DB - Multiple APIs in one service
๐ Database Keys & Constraints
๐๏ธ Types of Database Keys
Primary Key ๐
- Unique identifier for each record in a table
- Cannot be NULL or duplicate
- Automatically indexed for fast lookups
Examples:
-- Auto-incrementing primary key
id BIGSERIAL PRIMARY KEY
-- Composite primary key (multiple columns)
PRIMARY KEY (user_id, product_id)
-- Natural primary key
VARCHAR(255) PRIMARY KEY email
Foreign Key ๐
- Links two tables together
- References primary key of another table
- Maintains referential integrity
- Can be NULL (optional relationship)
Examples:
-- Simple foreign key
REFERENCES supplier(id)
supplier_id BIGINT
-- Foreign key with actions
REFERENCES supplier(id)
supplier_id BIGINT ON DELETE CASCADE -- Delete related records
ON UPDATE SET NULL -- Set to NULL on update
Unique Key โจ
- Must be unique across all records
- Can have multiple unique keys per table
- Can be NULL (unlike primary key)
Examples:
VARCHAR(255) UNIQUE
email VARCHAR(50) UNIQUE
username VARCHAR(20) UNIQUE phone_number
๐ก๏ธ Database Constraints
NOT NULL Constraint โ
- Prevents empty values in required fields
- Ensures data completeness
NOT NULL -- Required field
name TEXT VARCHAR(255) NOT NULL -- Must have email email
CHECK Constraint โ
- Custom validation rules
- Business logic enforcement
INTEGER CHECK (age >= 0 AND age <= 150)
age INTEGER CHECK (price > 0)
price CHECK (status IN ('active', 'inactive', 'pending')) status TEXT
DEFAULT Constraint ๐ฏ
- Automatic value assignment
- Reduces data entry errors
DEFAULT NOW()
created_at TIMESTAMPTZ DEFAULT 'active'
status TEXT DEFAULT 'Unknown' country TEXT
CASCADE Actions ๐
- Automatic relationship management
- Maintains data integrity
-- When supplier is deleted, set cheese supplier_id to NULL
ON DELETE SET NULL
-- When supplier is deleted, delete all related cheeses
ON DELETE CASCADE
-- When supplier ID changes, update all references
ON UPDATE CASCADE
๐ Supabase Tutorial
Supabase is an open-source Backend-as-a-Service (BaaS) that provides: - PostgreSQL database with real-time subscriptions - Authentication & user management - Auto-generated APIs (REST & GraphQL) - File storage - Edge functions
๐ Resources
1๏ธโฃ Setup & Installation
Prerequisites
- Create Supabase Account at supabase.com
- Create New Project in Supabase dashboard
- Get API Keys from Project Settings > API
Environment Setup
Create a .env
file in your project root:
SUPABASE_URL=https://your-project.supabase.co
SUPABASE_KEY=your-anon-public-key
Install Dependencies
# Install Supabase Python SDK
!uv pip install supabase python-dotenv
Using Python 3.10.18 environment at: C:\Users\hayk_\.conda\envs\lectures
Resolved 30 packages in 220ms
Uninstalled 2 packages in 41ms
Installed 14 packages in 296ms
+ deprecation==2.1.0
+ h2==4.2.0
+ hpack==4.1.0
+ hyperframe==6.1.0
+ postgrest==1.1.1
+ pyjwt==2.10.1
+ realtime==2.7.0
+ storage3==0.12.1
+ strenum==0.4.15
+ supabase==2.18.1
+ supabase-auth==2.12.3
+ supabase-functions==0.10.1
- typing-extensions==4.12.2 (from file:///C:/b/abs_0ffjxtihug/croot/typing_extensions_1734714875646/work)
~ typing-extensions==4.14.1
+ websockets==15.0.1
# ๐ Connect to Supabase
from dotenv import load_dotenv
=True)
load_dotenv(override
import os
from supabase import create_client, Client
# Get credentials from environment variables
= os.getenv("SUPABASE_URL")
supabase_url = os.getenv("SUPABASE_KEY")
supabase_key
= create_client(supabase_url, supabase_key) supabase: Client
2๏ธโฃ Database Schema & Table Creation
๐ Our Example Schema
Weโll create a cheese marketplace database with: - Suppliers - Companies that provide cheese - Cheese - Products with prices and supplier relationships - Users - Customers (for authentication examples)
๐ฏ Database Design Principles
- Primary Keys: Unique identifiers for each record
- Foreign Keys: Link tables together (relationships)
- Constraints: Ensure data quality (NOT NULL, CHECK, UNIQUE)
- Indexes: Speed up queries on frequently searched columns
๐ ๏ธ Table Creation SQL
Option 1: Run these queries in Supabase SQL Editor (Dashboard > SQL Editor)
Option 2: Execute via Python (shown in next cell)
-- Recommended: run in the Supabase SQL editor
-- SUPPLIERS
if not exists public.supplier (
create table id bigserial primary key,
not null default now(),
created_at timestamptz not null unique
name text ;
)
-- CHEESES
if not exists public.cheese (
create table id bigserial primary key,
not null default now(),
created_at timestamptz -- store prices in integer cents (e.g., 550 = โฌ5.50)
not null check (price >= 0),
price integer not null,
name text
supplier_id bigint,
constraint cheese_supplier_id_fkey
foreign key (supplier_id)id)
references public.supplier(set null
on delete ;
)
-- Helpful indexes
if not exists idx_cheese_supplier_id on public.cheese(supplier_id);
create index if not exists idx_cheese_price on public.cheese(price); create index
import pandas as pd
= supabase.table("testing").select("*").execute()
response print(pd.DataFrame(response.data))
name
0 barev
= (
response "cheese")
supabase.table("id":509, "name": "Cheddar", "price": 509})
.insert({
.execute() )
= (
response "cheese")
supabase.table("id": 2, "name": "Cheddar"})
.insert({
.execute() )
= supabase.table("supplier").select("*").execute()
response
# insert
= (
response "supplier")
supabase.table("id": 1, "name": "Supplier A"})
.insert({
.execute() )
= supabase.table("supplier").select("*").execute()
response response
APIResponse[~_ReturnT](data=[{'id': 1, 'created_at': '2025-08-19T00:36:25.140416+00:00', 'name': 'Supplier A'}], count=None)
# ๐ง Create Artificial Data for Testing
# Insert cheeses
print("๐ง Inserting cheeses...")
= [
cheeses_data "id": 3, "name": "Brie", "price": 1875, "supplier_id": 2},
{"id": 4, "name": "Camembert", "price": 1625, "supplier_id": 2},
{"id": 5, "name": "Emmental", "price": 2200, "supplier_id": 3},
{"id": 6, "name": "Gruyere", "price": 2850, "supplier_id": 3},
{"id": 7, "name": "Cheddar", "price": 1500, "supplier_id": 4},
{"id": 8, "name": "Gouda", "price": 1975, "supplier_id": 4}
{
]
"cheese").insert(cheeses_data).execute()
supabase.table(
print("โ
Cheeses inserted!")
print("๐ Artificial data ready for testing!")
๐ง Inserting cheeses...
โ
Cheeses inserted!
๐ Artificial data ready for testing!
print("๐ฆ Inserting suppliers...")
= [
suppliers_data "id": 2, "name": "ิฟีธีพีซีฏีถีฅึ ีีิธ"},
{"id": 3, "name": "Swiss Dairy"},
{"id": 4, "name": "Local Farm"}
{
]
for supplier in suppliers_data:
"supplier").insert(supplier).execute()
supabase.table(
print("โ
Suppliers inserted!")
๐ฆ Inserting suppliers...
โ
Suppliers inserted!
โ
Suppliers inserted!
# ๐ FILTERING Examples
print("๐ FILTERING & SORTING EXAMPLES")
print("=" * 50)
# Filter 1: Price-based filtering
print("๐ฐ Premium cheeses (price > $7.00):")
= supabase.table("cheese").select("name, price, category").gt("price", 700).execute()
expensive for cheese in expensive.data:
print(f" โข {cheese['name']}: ${cheese['price']/100:.2f} ({cheese['category']})")
print()
# Filter 2: Category filtering
print("๐ง Hard cheeses:")
= supabase.table("cheese").select("name, price").eq("category", "Hard").execute()
hard_cheese for cheese in hard_cheese.data:
print(f" โข {cheese['name']}: ${cheese['price']/100:.2f}")
print()
# Filter 3: Price range filtering
print("๐ต Mid-range cheeses ($6.00 - $8.00):")
= (supabase.table("cheese")
midrange "name, price, category")
.select("price", 600)
.gte("price", 800)
.lte(
.execute())for cheese in midrange.data:
print(f" โข {cheese['name']}: ${cheese['price']/100:.2f} ({cheese['category']})")
print()
# Filter 4: Multiple values with IN
print("๐ซ๐ท French cheese categories (Soft OR Blue):")
= (supabase.table("cheese")
french_types "name, price, category")
.select("category", ["Soft", "Blue"])
.in_(
.execute())for cheese in french_types.data:
print(f" โข {cheese['name']}: ${cheese['price']/100:.2f} ({cheese['category']})")
print()
# Filter 5: Text search (case-insensitive)
print("๐ค Cheeses with 'em' in name:")
= (supabase.table("cheese")
text_search "name, price")
.select("name", "%em%") # Case-insensitive LIKE
.ilike(
.execute())for cheese in text_search.data:
print(f" โข {cheese['name']}: ${cheese['price']/100:.2f}")
print()
# Filter 6: Sorting
print("๐ All cheeses sorted by price (ascending):")
= (supabase.table("cheese")
sorted_cheese "name, price, category")
.select("price", desc=False)
.order(
.execute())for cheese in sorted_cheese.data:
print(f" โข {cheese['name']}: ${cheese['price']/100:.2f} ({cheese['category']})")
print("\n" + "=" * 50)
# ๐ 2. GROUP BY Examples (using PostgreSQL functions)
print("๐ GROUP BY EXAMPLES")
print("=" * 50)
# Note: Supabase Python client doesn't have direct GROUP BY
# But we can use PostgreSQL functions with .rpc() or manual SQL
# Group By 1: Count cheeses per supplier
print("๐ญ Cheeses count per supplier:")
# We'll do this manually by getting data and processing
= supabase.table("cheese").select("supplier_id").execute()
all_cheeses = {}
supplier_counts for cheese in all_cheeses.data:
= cheese['supplier_id']
sid = supplier_counts.get(sid, 0) + 1
supplier_counts[sid]
# Get supplier names
for supplier_id, count in supplier_counts.items():
= supabase.table("supplier").select("name").eq("id", supplier_id).execute()
supplier = supplier.data[0]['name'] if supplier.data else f"Supplier {supplier_id}"
supplier_name print(f" - {supplier_name}: {count} cheeses")
print()
# Group By 2: Average price per supplier
print("๐ฐ Average price per supplier:")
= supabase.table("cheese").select("supplier_id, price").execute()
all_data = {}
supplier_prices for cheese in all_data.data:
= cheese['supplier_id']
sid if sid not in supplier_prices:
= []
supplier_prices[sid] 'price'])
supplier_prices[sid].append(cheese[
for supplier_id, prices in supplier_prices.items():
= sum(prices) / len(prices)
avg_price = supabase.table("supplier").select("name").eq("id", supplier_id).execute()
supplier = supplier.data[0]['name'] if supplier.data else f"Supplier {supplier_id}"
supplier_name print(f" - {supplier_name}: ${avg_price:.2f}")
print()
# Group By 3: Price ranges
print("๐ Cheese count by price range:")
= {"$0-15": 0, "$15-20": 0, "$20-25": 0, "$25+": 0}
price_ranges for cheese in all_data.data:
= cheese['price']
price if price < 15:
"$0-15"] += 1
price_ranges[elif price < 20:
"$15-20"] += 1
price_ranges[elif price < 25:
"$20-25"] += 1
price_ranges[else:
"$25+"] += 1
price_ranges[
for range_name, count in price_ranges.items():
print(f" - {range_name}: {count} cheeses")
print("\n" + "=" * 50)
# ๐ 3. JOIN Examples
print("๐ JOIN EXAMPLES")
print("=" * 50)
# Join 1: Get all cheeses with their supplier names
print("๐ง All cheeses with supplier information:")
# In Supabase, we use foreign table syntax for joins
= (supabase.table("cheese")
cheese_with_suppliers "id, name, price, supplier:supplier_id(name)")
.select(
.execute())
for item in cheese_with_suppliers.data:
= item['supplier']['name'] if item['supplier'] else 'Unknown'
supplier_name print(f" - {item['name']} (${item['price']}) from {supplier_name}")
print()
# Join 2: Get suppliers with their cheese count and total value
print("๐ญ Suppliers with cheese inventory:")
= (supabase.table("supplier")
suppliers_with_cheeses "id, name, cheese:cheese(name, price)")
.select(
.execute())
for supplier in suppliers_with_cheeses.data:
= supplier['cheese']
cheese_list = len(cheese_list)
cheese_count = sum(cheese['price'] for cheese in cheese_list)
total_value = [cheese['name'] for cheese in cheese_list]
cheese_names
print(f" - {supplier['name']}:")
print(f" โข {cheese_count} cheeses")
print(f" โข Total value: ${total_value:.2f}")
print(f" โข Products: {', '.join(cheese_names)}")
print()
# Join 3: Get expensive cheeses (>$20) with supplier info
print("๐ Premium cheeses (>$20) with suppliers:")
= (supabase.table("cheese")
premium_cheeses "name, price, supplier:supplier_id(name)")
.select("price", 20)
.gt(
.execute())
for cheese in premium_cheeses.data:
= cheese['supplier']['name'] if cheese['supplier'] else 'Unknown'
supplier_name print(f" - {cheese['name']}: ${cheese['price']} from {supplier_name}")
print()
# Join 4: Filter by supplier and show their cheeses
print("๐ซ๐ท French supplier cheeses:")
= (supabase.table("cheese")
french_cheeses "name, price, supplier:supplier_id(name)")
.select("supplier_id", 2) # French Fromagerie
.eq(
.execute())
for cheese in french_cheeses.data:
print(f" - {cheese['name']}: ${cheese['price']}")
print("\n" + "=" * 50)
print("๐ All examples completed!")
GPT
-- ๐ญ SUPPLIERS TABLE
-- Stores information about cheese suppliers/manufacturers
CREATE TABLE IF NOT EXISTS public.supplier (id BIGSERIAL PRIMARY KEY, -- Auto-incrementing ID
-- Automatic timestamp
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), -- Company name (must be unique)
name TEXT NOT NULL UNIQUE, 'Unknown', -- Country of origin
country TEXT DEFAULT -- Optional website URL
website TEXT, -- Contact information
contact_email TEXT ;
)
-- ๐ง CHEESE TABLE
-- Stores cheese products with pricing and supplier relationships
CREATE TABLE IF NOT EXISTS public.cheese (id BIGSERIAL PRIMARY KEY, -- Auto-incrementing ID
-- Automatic timestamp
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), -- Cheese name
name TEXT NOT NULL, >= 0), -- Price in cents (e.g., 550 = $5.50)
price INTEGER NOT NULL CHECK (price -- Optional description
description TEXT, 'Other', -- Cheese category
category TEXT DEFAULT -- Foreign key to supplier
supplier_id BIGINT,
-- Foreign key constraint with cascade options
CONSTRAINT cheese_supplier_fkey
FOREIGN KEY (supplier_id) id)
REFERENCES public.supplier(-- If supplier deleted, set to NULL
ON DELETE SET NULL ;
)
-- ๐ PERFORMANCE INDEXES
-- Speed up common queries
;
CREATE INDEX IF NOT EXISTS idx_cheese_supplier_id ON public.cheese(supplier_id);
CREATE INDEX IF NOT EXISTS idx_cheese_price ON public.cheese(price);
CREATE INDEX IF NOT EXISTS idx_cheese_category ON public.cheese(category);
CREATE INDEX IF NOT EXISTS idx_supplier_country ON public.supplier(country)
-- ๐ก COMMENTS FOR DOCUMENTATION
'Cheese suppliers and manufacturers';
COMMENT ON TABLE public.supplier IS 'Cheese products with pricing and supplier info';
COMMENT ON TABLE public.cheese IS 'Price stored in cents to avoid decimal issues'; COMMENT ON COLUMN public.cheese.price IS
# ๐ ๏ธ Create Tables via Python (Alternative to SQL Editor)
def create_database_schema():
"""
Create database tables programmatically using Supabase
This is an alternative to running SQL in the Supabase dashboard
"""
# SQL for creating suppliers table
= """
suppliers_sql CREATE TABLE IF NOT EXISTS public.supplier (
id BIGSERIAL PRIMARY KEY,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
name TEXT NOT NULL UNIQUE,
country TEXT DEFAULT 'Unknown',
website TEXT,
contact_email TEXT
);
"""
# SQL for creating cheese table
= """
cheese_sql CREATE TABLE IF NOT EXISTS public.cheese (
id BIGSERIAL PRIMARY KEY,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
name TEXT NOT NULL,
price INTEGER NOT NULL CHECK (price >= 0),
description TEXT,
category TEXT DEFAULT 'Other',
supplier_id BIGINT,
CONSTRAINT cheese_supplier_fkey
FOREIGN KEY (supplier_id)
REFERENCES public.supplier(id)
ON DELETE SET NULL
);
"""
# SQL for creating indexes
= """
indexes_sql CREATE INDEX IF NOT EXISTS idx_cheese_supplier_id ON public.cheese(supplier_id);
CREATE INDEX IF NOT EXISTS idx_cheese_price ON public.cheese(price);
CREATE INDEX IF NOT EXISTS idx_cheese_category ON public.cheese(category);
CREATE INDEX IF NOT EXISTS idx_supplier_country ON public.supplier(country);
"""
try:
print("๐๏ธ Creating database schema...")
# Execute table creation SQL
"public").rpc("sql", {"query": suppliers_sql}).execute()
supabase.postgrest.schema(print("โ
Suppliers table created")
"public").rpc("sql", {"query": cheese_sql}).execute()
supabase.postgrest.schema(print("โ
Cheese table created")
"public").rpc("sql", {"query": indexes_sql}).execute()
supabase.postgrest.schema(print("โ
Indexes created")
print("๐ Database schema setup complete!")
except Exception as e:
print(f"โ Error creating schema: {e}")
print("๐ก Try running the SQL directly in Supabase SQL Editor instead")
# Uncomment the line below to create tables
# create_database_schema()
print("๐ Table creation function defined!")
print("๐ก Uncomment the last line to create tables programmatically")
print("๐ง Or copy the SQL above to Supabase SQL Editor (recommended)")
3๏ธโฃ CRUD Operations (Create, Read, Update, Delete)
๐ Basic Database Operations
- CREATE - Insert new records
- READ - Query and retrieve data
- UPDATE - Modify existing records
- DELETE - Remove records
๐ง Sample Data Setup
Letโs start by adding some sample suppliers and cheese products to work with.
from supabase import create_client, Client
import os
= os.environ["SUPABASE_URL"]
url = os.environ["SUPABASE_KEY"] # or anon for read-only
key = create_client(url, key) supabase: Client
# ๐ญ CREATE: Insert Suppliers
# Sample supplier data with more details
= [
suppliers_data
{"id": 1,
"name": "ิฟีธีพีซีฏีถีฅึ ีีิธ",
"country": "Armenia",
"website": "https://kovikner.am",
"contact_email": "info@kovikner.am"
},
{"id": 2,
"name": "French Fromagerie",
"country": "France",
"website": "https://fromagerie.fr",
"contact_email": "contact@fromagerie.fr"
},
{"id": 3,
"name": "Swiss Alpine Dairy",
"country": "Switzerland",
"website": "https://alpinedairy.ch",
"contact_email": "orders@alpinedairy.ch"
}
]
try:
# Insert suppliers with error handling
print("๐ญ Inserting suppliers...")
= supabase.table("supplier").insert(suppliers_data).execute()
response
print(f"โ
Successfully inserted {len(response.data)} suppliers!")
for supplier in response.data:
print(f" โข {supplier['name']} (ID: {supplier['id']})")
except Exception as e:
print(f"โ Error inserting suppliers: {e}")
print("๐ก Suppliers might already exist, or check your table schema")
APIResponse[~_ReturnT](data=[{'id': 1, 'created_at': '2025-08-19T01:02:56.083173+00:00', 'name': 'ิฟีธีพีซีฏีถีฅึ ีีิธ'}, {'id': 2, 'created_at': '2025-08-19T01:02:56.083173+00:00', 'name': 'ีีีีีีีี ีิฒิธ'}, {'id': 3, 'created_at': '2025-08-19T01:02:56.083173+00:00', 'name': 'ีีธึีธึีฅึีซ ีฐีกีดีกีฏีธีพีกีฏีกีถ ีกีฝีธึีซึีกึีซีก'}], count=None)
# ๐ง CREATE: Insert Cheese Products
# Diverse cheese data with categories and descriptions
= [
cheese_data
{"name": "Gouda",
"price": 550,
"supplier_id": 3,
"category": "Hard",
"description": "Classic Dutch cheese with a rich, nutty flavor"
},
{"name": "ิผีธีผีซ",
"price": 850,
"supplier_id": 1,
"category": "Fresh",
"description": "Traditional Armenian cheese, perfect for breakfast"
},
{"name": "Roquefort",
"price": 920,
"supplier_id": 2,
"category": "Blue",
"description": "Famous French blue cheese with sharp, tangy flavor"
},
{"name": "Emmental",
"price": 690,
"supplier_id": 3,
"category": "Hard",
"description": "Swiss cheese with characteristic holes and mild taste"
},
{"name": "Camembert",
"price": 780,
"supplier_id": 2,
"category": "Soft",
"description": "Creamy French cheese with white rind"
},
{"name": "Chanakh",
"price": 750,
"supplier_id": 1,
"category": "Brined",
"description": "Traditional Armenian brined cheese"
}
]
try:
print("๐ง Inserting cheese products...")
= supabase.table("cheese").insert(cheese_data).execute()
response
print(f"โ
Successfully inserted {len(response.data)} cheese products!")
for cheese in response.data:
= cheese['price'] / 100
price_dollars print(f" โข {cheese['name']}: ${price_dollars:.2f} ({cheese['category']})")
except Exception as e:
print(f"โ Error inserting cheeses: {e}")
print("๐ก Check if suppliers exist first, or table constraints")
APIResponse[~_ReturnT](data=[{'id': 1, 'created_at': '2025-08-19T01:04:33.868746+00:00', 'price': 550, 'name': 'Gouda', 'supplier_id': 1}, {'id': 2, 'created_at': '2025-08-19T01:04:33.868746+00:00', 'price': 850, 'name': 'ิผีธีผีซ', 'supplier_id': 1}, {'id': 3, 'created_at': '2025-08-19T01:04:33.868746+00:00', 'price': 920, 'name': 'ีีกีถีกีญ', 'supplier_id': 2}, {'id': 4, 'created_at': '2025-08-19T01:04:33.868746+00:00', 'price': 890, 'name': 'ิฒีธึีขีธีฝีธีพ', 'supplier_id': 3}], count=None)
# ๐ READ: Query Data
import pandas as pd
print("๐ READING DATA FROM TABLES")
print("=" * 50)
# 1. Get all cheeses
print("๐ง All cheese products:")
= supabase.table("cheese").select("*").execute()
response = pd.DataFrame(response.data)
cheese_df
if not cheese_df.empty:
# Convert price from cents to dollars for display
'price_dollars'] = cheese_df['price'] / 100
cheese_df[print(cheese_df[['id', 'name', 'price_dollars', 'category', 'supplier_id']].to_string(index=False))
else:
print("No cheese products found")
print("\n" + "-" * 30)
# 2. Get all suppliers
print("๐ญ All suppliers:")
= supabase.table("supplier").select("*").execute()
response = pd.DataFrame(response.data)
supplier_df
if not supplier_df.empty:
print(supplier_df[['id', 'name', 'country', 'website']].to_string(index=False))
else:
print("No suppliers found")
print("\n" + "=" * 50)
id created_at price name supplier_id
0 1 2025-08-19T01:04:33.868746+00:00 550 Gouda 1
1 2 2025-08-19T01:04:33.868746+00:00 850 ิผีธีผีซ 1
2 3 2025-08-19T01:04:33.868746+00:00 920 ีีกีถีกีญ 2
3 4 2025-08-19T01:04:33.868746+00:00 890 ิฒีธึีขีธีฝีธีพ 3
# Top 10 most expensive
= (supabase.table("cheese")
r "id,name,price")
.select("price", 1000)
.gt("name", ["Gouda"])
.in_("price", desc=True)
.order(range(0, 10)
.
.execute())= pd.DataFrame(r.data)
df print(df)
id name price
0 8 Gouda 1975
# Alias "supplier" from the FK column supplier_id
= (supabase.table("cheese")
r "id,name,price,supplier:supplier_id(id,name)")
.select(
.execute())print(pd.DataFrame(r.data))
id name price supplier
0 1 Gouda 550 {'id': 1, 'name': 'ิฟีธีพีซีฏีถีฅึ ีีิธ'}
1 2 ิผีธีผีซ 850 {'id': 1, 'name': 'ิฟีธีพีซีฏีถีฅึ ีีิธ'}
2 3 ีีกีถีกีญ 920 {'id': 2, 'name': 'ีีีีีีีี ีิฒิธ'}
3 4 ิฒีธึีขีธีฝีธีพ 890 {'id': 3, 'name': 'ีีธึีธึีฅึีซ ีฐีกีดีกีฏีธีพีกีฏีกีถ ีกีฝีธึีซึ...
# Alias "supplier" from the FK column supplier_id
= (supabase.table("cheese")
r "id,name,price,supplier:supplier_id(name)")
.select(
.execute())print(pd.DataFrame(r.data))
id name price supplier
0 1 Gouda 550 {'name': 'ิฟีธีพีซีฏีถีฅึ ีีิธ'}
1 2 ิผีธีผีซ 850 {'name': 'ิฟีธีพีซีฏีถีฅึ ีีิธ'}
2 3 ีีกีถีกีญ 920 {'name': 'ีีีีีีีี ีิฒิธ'}
3 4 ิฒีธึีขีธีฝีธีพ 890 {'name': 'ีีธึีธึีฅึีซ ีฐีกีดีกีฏีธีพีกีฏีกีถ ีกีฝีธึีซึีกึีซีก'}
# Require a match using !inner
= (supabase.table("cheese")
r "id,name,price,supplier!inner(id,name)")
.select(
.execute())print(pd.DataFrame(r.data))
id name price supplier
0 1 Gouda 550 {'id': 1, 'name': 'ิฟีธีพีซีฏีถีฅึ ีีิธ'}
1 2 ิผีธีผีซ 850 {'id': 1, 'name': 'ิฟีธีพีซีฏีถีฅึ ีีิธ'}
2 3 ีีกีถีกีญ 920 {'id': 2, 'name': 'ีีีีีีีี ีิฒิธ'}
3 4 ิฒีธึีขีธีฝีธีพ 890 {'id': 3, 'name': 'ีีธึีธึีฅึีซ ีฐีกีดีกีฏีธีพีกีฏีกีถ ีกีฝีธึีซึ...
= (supabase.table("cheese")
r "id,name,price,supplier!inner(id,name)")
.select("supplier.name", "ีีีีีีีี ีิฒิธ")
.eq(
.execute())print(pd.DataFrame(r.data))
id name price supplier
0 3 ีีกีถีกีญ 920 {'id': 2, 'name': 'ีีีีีีีี ีิฒิธ'}
# โ๏ธ UPDATE & ๐๏ธ DELETE Operations
print("โ๏ธ UPDATE EXAMPLES")
print("=" * 30)
# Update a cheese price
try:
print("๐ฐ Updating Gouda price from $5.50 to $6.25...")
= (supabase.table("cheese")
response "price": 625}) # $6.25 in cents
.update({"name", "Gouda")
.eq(
.execute())
if response.data:
= response.data[0]
updated_cheese print(f"โ
Updated: {updated_cheese['name']} now costs ${updated_cheese['price']/100:.2f}")
else:
print("โ No cheese updated - check if 'Gouda' exists")
except Exception as e:
print(f"โ Update error: {e}")
print()
# Update supplier website
try:
print("๐ Updating supplier website...")
= (supabase.table("supplier")
response "website": "https://kovikner-updated.am"})
.update({"name", "ิฟีธีพีซีฏีถีฅึ ีีิธ")
.eq(
.execute())
if response.data:
= response.data[0]
updated_supplier print(f"โ
Updated: {updated_supplier['name']} website")
else:
print("โ No supplier updated")
except Exception as e:
print(f"โ Update error: {e}")
print("\n" + "๐๏ธ DELETE EXAMPLES")
print("=" * 30)
# Note: Be careful with DELETE operations!
print("โ ๏ธ DELETE operations are permanent!")
print("๐ก In production, consider 'soft deletes' (marking as inactive)")
print("๐ For this tutorial, we'll skip actual deletions to preserve data")
# Example of how you would delete (commented out):
# Delete a specific cheese
# response = supabase.table("cheese").delete().eq("name", "SomeCheeseToDelete").execute()
# Delete all cheeses from a supplier
# response = supabase.table("cheese").delete().eq("supplier_id", 999).execute()
print("๐ DELETE syntax examples shown above (commented out for safety)")
APIResponse[~_ReturnT](data=[{'id': 2, 'created_at': '2025-08-19T01:02:56.083173+00:00', 'name': 'ีีีีีีีีีีีีีีีีีีีีีีีี ีิฒิธ'}], count=None)
4๏ธโฃ Advanced Queries
๐ Filtering, Sorting & Joins
Master advanced database operations to build powerful applications.
Query Types Weโll Cover:
- Filtering - Find specific records with conditions
- Sorting - Order results by price, name, etc.
- Joining - Combine data from multiple tables
- Aggregation - Count, sum, average operations
- Pagination - Handle large datasets efficiently
6๏ธโฃ Real-time Features
โก Live Data Updates
Supabase provides real-time subscriptions to database changes:
# Subscribe to cheese table changes
def handle_changes(payload):
print(f"Change detected: {payload}")
# Listen for all changes
"cheese").on("*", handle_changes).subscribe()
supabase.table(
# Listen for specific events
"cheese").on("INSERT", handle_changes).subscribe()
supabase.table("cheese").on("UPDATE", handle_changes).subscribe()
supabase.table("cheese").on("DELETE", handle_changes).subscribe() supabase.table(
๐ Use Cases for Real-time:
- Live dashboards - Stock levels, sales metrics
- Collaborative apps - Multiple users editing data
- Notifications - Alert users when data changes
- Chat applications - Real-time messaging
- Gaming - Live scoreboards and updates
๐ก Real-time Architecture:
- Uses WebSocket connections
- PostgreSQL triggers detect changes
- Pub/Sub system broadcasts updates
- Automatic reconnection handling
๐ฏ Next Steps & Best Practices
๐ Production Considerations
Security
- Enable Row Level Security (RLS) policies
- Use environment variables for API keys
- Implement proper authentication flows
- Set up database backups
Performance
- Add indexes for frequently queried columns
- Use connection pooling for high-traffic apps
- Implement caching strategies (Redis, etc.)
- Monitor query performance and optimize
Scaling
- Use edge functions for serverless logic
- Implement horizontal scaling strategies
- Consider read replicas for read-heavy workloads
- Plan data archiving for historical data
๐ Additional Resources
Advanced Features to Explore:
- Edge Functions - Serverless functions at the edge
- Storage - File uploads and management
- PostgREST - Auto-generated REST APIs
- GraphQL - Alternative API interface
- Webhooks - External system integrations
Supabase Ecosystem:
- Dashboard - Visual database management
- CLI tools - Command-line development
- Migration system - Database schema versioning
- Extensions - PostgreSQL extensions support
๐ Congratulations!
Youโve completed the Supabase tutorial! You now know how to: - โ
Set up Supabase projects and connections - โ
Create database schemas and tables - โ
Perform CRUD operations - โ
Write advanced queries with filtering and joins
- โ
Implement authentication and authorization - โ
Understand real-time capabilities
Keep building and exploring! ๐
๐ฒ 34 (16)
- โถ๏ธีีฝีฏีฅ ึีฌีซีฏีจ
- ๐Random link
- ๐ฆ๐ฒ๐ถHigh (ีึีจี ีฟีกึีซ)
- ๐๐ถGilbert OโSullivan - Alone Again
- ๐คิฟีกึีฃีซีถ