Node.js: SQLite e Prisma ORM
Última atualização: 2026-08-26
Charlie está desenvolvendo um aplicativo para desktop destinado à criação de anotações que requer armazenamento local de dados, mas ele não quer que os usuários tenham que instalar um serviço MySQL separado. O SQLite é um banco de dados incorporado que não requer configuração, no qual um único arquivo constitui todo o banco de dados; quando combinado com o ORM Prisma, ele oferece segurança de tipos completa para operações SQL.
1. better-sqlite3: Um banco de dados incorporado com uma API síncrona
(1) Por que escolher o better-sqlite3?
Existem várias bibliotecas SQLite no ecossistema do Node.js, e a better-sqlite3 é conhecida por sua API síncrona — ela retorna imediatamente após a invocação, sem a necessidade de await ou callbacks aninhados. Ela compila o SQLite em C++ em nível baixo, resultando em um desempenho que supera em muito o das bibliotecas wrapper assíncronas.
| Recurso | Descrição |
|---|---|
| API de sincronização | Sem o “inferno dos callbacks”, código linear e legível |
| Configuração zero | Não é preciso instalar um serviço de banco de dados — o npm install já está pronto para uso |
| Armazenamento em um único arquivo | Todo o banco de dados é um único arquivo .db |
| Suporte a transações | Transações aninhadas e instruções preparadas — tudo incluído |
| Alto desempenho | Ligações em C++, 2 a 3 vezes mais rápidas que o node-sqlite3 |
| Multiplataforma | Pode ser compilado no Windows, macOS e Linux |
(2) Instalação e conexões básicas
npm init -y
npm install better-sqlite3
const Database = require('better-sqlite3');
const db = new Database('myapp.db');
db.pragma('journal_mode = WAL');
db.pragma('foreign_keys = ON');
console.log('SQLite Version:', db.prepare('SELECT sqlite_version()').get());
(3) Guia de referência rápida aos métodos mais comuns
| Método | Objetivo | Exemplo |
|---|---|---|
db.prepare(sql) |
Criar uma instrução pré-compilada | const stmt = db.prepare('SELECT * FROM users WHERE id = ?') |
stmt.run(...params) |
Executar INSERT/UPDATE/DELETE | stmt.run(1, 'Charlie') |
stmt.get(...params) |
Voltar ao objeto de linha única | stmt.get(1) |
stmt.all(...params) |
Retorna a matriz com todas as linhas | stmt.all() |
stmt.values(...params) |
Matriz de valores de retorno (sem nomes de chaves) | stmt.values() |
db.exec(sql) |
Executar várias instruções SQL | db.exec(schemaSql) |
db.transaction(fn) |
Criar função de transação | const insertMany = db.transaction((items) => {...}) |
db.pragma(cmd) |
Definir/Consultar PRAGMA | db.pragma('journal_mode = WAL') |
▶ Exemplo: Fluxo de trabalho CRUD completo com o better-sqlite3
const Database = require('better-sqlite3');
const db = new Database('notes.db');
db.exec(`
CREATE TABLE IF NOT EXISTS notes (
id INTEGER PRIMARY KEY AUTOINCREMENT,
title TEXT NOT NULL,
body TEXT DEFAULT '',
created_at TEXT DEFAULT (datetime('now'))
)
`);
const insert = db.prepare('INSERT INTO notes (title, body) VALUES (?, ?)');
const result = insert.run('First Note', 'Hello SQLite!');
console.log('Insert a row ID:', result.lastInsertRowid);
const find = db.prepare('SELECT * FROM notes WHERE id = ?');
console.log('Search Results:', find.get(1));
const update = db.prepare('UPDATE notes SET title = ? WHERE id = ?');
update.run('Revised Title', 1);
const remove = db.prepare('DELETE FROM notes WHERE id = ?');
remove.run(1);
const listAll = db.prepare('SELECT * FROM notes ORDER BY created_at DESC');
console.log('All Notes:', listAll.all());
db.close();
(4) Uso transacional
const insertMany = db.transaction((notes) => {
for (const n of notes) {
insert.run(n.title, n.body);
}
});
insertMany([
{ title: 'Notes A', body: 'Content A' },
{ title: 'Notes B', body: 'Content B' },
]);
2. Revisão dos conceitos básicos das instruções SQL
(1) As quatro operações principais: CRUD
| Operação | SQL | Palavra-chave |
|---|---|---|
| Criar | INSERIR | INSERT INTO table (col) VALUES (val) |
| Ler | SELECT | SELECT col FROM table WHERE cond |
| Atualização | ATUALIZAÇÃO | UPDATE table SET col=val WHERE cond |
| Excluir | EXCLUIR | DELETE FROM table WHERE cond |
(2) Cláusulas comuns de consulta
SELECT Listed
FROM Table Name
WHERE Conditions
GROUP BY Grouping Column
HAVING Grouping Criteria
ORDER BY Sorted List ASC|DESC
LIMIT Quantity OFFSET offset
(3) Consultas com junção
db.exec(`
CREATE TABLE IF NOT EXISTS authors (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL
)
`);
db.exec(`
CREATE TABLE IF NOT EXISTS books (
id INTEGER PRIMARY KEY AUTOINCREMENT,
title TEXT NOT NULL,
author_id INTEGER REFERENCES authors(id)
)
`);
const joinQuery = db.prepare(`
SELECT books.title, authors.name AS author
FROM books
JOIN authors ON books.author_id = authors.id
`);
3. Instalação e inicialização do Prisma
(1) O que é o Prisma?
O Prisma é um ORM de última geração para Node.js/TypeScript. Seu fluxo de trabalho principal é o seguinte:
flowchart LR
A["schema.prisma"] -->|"prisma migrate dev"| B["Migration SQL"]
A -->|"prisma generate"| C["Prisma Client"]
C -->|"Type-Safe Queries"| D[("Database")]
B --> D
- schema.prisma: Definição declarativa de modelos de dados
- Prisma Migrate: Gera e executa automaticamente o código SQL de migração
- Prisma Client: Um cliente de consulta gerado automaticamente e com segurança de tipos
(2) Inicialização do projeto
mkdir prisma-notes && cd prisma-notes
npm init -y
npm install prisma --save-dev
npm install @prisma/クライアント
npx prisma init --datasource-provider sqlite
Gerado após a inicialização:
prisma-notes/
├── prisma/
│ └── schema.prisma
├── .env
└── package.json
.env Conteúdo do arquivo:
DATABASE_URL="file:./dev.db"
(3) Referência rápida do Prisma Command
| Comando | Finalidade |
|---|---|
npx prisma init |
Inicializando um projeto Prisma |
npx prisma migrate dev |
Criar e aplicar uma migração de desenvolvimento |
npx prisma migrate deploy |
Migração de aplicativos no ambiente de produção |
npx prisma generate |
Gerar o cliente Prisma |
npx prisma studio |
Abrir a interface de gerenciamento visual |
npx prisma db push |
Enviar o esquema diretamente durante a fase de protótipo (sem gerar arquivos de migração) |
npx prisma db seed |
Executar o script de dados iniciais |
4. schema.prisma: Definindo o modelo
(1) Estrutura básica
// prisma/schema.prisma
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "sqlite"
url = env("DATABASE_URL")
}
model Note {
id Int @id @default(autoincrement())
title String
body String @default("")
pinned Boolean @default(false)
tags String @default("")
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
(2) Referência rápida aos tipos de campo
| Tipo de Prisma | Mapeamento para SQLite | Descrição |
|---|---|---|
String |
TEXTO | string |
Int |
INTEGER | inteiro de 32 bits |
BigInt |
INTEGER | inteiro de 64 bits |
Float |
REAL | Número de ponto flutuante |
Boolean |
INTEGER | 0 ou 1 |
DateTime |
TEXTO | sequência ISO 8601 |
Json |
TEXTO | string JSON |
Bytes |
BLOB | Dados binários |
Decimal |
TEXTO | Decimais de alta precisão |
Observação: O sistema de tipos do SQLite difere do do PostgreSQL; o Prisma se encarrega da adaptação subjacente. Ao mudar para
provider, os mapeamentos de tipos de campo serão ajustados automaticamente.
(3) Propriedades e modificadores
| Modificador | Finalidade | Exemplo |
|---|---|---|
@id |
chave primária | id Int @id |
@default |
Valor padrão | @default(autoincrement()) / @default(now()) / @default("active") |
@unique |
Restrição exclusiva | email String @unique |
@relation |
Definição de relação | @relation(fields: [authorId], references: [id]) |
@map / @@map |
Mapeamento de nomes de colunas/tabelas | @map("created_at") |
@@unique |
Único composto | @@unique([firstName, lastName]) |
@@index |
Índice Composto | @@index([categoryId, createdAt]) |
? |
Campo opcional | bio String? |
(4) Definições de relações
model User {
id Int @id @default(autoincrement())
email String @unique
name String
notes Note[]
}
model Note {
id Int @id @default(autoincrement())
title String
body String @default("")
authorId Int
author User @relation(fields: [authorId], references: [id], onDelete: Cascade)
}
▶ Exemplo: Definindo Relacionamentos Multimodelo
// prisma/schema.prisma — relacionamentos entre User, Note e Tag
model User {
id Int @id @default(autoincrement())
email String @unique
name String
notes Note[]
createdAt DateTime @default(now())
}
model Note {
id Int @id @default(autoincrement())
title String
body String @default("")
published Boolean @default(false)
authorId Int
author User @relation(fields: [authorId], references: [id], onDelete: Cascade)
tags NoteTag[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
model Tag {
id Int @id @default(autoincrement())
name String @unique
notes NoteTag[]
}
model NoteTag {
noteId Int
tagId Int
note Note @relation(fields: [noteId], references: [id], onDelete: Cascade)
tag Tag @relation(fields: [tagId], references: [id], onDelete: Cascade)
@@id([noteId, tagId])
@@index([tagId])
}
Este exemplo define três modelos com dois tipos de relacionamentos:
- User → Note: um-para-muitos, exclusão em cascata
- Note ↔ Tag: muitos-para-muitos via tabela de junção
NoteTag, usando chave primária composta@@ide índice@@index
5. Migração com o Prisma Migrate
(1) Criar e aplicar uma migração
npx prisma migrate dev --name init
Após a execução:
prisma/
├── schema.prisma
└── migrations/
└── 20260703_init/
└── migration.sql
Gerado migration.sql:
CREATE TABLE "Note" (
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
"title" TEXT NOT NULL,
"body" TEXT NOT NULL DEFAULT '',
"pinned" BOOLEAN NOT NULL DEFAULT false,
"tags" TEXT NOT NULL DEFAULT '',
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" DATETIME NOT NULL
);
(2) Fluxo de trabalho de migração
Development Phase: schema Edit → npx prisma migrate dev --name Description
Testing Phase: npx prisma migrate deploy(App Only,Do not create a new migration)
Prototyping Phase: npx prisma db push(Skip migrating files,Rapid Iteration)
Reset Data: npx prisma migrate reset(Clear the database and replay all migrations)
(3) Implantação em produção
npx prisma migrate deploy
migrate deployExecuta apenas migrações não aplicadas; não cria novas migrações nem reinicializa dados — ideal para pipelines de CI/CD.
6. CRUD do Prisma Client
(1) Inicializar o cliente
const { PrismaClient } = require('@prisma/client');
const prisma = new PrismaClient();
async function main() {
// CRUD Instructions are written here
}
main()
.catch(console.error)
.finally(() => prisma.$disconnect());
(2) Criar — Criar
const note = await prisma.note.create({
data: {
title: 'Study Prisma',
body: 'Prisma Making Database Operations Type-Safe',
pinned: true,
},
});
const notes = await prisma.note.createMany({
data: [
{ title: 'Notes A', body: 'Content A' },
{ title: 'Notes B', body: 'Content B', pinned: true },
],
});
(3) Ler — Consulta
const one = await prisma.note.findUnique({ where: { id: 1 } });
const first = await prisma.note.findFirst({
where: { pinned: true },
orderBy: { createdAt: 'desc' },
});
const all = await prisma.note.findMany();
const filtered = await prisma.note.findMany({
where: {
pinned: true,
title: { contains: 'Prisma' },
},
});
(4) Atualização — Atualização
const updated = await prisma.note.update({
where: { id: 1 },
data: { title: 'Updated Title', pinned: false },
});
const count = await prisma.note.updateMany({
where: { pinned: false },
data: { tags: 'archived' },
});
(5) Excluir — Excluir
const deleted = await prisma.note.delete({ where: { id: 1 } });
const deleteCount = await prisma.note.deleteMany({
where: { pinned: false },
});
(6) Lista de filtros de consulta
| Filtro | Significado | Exemplo |
|---|---|---|
equals |
é igual a | { title: { equals: 'Hello' } } |
not |
não é igual a | { id: { not: 1 } } |
contains |
incluir | { title: { contains: 'Prisma' } } |
startsWith |
Prefixo | { title: { startsWith: 'Learn' } } |
endsWith |
sufixo | { email: { endsWith: '@test.com' } } |
in |
Na lista | { id: { in: [1, 2, 3] } } |
notIn |
Não consta na lista | { id: { notIn: [4, 5] } } |
lt / lte |
Menor que / Menor ou igual a | { id: { lte: 10 } } |
gt / gte |
Maior que / Maior ou igual a | { id: { gte: 5 } } |
AND |
E | { AND: [{ pinned: true }, { title: { contains: 'A' } }] } |
OR |
ou | { OR: [{ pinned: true }, { pinned: false }] } |
NOT |
Não | { NOT: { title: 'Hello' } } |
▶ Exemplo: Incluindo Dados Relacionados e Filtragem
const { PrismaClient } = require('@prisma/client');
const prisma = new PrismaClient();
async function queryNotes() {
// Buscar notas publicadas com autor e tags
const notes = await prisma.note.findMany({
where: {
published: true,
title: { contains: 'Prisma' },
},
include: {
author: {
select: { id: true, name: true, email: true },
},
tags: {
include: {
tag: { select: { id: true, name: true } },
},
},
},
orderBy: { createdAt: 'desc' },
take: 10,
});
console.log(`Encontradas ${notes.length} notas`);
for (const note of notes) {
const tagNames = note.tags.map((nt) => nt.tag.name).join(', ');
console.log(`${note.title} — ${note.author.name} [${tagNames}]`);
}
}
queryNotes()
.catch(console.error)
.finally(() => prisma.$disconnect());
Este exemplo usa include para carregar antecipadamente os author e tags relacionados, e select para limitar os campos apenas ao necessário. O resultado inclui dados aninhados sem consultas adicionais.
7. Ordenação e paginação
(1) Classificação
const sorted = await prisma.note.findMany({
orderBy: [
{ pinned: 'desc' },
{ createdAt: 'desc' },
],
});
(2) Paginação
const PAGE_SIZE = 10;
const page1 = await prisma.note.findMany({
skip: 0,
take: PAGE_SIZE,
orderBy: { createdAt: 'desc' },
});
const page2 = await prisma.note.findMany({
skip: PAGE_SIZE,
take: PAGE_SIZE,
orderBy: { createdAt: 'desc' },
});
(3) Paginação baseada no cursor (recomendada para conjuntos de dados grandes)
const first = await prisma.note.findMany({
take: 10,
orderBy: { id: 'asc' },
});
const cursor = first[first.length - 1].id;
const next = await prisma.note.findMany({
take: 10,
skip: 1,
cursor: { id: cursor },
orderBy: { id: 'asc' },
});
▶ Exemplo: Pesquisa e Paginação por Cursor
const { PrismaClient } = require('@prisma/client');
const prisma = new PrismaClient();
async function searchNotes(searchTerm, cursorId = null) {
const PAGE_SIZE = 5;
const results = await prisma.note.findMany({
take: PAGE_SIZE + 1,
skip: cursorId ? 1 : 0,
cursor: cursorId ? { id: cursorId } : undefined,
where: {
OR: [
{ title: { contains: searchTerm } },
{ body: { contains: searchTerm } },
],
},
include: { author: { select: { name: true } } },
orderBy: { id: 'asc' },
});
const hasMore = results.length > PAGE_SIZE;
if (hasMore) results.pop();
return {
items: results,
nextCursor: hasMore ? results[results.length - 1].id : null,
hasMore,
};
}
async function main() {
let cursor = null;
for (let page = 1; page <= 3; page++) {
const { items, nextCursor, hasMore } = await searchNotes('Prisma', cursor);
console.log(`Página ${page}: ${items.length} resultados`);
items.forEach((n) => console.log(` ${n.id}: ${n.title}`));
if (!hasMore) break;
cursor = nextCursor;
}
}
main()
.catch(console.error)
.finally(() => prisma.$disconnect());
Combina pesquisa de texto completo nos campos title e body com paginação baseada em cursor. Busca um registro extra para determinar se existe uma próxima página e o remove antes de retornar.
8. Comparação na seleção de bancos de dados
(1) SQLite x MySQL x PostgreSQL x MongoDB
| Dimensão | SQLite | MySQL | PostgreSQL | MongoDB |
|---|---|---|---|---|
| Tipo | Incorporado | Cliente-servidor | Cliente-servidor | Baseado em documentos |
| Instalação | Não requer instalação (incluído no pacote npm) | Requer a instalação de um serviço | Requer a instalação de um serviço | Requer a instalação de um serviço |
| Gravações simultâneas | Um gravador | Vários gravadores | Vários gravadores | Vários gravadores |
| Tamanho dos dados | Pequeno a médio (escala de GB) | Grande (escala de TB) | Grande (escala de TB) | Grande (escala de TB) |
| Casos de uso | Aplicativos de desktop / Protótipos / Testes | Aplicativos web / Projetos de médio porte | Consultas complexas / Dados geoespaciais | Esquema flexível / Registros |
| Suporte a JSON | Limitado (extensões JSON-1) | Compatível | JSONB nativo | Documentação nativa |
| Pesquisa de texto completo | Extensão FTS5 | Índice de texto completo | tsvector | Índice de texto |
| Transações | ACID completo | ACID completo | ACID completo | Transações com múltiplos documentos (4.0+) |
| Licença | Domínio Público | GPL / Comercial | PostgreSQL | SSPL |
(2) Comparação de estruturas de ORM
| Dimensão | Mongoose | Prisma | Sequelize | TypeORM |
|---|---|---|---|---|
| Idioma | JavaScript | TypeScript (preferencial) | JavaScript | TypeScript (preferencial) |
| Banco de dados | Apenas MongoDB | SQLite/MySQL/PostgreSQL/MongoDB | MySQL/PostgreSQL/SQLite/MSSQL | MySQL/PostgreSQL/SQLite/MSSQL |
| Definição de esquema | Objeto JS | .prisma Arquivo declarativo |
Definição de modelo JS | Classe decoradora / entidade |
| Segurança de tipos | Fraca (manual) | Forte (gerada automaticamente) | Fraca | Média (tipos decoradores) |
| Ferramenta de migração | Não integrada | prisma migrate |
sequelize-cli |
Integrada |
| Método de consulta | API encadeada | Objeto encadeado | SQL encadeado / nativo | QueryBuilder / nativo |
| Problema N+1 | Precisa ser preenchido | Inclui automaticamente | Precisa de preenchimento antecipado/pós-carregamento | Precisa de relações |
| Tamanho da comunidade | Grande | Em rápido crescimento | Grande | Grande |
| Projetos adequados | Projetos com MongoDB | TypeScript full-stack | Node.js tradicional | Ecossistema NestJS |
9. Exemplo abrangente: Camada de dados de gerenciamento de notas
Crie uma camada de dados CRUD completa para gerenciamento de notas usando o Prisma e o SQLite.
▶ Exemplo: Prisma + Gerenciamento de notas com SQLite
Etapa 1 — Definição do esquema
// prisma/schema.prisma
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "sqlite"
url = env("DATABASE_URL")
}
model Note {
id Int @id @default(autoincrement())
title String
body String @default("")
pinned Boolean @default(false)
tags String @default("")
createdAt DateTime @default(now()) @map("created_at")
updatedAt DateTime @updatedAt @map("updated_at")
@@map("notes")
}
Etapa 2 — Migração
npx prisma migrate dev --name notes_init
Etapa 3 — Camada de acesso aos dados
const { PrismaClient } = require('@prisma/client');
const prisma = new PrismaClient();
async function createNote(data) {
return prisma.note.create({ data });
}
async function getNoteById(id) {
return prisma.note.findUnique({ where: { id } });
}
async function updateNote(id, data) {
return prisma.note.update({ where: { id }, data });
}
async function deleteNote(id) {
return prisma.note.delete({ where: { id } });
}
async function listNotes({ page = 1, pageSize = 10, pinned, keyword } = {}) {
const where = {};
if (pinned !== undefined) where.pinned = pinned;
if (keyword) where.title = { contains: keyword };
const [items, total] = await Promise.all([
prisma.note.findMany({
where,
orderBy: [{ pinned: 'desc' }, { createdAt: 'desc' }],
skip: (page - 1) * pageSize,
take: pageSize,
}),
prisma.note.count({ where }),
]);
return { items, total, page, pageSize, totalPages: Math.ceil(total / pageSize) };
}
async function togglePin(id) {
const note = await prisma.note.findUnique({ where: { id } });
if (!note) throw new Error('The note does not exist.');
return prisma.note.update({
where: { id },
data: { pinned: !note.pinned },
});
}
module.exports = {
createNote,
getNoteById,
updateNote,
deleteNote,
listNotes,
togglePin,
};
Etapa 4 — Exemplo de uso
const db = require('./note-service');
async function main() {
const n1 = await db.createNote({ title: 'Study Prisma', body: 'Type Safety ORM', pinned: true });
const n2 = await db.createNote({ title: 'SQLite Key Points', body: 'Zero-Configuration Embedded Database' });
const n3 = await db.createNote({ title: 'Prisma Migration', body: 'migrate dev Driver' });
console.log('Single-Record Query:', await db.getNoteById(n1.id));
await db.updateNote(n2.id, { body: 'What's New' });
await db.togglePin(n3.id);
const result = await db.listNotes({ page: 1, pageSize: 10, keyword: 'Prisma' });
console.log('Search Results:', result);
await db.deleteNote(n2.id);
const all = await db.listNotes({ page: 1, pageSize: 10 });
console.log('Remaining Notes:', all);
}
main()
.catch(console.error)
.finally(() => require('@prisma/client').PrismaClient &&
require('./node_modules/.prisma/client').$disconnect?.());
Executar:
node index.js
Etapa 5 — Gestão visual
npx prisma studio
Abra http://localhost:5555 no seu navegador para visualizar e editar os dados de forma interativa.
10. Resumo desta aula
- O SQLite é um banco de dados incorporado que não requer configuração; o
better-sqlite3oferece uma API de sincronização de alto desempenho - O Prisma usa
schema.prismapara definir modelos de forma declarativa, gerando automaticamente migrações e clientes com segurança de tipos prisma migrate devpara desenvolvimento e migração de drivers;prisma migrate deploypara implantação em produção- O Prisma Client oferece suporte a
findMany,create,update,deletee uma ampla variedade de opções de filtragem, classificação e paginação - Seleção do banco de dados: escolha o SQLite para aplicativos de desktop/protótipos; escolha o MySQL ou o PostgreSQL para aplicativos web; escolha o MongoDB para esquemas flexíveis
- Choosing an ORM: Use Mongoose with MongoDB, Prisma for full-stack TypeScript, and TypeORM with NestJS
❓ Perguntas Frequentes
defineModel. Prisma offers better type safety, while Sequelize has a more mature ecosystem.- P: O SQLite oferece suporte à concorrência? R: Ele oferece suporte a várias leituras e uma única gravação; no modo WAL, as leituras podem ser realizadas simultaneamente, mas as gravações continuam sendo serializadas. Para cenários de gravação com alta concorrência, é recomendável mudar para o MySQL ou o PostgreSQL.
- P: O que é melhor, Prisma ou Sequelize? R: O Prisma oferece maior segurança de tipos, uma experiência de migração melhor e consultas livres de problemas do tipo N+1; o Sequelize possui um ecossistema mais maduro e oferece suporte a mais dialetos de banco de dados. Recomendamos o Prisma para novos projetos.
- P: Por que o better-sqlite3 é síncrono? R: O SQLite em si é uma biblioteca dentro do processo, e as operações de E/S levam apenas microssegundos; o uso de operações assíncronas acabaria aumentando a sobrecarga do ciclo de eventos. A API síncrona elimina callbacks aninhados, resultando em um código mais limpo.
- P: Qual é o tamanho máximo de um banco de dados SQLite? R: O limite teórico é de 281 TB, mas, na prática, ele está sujeito ao limite de tamanho de um único arquivo do sistema operacional; em cenários comuns, bancos de dados de várias dezenas de GB não representam nenhum problema.
- P: Quando se deve migrar do SQLite para o PostgreSQL? R: Você deve migrar quando precisar de gravações simultâneas em vários processos, consultas JSONB nativas, pesquisa de texto completo, dados geoespaciais, políticas de segurança no nível da linha ou quando exceder a capacidade de armazenamento de uma única máquina.
- P: O Prisma é compatível com o MongoDB? R: A versão 2.0 e as versões posteriores são compatíveis com o MongoDB, mas o conjunto de recursos não é tão abrangente quanto o oferecido para bancos de dados relacionais; para agregações complexas, recomendamos o uso do Mongoose.
- Q: How should Prisma Client instances be managed in a production environment? A: Use a global singleton to avoid creating a new instance with every request; in hot-reload environments such as Next.js, use
globalThiscaching to prevent connection leaks.
📖 Resumo
- 1 better-sqlite3: Conceitos básicos e uso da API síncrona para bancos de dados incorporados
- 2 Conceitos-chave e uso das instruções SQL: uma revisão dos fundamentos
- 3 Conceitos-chave e uso da instalação e inicialização do Prisma
- 4 schema.prisma: Definição dos conceitos fundamentais e uso do modelo
- 5 Conceitos fundamentais e uso do Prisma Migrate
- 6 Conceitos básicos e uso do CRUD do Prisma Client
- 7 Conceitos fundamentais e uso da ordenação e da paginação
- 8 conceitos e métodos fundamentais para comparar e selecionar bancos de dados
📝 Exercícios
- Use
better-sqlite3para criar uma tabelausers, implemente operações de inserção, consulta por e-mail, atualização e exclusão, e utilize transações para garantir a atomicidade. - Inicialize um projeto Prisma, defina dois modelos —
UserePost(uma relação um-para-muitos) — e, após executar as migrações, use o Prisma Client para criar usuários, publicar artigos e consultar usuários e todos os seus artigos. - Com base no exemplo de gerenciamento de notas, adicione o modelo
Categorypara permitir a filtragem de notas por categoria e inclua suporte à filtragem por ID de categoria nolistNotes. - Compare a implementação do mesmo conjunto de operações CRUD usando o SQL nativo
better-sqlite3e o Prisma Client, observando as diferenças no número de linhas e na legibilidade. - Escreva um script usando
prisma.note.findManypara implementar a pesquisa por palavra-chave, priorizar os principais resultados e a paginação, e compare as diferenças de desempenho entre a paginação por deslocamento e a paginação por cursor ao processar 10.000 registros.