اسکیولایت
SQLite
اجرای کوئری SQL روی دیتابیس فایلی SQLite - سبک، سریع و بدون سرور
نمای کلی
نود SQLite چیست؟
نود SQLite امکان کار مستقیم با دیتابیسهای SQLite را در n8n فراهم میکند. SQLite پرکاربردترین دیتابیس در جهان است و در هر گوشی موبایل، مرورگر و سیستمعامل استفاده میشود.
چرا SQLite؟
- بدون سرور: نیازی به نصب MySQL یا PostgreSQL نیست
- **فایلمحور**: کل دیتابیس یک فایل
.dbاست - سریع: برای عملیات خواندن فوقالعاده سریع
- قابل حمل: فایل را کپی کنید و تمام
- صفر پیکربندی: بدون هیچ تنظیماتی کار میکند
- ACID Compliant: تراکنشهای ایمن
قابلیتهای کلیدی در n8n:
- Execute Query: اجرای هر کوئری SQL (SELECT, INSERT, UPDATE, DELETE)
- Execute Query with Parameters: اجرای کوئری با پارامترهای ایمن (جلوگیری از SQL Injection)
- Insert Rows: درج ردیفها از دادههای workflow
- Transaction Support: اجرای چندین کوئری در یک تراکنش
موارد استفاده مناسب:
- ذخیره state بین اجراها (مثلاً آخرین ID پردازش شده)
- Cache نتایج API
- Log فعالیتها و خطاها
- ذخیره تنظیمات workflow
- پروژههای کوچک با کمتر از ۱ میلیون رکورد
- Prototype و تست قبل از مهاجرت به PostgreSQL
چه زمانی از SQLite استفاده نکنید:
- ❌ چندین workflow همزمان روی یک فایل بنویسند (concurrent writes)
- ❌ دیتابیس بزرگتر از ۱ گیگابایت
- ❌ نیاز به دسترسی شبکهای از چندین سرور
احراز هویت
تنظیم اتصال SQLite
مسیر فایل دیتابیس
SQLite نیاز به احراز هویت ندارد. فقط مسیر فایل .db را مشخص کنید:
در n8n credentials:
- Database File Path: مسیر فایل دیتابیس
مثالهای مسیر:
# Linux/Mac
/home/n8n/data/mydb.sqlite
# Windows
C:\Users\user\data\mydb.sqlite
# مسیر نسبی (از ریشه n8n)
./data/workflow-data.db
# در Docker
/data/mydb.sqliteایجاد دیتابیس جدید:
اگر فایل وجود نداشته باشد، SQLite خودکار آن را ایجاد میکند. فقط مسیر معتبر بدهید.
دسترسی فایل:
- n8n باید دسترسی read/write به فایل و پوشه والد داشته باشد
- در Docker، مسیر باید به volume mount شده باشد
- فایل SQLite باید روی local filesystem باشد (نه network drive)
تنظیم Docker Volume:
docker run -d \
-v /host/path/data:/data \
-e DATABASE_URL="file:/data/n8n.db" \
n8nio/n8nWAL Mode (توصیه شده):
برای performance بهتر، WAL mode را فعال کنید:
PRAGMA journal_mode=WAL;
PRAGMA synchronous=NORMAL;عملیاتهای موجود
executeQuery
اجرای هر کوئری SQL دلخواه
executeQueryWithParams
اجرای کوئری با پارامترهای ایمن (ضد SQL Injection)
insert
درج دادهها در جدول (از فیلدهای workflow)
update
ویرایش ردیفهای موجود
select
خواندن دادهها از جدول
createTable
ایجاد جدول جدید با ستونها
کاربردهای متداول
کاربردهای رایج
۱. ذخیره State بین اجراها
آخرین ID پردازش شده را ذخیره کنید تا از پردازش تکراری جلوگیری شود.
-- ذخیره آخرین ID
INSERT OR REPLACE INTO state (key, value) VALUES ('last_processed_id', '12345');
-- خواندن آخرین ID
SELECT value FROM state WHERE key = 'last_processed_id';Schedule → SQLite (آخرین ID) → API (فقط رکوردهای جدید) → پردازش → SQLite (update ID)۲. Cache نتایج API
نتایج APIهای کُند یا rate-limited را cache کنید.
CREATE TABLE IF NOT EXISTS api_cache (
url TEXT PRIMARY KEY,
response TEXT,
cached_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
-- بررسی cache (کمتر از ۱ ساعت)
SELECT response FROM api_cache
WHERE url = ? AND cached_at > datetime('now', '-1 hour');۳. Activity Log
ثبت فعالیتها و خطاها برای monitoring و debug.
CREATE TABLE IF NOT EXISTS activity_log (
id INTEGER PRIMARY KEY AUTOINCREMENT,
workflow TEXT,
action TEXT,
details TEXT,
status TEXT,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);Workflow → ... → SQLite (INSERT log) → ... → Error Trigger → SQLite (INSERT error log)۴. Deduplication (جلوگیری از تکرار)
از پردازش تکراری ایمیلها، پیامها یا سفارشها جلوگیری کنید.
-- بررسی تکراری بودن
SELECT COUNT(*) as cnt FROM processed WHERE message_id = ?;
-- ثبت پردازش شده
INSERT INTO processed (message_id, processed_at) VALUES (?, datetime('now'));۵. Queue System ساده
یک صف (queue) ساده برای پردازش تأخیری تسکها بسازید.
-- اضافه به صف
INSERT INTO job_queue (payload, status) VALUES (?, 'pending');
-- دریافت تسک بعدی
SELECT * FROM job_queue WHERE status = 'pending' ORDER BY id LIMIT 1;
-- ثبت انجام شده
UPDATE job_queue SET status = 'done', completed_at = datetime('now') WHERE id = ?;۶. ذخیره تنظیمات Workflow
تنظیمات داینامیک workflow را در دیتابیس ذخیره کنید بجای hardcode.
CREATE TABLE IF NOT EXISTS config (
key TEXT PRIMARY KEY,
value TEXT,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
INSERT OR REPLACE INTO config VALUES ('email_recipients', 'admin@example.com', datetime('now'));۷. Rate Limiting
محدود کردن تعداد درخواستها به یک API در بازه زمانی مشخص.
-- بررسی تعداد درخواست در ساعت اخیر
SELECT COUNT(*) as cnt FROM api_calls
WHERE api_name = ? AND called_at > datetime('now', '-1 hour');
-- ثبت درخواست
INSERT INTO api_calls (api_name, called_at) VALUES (?, datetime('now'));۸. Data Aggregation
جمعآوری و تجمیع دادهها از منابع مختلف و ذخیره برای گزارش.
INSERT INTO daily_stats (date, total_orders, revenue)
VALUES (date('now'), ?, ?);
SELECT date, total_orders, revenue FROM daily_stats
WHERE date >= date('now', '-30 days') ORDER BY date;۹. Lookup Table
ذخیره mappingها و ترجمهها برای استفاده در workflow.
-- جدول mapping
CREATE TABLE IF NOT EXISTS city_codes (
code TEXT PRIMARY KEY,
name_fa TEXT,
name_en TEXT,
province TEXT
);
-- Lookup سریع
SELECT name_fa, province FROM city_codes WHERE code = ?;۱۰. Session Management
ذخیره و مدیریت sessionهای کاربران در workflowهای چتبات.
INSERT OR REPLACE INTO chat_sessions (user_id, context, last_message, updated_at)
VALUES (?, ?, ?, datetime('now'));نکات حرفهای
نکات حرفهای
۱. همیشه از CREATE TABLE IF NOT EXISTS استفاده کنید
اولین بار که workflow اجرا میشود، جدول خودکار ساخته شود:
CREATE TABLE IF NOT EXISTS my_data (
id INTEGER PRIMARY KEY AUTOINCREMENT,
key TEXT UNIQUE,
value TEXT,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);۲. WAL Mode را فعال کنید
Write-Ahead Logging عملکرد را تا ۵ برابر بهبود میدهد:
PRAGMA journal_mode=WAL;
PRAGMA synchronous=NORMAL;۳. از Parameterized Queries استفاده کنید
هرگز مقادیر را مستقیم در کوئری concat نکنید. از ? و پارامتر استفاده کنید.
۴. Index بسازید
برای ستونهایی که زیاد جستجو میشوند:
CREATE INDEX IF NOT EXISTS idx_email ON users(email);
CREATE INDEX IF NOT EXISTS idx_created ON logs(created_at);۵. INSERT OR REPLACE برای Upsert
INSERT OR REPLACE INTO config (key, value) VALUES ('setting', 'value');۶. Datetime Functions
SQLite توابع تاریخ/زمان مفیدی دارد:
-- زمان فعلی
datetime('now')
-- ۳۰ دقیقه قبل
datetime('now', '-30 minutes')
-- ۷ روز آینده
date('now', '+7 days')
-- فقط تاریخ
date('now')۷. JSON Support
SQLite از JSON پشتیبانی میکند:
SELECT json_extract(data, '$.name') as name FROM records;
INSERT INTO records (data) VALUES (json('{"name":"علی","age":30}'));۸. Cleanup قدیمیها
به صورت دورهای دادههای قدیمی را پاک کنید:
DELETE FROM logs WHERE created_at < datetime('now', '-30 days');
DELETE FROM api_cache WHERE cached_at < datetime('now', '-1 hour');۹. Backup Strategy
فایل SQLite را به صورت دورهای کپی کنید. در حین نوشتن کپی نکنید - از .backup command استفاده کنید.
۱۰. Transaction برای عملیات چندگانه
BEGIN TRANSACTION;
INSERT INTO orders (...) VALUES (...);
UPDATE inventory SET stock = stock - 1 WHERE id = ?;
COMMIT;۱۱. VACUUM برای بهینهسازی
بعد از حذف تعداد زیادی ردیف، فایل را بهینه کنید:
VACUUM;۱۲. حداکثر سایز
SQLite تا ۲۸۱ ترابایت را پشتیبانی میکند، اما برای بهترین عملکرد فایل زیر ۱ گیگابایت نگه دارید.
۱۳. Read-Only Mode
برای workflowهایی که فقط SELECT میکنند، از ?mode=ro در connection string استفاده کنید.
۱۴. COALESCE برای مقادیر پیشفرض
SELECT COALESCE(value, 'default') FROM config WHERE key = ?;۱۵. از SQLite برای State Machine استفاده کنید
workflowهای پیچیده را با ذخیره state در SQLite مدیریت کنید. state بین restartها حفظ میشود.
رفع مشکلات
رفع مشکلات رایج
❌ خطای "SQLITE_BUSY: database is locked"
علت: چندین عملیات نوشتن همزمان روی دیتابیس
راهحل
- WAL mode را فعال کنید:
PRAGMA journal_mode=WAL; - از
PRAGMA busy_timeout=5000;استفاده کنید - عملیات نوشتن را serialize کنید (نه parallel)
- از دو workflow همزمان روی یک فایل ننویسید
❌ خطای "no such table"
علت: جدول وجود ندارد
راهحل
- ابتدا جدول را بسازید:
CREATE TABLE IF NOT EXISTS ... - مسیر فایل دیتابیس را بررسی کنید (شاید به فایل اشتباهی وصل شده)
- نام جدول case-sensitive است
❌ خطای "SQLITE_READONLY"
علت: n8n دسترسی نوشتن به فایل ندارد
راهحل
- دسترسی فایل را بررسی کنید:
chmod 666 mydb.sqlite - پوشه والد هم باید writable باشد
- در Docker، مطمئن شوید volume mount صحیح است
- فایل روی read-only filesystem نباشد
❌ خطای "disk I/O error"
علت: مشکل در دسترسی به فایل
راهحل
- فضای دیسک کافی باشد
- فایل روی network drive (NFS, SMB) نباشد
- فایلهای WAL و SHM کنار فایل اصلی باشند
- دیسک سالم باشد
❌ خروجی خالی از SELECT
علت: دادهای مطابق شرط وجود ندارد
راهحل
- کوئری را بدون WHERE تست کنید
- مقادیر پارامترها را بررسی کنید
- نام ستونها را exact بررسی کنید
❌ خطای SQL Injection
علت: استفاده مستقیم از ورودی کاربر در کوئری
راهحل
- همیشه از parameterized queries استفاده کنید:
-- بد ❌
SELECT * FROM users WHERE name = '${name}';
-- خوب ✅
SELECT * FROM users WHERE name = ?;
-- سپس name را به عنوان پارامتر ارسال کنید❌ خطای "SQLITE_CORRUPT"
علت: فایل دیتابیس خراب شده
راهحل
- از backup استفاده کنید
- تلاش برای repair:
sqlite3 corrupt.db ".dump" | sqlite3 new.db - فایلهای WAL و SHM را حذف و restart کنید
❌ Performance ضعیف
علت: کوئریهای بهینه نشده
راهحل
- Index بسازید:
CREATE INDEX idx_name ON table(column); - از
EXPLAIN QUERY PLANاستفاده کنید - WAL mode فعال کنید
- برای SELECTهای بزرگ از LIMIT استفاده کنید
