21 de dez. de 2024·8 min de leitura

Restrições de banco de dados para validação de formulários em apps sem código

Use restrições de banco de dados para validação de formulários: bloqueie dados ruins cedo, mostre erros claros e mantenha apps sem código consistentes entre equipes.

Restrições de banco de dados para validação de formulários em apps sem código

Por que dados ruins em formulários se espalham tão rápido

Dados ruins raramente ficam em um só lugar. Um valor errado digitado em um formulário pode ser copiado, referenciado e confiado por todas as partes do app que o utilizam.

Geralmente começa pequeno: alguém digita um email com um espaço no final, seleciona o cliente errado ou insere uma quantidade negativa porque o campo permite. O formulário aceita, então o sistema trata aquilo como válido.

A partir daí, a propagação é rápida. Relatórios mostram totais errados, automações rodam sobre registros incorretos e mensagens ao cliente puxam campos bagunçados e parecem pouco profissionais. Equipes então criam soluções paliativas como planilhas privadas, o que aumenta ainda mais as divergências. Pior ainda: o mesmo valor ruim costuma voltar depois porque aparece como opção ou é copiado para novos registros.

Corrigir dados depois é lento e arriscado porque limpeza raramente é um único ajuste. É preciso achar todos os lugares por onde o valor passou, atualizar registros relacionados e checar novamente tudo que depende dele. Uma correção “simples” pode quebrar fluxos, disparar notificações duplicadas ou embaçar o histórico de auditoria.

O objetivo das restrições de banco de dados para validação de formulários é interromper essa reação em cadeia na primeira etapa. Quando o banco de dados recusa dados impossíveis ou inconsistentes, você evita falhas silenciosas e tem um momento claro para mostrar um feedback útil na UI.

Imagine um formulário interno de pedido construído em uma ferramenta no-code como AppMaster. Se um pedido for salvo com o link do cliente ausente ou com um número de pedido duplicado, isso pode contaminar faturas, tarefas de envio e relatórios de receita. Capturar no momento do envio mantém tudo a jusante limpo e evita limpezas dolorosas depois.

Restrições de banco de dados, explicadas sem jargão

Restrições de banco de dados são regras simples que vivem no banco. Elas rodam sempre que dados são salvos, não importa de onde venham: um formulário web, uma tela mobile, uma importação ou uma chamada de API. Se uma regra é violada, o banco recusa o salvamento.

Essa é a grande diferença em relação à validação apenas na UI. Um formulário pode checar campos antes de você clicar em salvar, mas essas checagens são fáceis de perder ou contornar. Outra tela pode esquecer a mesma regra. Uma automação pode escrever diretamente no banco. Logo você tem dados que parecem corretos em um lugar e quebram relatórios em outro.

Quando se fala em restrições de banco de dados para validação de formulários, a ideia é esta: deixe o banco ser o juiz final, e deixe a UI guiar o usuário para que ele raramente chegue a esse limite.

A maioria dos apps reais cobre muito com três básicas:

  • Unique: “Esse valor deve ser único.” Exemplo: email, ID de funcionário, número de fatura.
  • Check: “Essa condição deve ser verdadeira.” Exemplo: quantity > 0, start_date <= end_date.
  • Foreign key: “Isso deve apontar para um registro real em outra tabela.” Exemplo: todo pedido deve referenciar um cliente existente.

As restrições importam ainda mais em apps no-code porque normalmente há mais de uma forma de criar ou atualizar dados. Você pode ter um app web para admins, um app mobile para equipe de campo e processos automatizados escrevendo registros nos bastidores. Restrições mantêm todos esses caminhos consistentes.

Elas também tornam os erros mais claros quando você as projeta intencionalmente. Em vez de deixar dados ruins entrarem e consertá‑los depois, você pode mostrar uma mensagem focada como “Esse número de fatura já existe” ou “Selecione um cliente válido” e manter o banco limpo desde o primeiro dia.

Da restrição para mensagens humanas e claras

Restrições são ótimas para barrar dados ruins, mas erros brutos do banco geralmente são escritos para desenvolvedores, não para quem preenche o formulário. O objetivo é simples: mantenha a regra no banco e então traduza a falha em uma mensagem que explique o que aconteceu e o que fazer em seguida.

Trate cada restrição como um pequeno “contrato de erro” com duas partes: o que está errado e como consertar. Sua UI permanece amigável sem enfraquecer as regras de dados.

Algumas traduções que funcionam bem:

  • Ruim: “Unique constraint violation on users_email_key”

  • Bom: “Este email já está em uso. Tente entrar ou use um email diferente.”

  • Ruim: “Check constraint failed: order_total_positive”

  • Bom: “O total deve ser maior que 0. Adicione ao menos um item ou ajuste a quantidade.”

  • Ruim: “Foreign key violation on customer_id”

  • Bom: “Escolha um cliente válido. Se ele for novo, crie o cliente primeiro.”

Onde você mostra a mensagem importa tanto quanto as palavras. Coloque o erro de campo ao lado do campo. Para regras envolvendo vários campos (como “data de fim deve ser depois da data de início”), um banner no nível do formulário costuma ser mais claro.

Mantenha o conjunto de estilos de mensagem pequeno. Texto inline para a maioria dos problemas, um pequeno banner para regras entre campos e um toast para confirmações curtas (não para correções detalhadas) costuma ser suficiente.

Também mantenha a redação consistente entre web e mobile. Se sua forma web diz “Escolha um cliente válido”, seu app mobile não deve dizer “FK inválida”. Use os mesmos verbos curtos (“Escolha”, “Insira”, “Remova”) e o mesmo tom, para que os usuários aprendam o que esperar.

Se você está construindo no AppMaster, esse mapeamento é algo que você projeta intencionalmente: o banco permanece estrito, enquanto a lógica da UI transforma falhas em orientação calma e específica.

Passo a passo: crie as regras primeiro, depois o formulário

Se você projeta o formulário primeiro, acaba correndo atrás de casos de borda para sempre. Se projeta as regras de dados primeiro, a UI fica mais simples porque reflete regras que já existem no banco.

Uma ordem prática de construção:

  1. Anote os poucos campos que realmente importam. Defina “válido” em palavras simples. Exemplo: “Email deve ser único”, “Quantidade deve ser 1 ou mais”, “Todo pedido deve pertencer a um cliente”.
  2. Modele as tabelas e relações. Decida o que pertence ao que antes de desenhar telas.
  3. Adicione restrições para as regras inegociáveis. Use unique para duplicatas, check para regras que devem sempre ser verdadeiras e foreign keys para relacionamentos.
  4. Construa a UI para corresponder às restrições. Marque campos obrigatórios, use os tipos de entrada corretos e adicione dicas simples. A UI deve guiar as pessoas, mas o banco continua sendo a barreira final.
  5. Tente quebrar de propósito. Cole valores bagunçados, tente duplicatas e selecione registros relacionados ausentes. Depois melhore rótulos e textos de erro até ficar óbvio o que corrigir.

Exemplo rápido

Suponha que você esteja construindo um formulário interno “Novo Pedido”. Você pode deixar o usuário buscar por nome do cliente, mas o banco deve aceitar apenas um real Customer ID (foreign key). Na UI, isso vira um seletor pesquisável. Se o usuário submeter sem escolher um cliente, a mensagem pode simplesmente dizer “Escolha um cliente” em vez de falhar depois com um erro confuso de salvamento.

Isso mantém regras consistentes entre web e mobile sem repetir lógica frágil em toda parte.

Restrições unique que impedem duplicatas que as pessoas realmente criam

Faça o formulário corresponder ao modelo
Desenhe pickers e campos obrigatórios que correspondam às regras do banco de dados desde o primeiro dia.
Construir UI agora

Uma restrição unique é a maneira mais simples de evitar que “a mesma coisa, registrada de formas diferentes” se acumule. Faz o banco recusar um valor duplicado, mesmo que o formulário tenha deixado passar.

Use unique para valores que as pessoas naturalmente repetem por acidente: emails, nomes de usuário, números de fatura, etiquetas de ativos, matrículas de funcionários ou números de ticket colados de planilhas.

A primeira decisão é o escopo. Alguns valores devem ser únicos em todo o sistema (um username). Outros só precisam ser únicos dentro de um grupo pai (um número de fatura por organização, ou uma etiqueta de ativo por depósito). Escolha o escopo de propósito para não bloquear dados válidos.

Uma forma prática de pensar:

  • Único global: um valor, um registro em qualquer lugar (username, identificador público)
  • Único por organização: único dentro de uma empresa/time (invoice_number + org_id)
  • Único por local: único dentro de um site (asset_tag + location_id)

Como você trata o conflito importa tanto quanto a regra. Quando uma unique falha, não diga apenas “já existe”. Diga o que colidiu e o que o usuário pode fazer a seguir. Por exemplo: “O número de fatura 1047 já existe para Acme Co. Tente 1047-2 ou abra a fatura existente.” Se sua UI puder referenciar com segurança o registro existente, uma pequena dica como data de criação ou dono ajuda o usuário a recuperar sem expor dados sensíveis.

Edições precisam de cuidado especial. Um erro comum é tratar uma atualização como um novo registro e sinalizar uma “duplicata” contra si mesmo. Garanta que sua lógica de salvamento reconheça o registro atual para não comparar a linha com ela mesma.

No AppMaster, defina a regra unique no Data Designer primeiro e depois reflita isso no formulário com uma mensagem amigável. O banco continua sendo o juiz final e sua UI permanece honesta porque explica uma regra real.

Check constraints para regras que devem sempre ser verdadeiras

Uma check constraint é uma regra que o banco aplica em cada linha, o tempo todo. Se alguém insere um valor que quebra a regra, o salvamento falha. Isso é exatamente o que você quer para regras que nunca devem ser violadas, mesmo quando dados são criados por telas diferentes, importações ou automações.

As melhores checks são simples e previsíveis. Se o usuário não consegue deduzir a regra, ele continuará recebendo erros e culpando o formulário. Mantenha checks focadas em fatos, não em políticas complicadas.

Checks comuns que valem a pena:

  • Intervalos: quantidade entre 1 e 1000, idade entre 13 e 120
  • Estados permitidos: status deve ser Draft, Submitted, Approved ou Rejected
  • Números positivos: amount > 0, desconto entre 0 e 100
  • Ordem de datas: end_date >= start_date
  • Lógica simples: se status = Approved então approved_at não é nulo

O truque que torna checks amigáveis é como você redige a mensagem na UI. Não repita o nome da restrição. Diga ao usuário o que mudar.

Bons padrões:

  • “Quantidade deve estar entre 1 e 1000.”
  • “Escolha um status: Draft, Submitted, Approved ou Rejected.”
  • “A data de fim deve ser igual ou posterior à data de início.”
  • “O valor deve ser maior que 0.”

Em um construtor no-code como o AppMaster, tudo bem espelhar as mesmas checks no formulário para feedback instantâneo, mas mantenha a check no banco como o guarda‑corpo final. Assim, se uma nova tela for adicionada depois, a regra continua válida.

Chaves estrangeiras que mantêm relações reais

Previna links quebrados entre tabelas
Faça as relações serem reais para que pedidos só possam apontar para clientes existentes.
Usar chaves estrangeiras

Uma foreign key (FK) aplica uma promessa simples: se um campo diz que aponta para outro registro, esse outro registro deve existir. Se um Order tem um CustomerId, o banco recusa qualquer pedido que referencie um cliente que não esteja na tabela Customers.

Isso importa porque campos de relação são onde dados “quase corretos” aparecem. Alguém digita o nome do cliente um pouco errado, cola um ID antigo ou seleciona um registro que foi excluído ontem. Sem FK, esses erros parecem ok até relatórios, faturamento ou suporte quebrarem.

O padrão de UI é direto: substitua texto livre por escolhas seguras. Em vez de um input de texto para “Cliente”, use um select, busca ou autocomplete que escreva o ID do cliente nos bastidores. Em um construtor no-code (por exemplo, usando componentes UI do AppMaster ligados aos seus modelos), isso geralmente significa vincular um dropdown ou lista de busca à tabela Customers e salvar a referência do registro selecionado, não o rótulo.

Quando o registro referenciado estiver ausente ou excluído, decida o comportamento de antemão. A maioria das equipes escolhe uma destas abordagens:

  • Evitar exclusão enquanto existirem registros relacionados (comum para clientes, produtos, departamentos)
  • Arquivar em vez de excluir (manter histórico sem quebrar relações)
  • Deletar em cascata somente quando for realmente seguro (raro para dados de negócio)
  • Zerar a referência apenas quando a relação for opcional

Também planeje o fluxo de “criar registro relacionado”. Um formulário não deve forçar o usuário a sair, criar o cliente em outro lugar e depois voltar e re‑digitar tudo. Uma abordagem prática é uma ação “Novo cliente” que cria o cliente primeiro, retorna o novo ID e o seleciona automaticamente.

Se uma FK falhar, não mostre uma mensagem crua do banco. Diga o que aconteceu em linguagem simples: “Por favor, escolha um cliente existente (o cliente selecionado não existe mais).” Essa frase única impede que uma relação quebrada se espalhe.

Lidando com falhas de restrição no fluxo da UI

Envie uma ferramenta interna de pedidos limpa
Crie um formulário Novo Pedido que bloqueie duplicados e clientes ausentes no momento do salvamento.
Começar a criar

Bons formulários capturam erros cedo, mas não devem fingir que são o juiz final. A UI ajuda o usuário a ir mais rápido; o banco garante que nada ruim seja salvo.

Checagens do lado do cliente são para coisas óbvias: um campo obrigatório está vazio, um email está sem o @ ou um número está fora de um teto absurdo. Mostrar isso imediatamente faz o formulário parecer responsivo e reduz envios falhos.

Checagens do lado do servidor é onde as restrições fazem o verdadeiro trabalho. Mesmo se a UI perder algo (ou duas pessoas enviarem ao mesmo tempo), o banco bloqueia duplicatas, valores inválidos e relações quebradas.

Quando um erro de restrição volta do servidor, mantenha a resposta previsível:

  • Mantenha todo o input do usuário no formulário. Não recarregue a página.
  • Destaque o campo que causou o problema e adicione uma mensagem curta próxima a ele.
  • Se o problema envolver vários campos, mostre uma mensagem no topo e ainda marque o campo mais adequado.
  • Ofereça uma ação segura: editar o valor ou abrir o registro existente, se fizer sentido.

Por fim, registre o que aconteceu para melhorar o formulário. Capture o nome da restrição, a tabela/campo e a ação do usuário que a desencadeou. Se uma restrição falha frequentemente, adicione uma dica pequena na UI ou uma checagem extra no cliente. Um pico repentino também pode sinalizar uma tela confusa ou uma integração quebrada.

Exemplo: um formulário interno de pedidos que se mantém limpo ao longo do tempo

Considere uma ferramenta interna usada por vendas e suporte: um formulário “Criar Pedido”. Parece inofensivo, mas toca nas tabelas mais importantes do banco. Se o formulário aceitar entradas ruins mesmo uma vez, esses erros se espalham para faturas, envios, reembolsos e relatórios.

A forma limpa de construir é deixar as regras do banco guiarem a UI. O formulário vira uma interface amigável para regras que continuam válidas, mesmo quando alguém importa dados ou edita registros em outro lugar.

Veja o que a tabela Order faz valer:

  • Número de pedido único: cada order_number deve ser diferente.
  • Checks para regras sempre verdadeiras: quantity > 0, unit_price >= 0 e talvez unit_price <= 100000.
  • Foreign key para Customer: todo pedido deve apontar para um registro de cliente real.

Agora veja o que acontece no uso real.

Um representante digita um número de pedido de memória e acidentalmente reutiliza um existente. O salvamento falha na unique. Em vez de um vago “salvamento falhou”, a UI pode mostrar: “Número do pedido já existe. Use o próximo número disponível ou pesquise o pedido existente.”

Mais tarde, um registro de cliente é mesclado ou excluído enquanto alguém ainda tem o formulário aberto. Ao salvar com o cliente antigo selecionado, a foreign key bloqueia. Uma boa resposta da UI é: “Esse cliente não está mais disponível. Atualize a lista de clientes e escolha outro.” Em seguida você recarrega o dropdown de Customer e mantém o restante do formulário intacto para que o usuário não perca o trabalho.

Com o tempo, esse padrão mantém pedidos consistentes sem depender da atenção constante de todos.

Erros comuns que causam mensagens confusas e dados sujos

Quebre seu formulário antes dos usuários
Insira entradas bagunçadas de propósito e refine a validação até que a correção fique óbvia.
Testar

A maneira mais rápida de obter dados bagunçados é confiar apenas em regras na UI. Um campo obrigatório no formulário ajuda, mas não protege importações, integrações, edições de admin ou uma segunda tela que escreve na mesma tabela. Se o banco aceita valores ruins, eles aparecerão em toda parte depois.

Outro erro comum é escrever restrições que são rígidas demais para a vida real. Uma check que parece correta no primeiro dia pode bloquear usos normais uma semana depois, como reembolsos, envios parciais ou telefones de outros países. Uma boa regra é: restrinja o que deve sempre ser verdadeiro, não o que geralmente é verdade.

Atualizações muitas vezes são esquecidas. Colisões unique em edição são clássicas: um usuário abre um registro, muda um campo não relacionado e o salvamento falha porque um valor “único” mudou em outro lugar. Transições de status são outra armadilha. Se um registro pode ir de Draft para Approved para Cancelled, verifique se seus checks permitem toda a jornada, não só o estado final.

Foreign keys falham de uma forma muito evitável: deixar as pessoas digitarem IDs. Se a UI permite texto livre para um registro relacionado, você terá relações quebradas. Prefira seletores vinculados a registros existentes e mantenha a FK no banco como última linha de defesa.

Finalmente, erros brutos do banco geram pânico e tickets de suporte. Você pode manter restrições estritas e ainda assim mostrar mensagens humanas.

Uma lista curta de correções:

  • Mantenha as restrições como fonte da verdade, não apenas regras de formulário
  • Projete checks em torno de fluxos reais, incluindo exceções
  • Trate edições e transições, não apenas criação
  • Use pickers para relacionamentos, não identificadores digitados
  • Mapear falhas de restrição para mensagens amigáveis por campo

Checklist rápido e próximos passos para equipes no-code

Antes de lançar um formulário, assuma que ele será usado com pressa, em um dia ruim, com dados copiados. A abordagem mais segura é restrições de banco de dados para validação de formulários, assim o banco faz valer a verdade mesmo se a UI deixar passar algo.

Verificações rápidas antes do lançamento

Execute estas checagens em todo formulário que escreve no banco:

  • Duplicatas: identifique o que deve ser único (email, número do pedido, ID externo) e confirme que a regra unique existe
  • Relações ausentes: confirme que toda relação obrigatória está aplicada (por exemplo, um Order deve ter um Customer)
  • Intervalos inválidos: adicione checks para valores que precisam ficar dentro de limites (quantity > 0, desconto entre 0 e 100)
  • Campos obrigatórios: garanta que dados “necessários” sejam aplicados no nível do banco, não apenas com flags de UI
  • Padrões seguros: decida o que deve vir preenchido por padrão (status = "Draft") para que as pessoas não adivinhem

Depois, teste como um usuário, não como um construtor: faça uma submissão limpa de ponta a ponta e tente quebrá‑la com duplicatas, relações ausentes, números fora do intervalo, campos obrigatórios em branco e tipos errados.

Próximos passos no AppMaster

Se você está construindo no AppMaster (appmaster.io), modele as regras primeiro no Data Designer (unique, check e foreign keys), depois construa o formulário no web ou mobile UI builder e conecte a lógica de salvamento no Business Process Editor. Quando uma restrição falhar, capture o erro e mapeie‑o para uma única ação clara: o que mudar e onde.

Mantenha o texto de erro consistente e calmo. Evite culpas. Prefira “Use um endereço de email único” em vez de “Email inválido.” Se possível, mostre o valor conflitante ou o intervalo requerido para que a correção fique óbvia.

Escolha um formulário real (como “Criar Cliente” ou “Novo Pedido”), construa‑o de ponta a ponta e valide com dados bagunçados de amostra vindos do dia a dia da sua equipe.

FAQ

Por que eu deveria impor validação no banco de dados em vez de apenas na interface do formulário?

Comece com restrições no banco de dados porque elas protegem todas as formas de escrita: formulários web, telas mobile, importações e chamadas de API. A validação no cliente ainda é útil para feedback mais rápido, mas o banco de dados deve ser a barreira final para que valores ruins não entrem por outra tela ou automação.

Quais restrições de banco importam mais para formulários de negócios típicos?

Concentre-se no básico que evita a maior parte dos danos reais aos dados: unique para duplicados, check para regras que devem sempre ser verdadeiras, e foreign keys para relações reais. Adicione apenas as regras das quais você tem certeza de que nunca devem ser violadas, mesmo em importações ou casos de exceção.

Quando devo usar uma restrição unique e como escolher o escopo certo?

Use uma restrição única quando um valor deve identificar um registro dentro do escopo escolhido, como email, número de fatura ou matrícula de funcionário. Decida o escopo primeiro (global vs por organização/local) para não bloquear repetições válidas que existam no seu negócio.

O que faz uma boa restrição check que não irá frustrar os usuários?

Mantenha as restrições check simples e previsíveis, como intervalos, números positivos ou ordenação de datas. Se os usuários não conseguem adivinhar a regra pelo rótulo do campo, eles vão errar várias vezes; então forneça uma orientação clara na UI e evite checks que codifiquem políticas complicadas.

Como as chaves estrangeiras ajudam, e o que a interface deve fazer diferente?

Uma foreign key impede referências “quase corretas”, como um pedido apontando para um cliente que não existe mais. Na UI, evite campos de texto livres para relações; use um seletor ou busca que salve o ID do registro relacionado para que a relação permaneça válida.

Como transformo erros brutos de restrição em mensagens claras e humanas?

Trate cada restrição como um “contrato de erro”: traduza a falha técnica em uma frase que explique o que aconteceu e o que fazer a seguir. Por exemplo, substitua uma violação unique crua por “Este email já está em uso. Use outro email ou entre na conta.”

Onde devo exibir erros relacionados a restrições no formulário?

Mostre erros de campo ao lado do respectivo campo e mantenha os dados do usuário no formulário para que ele possa corrigir rapidamente. Para regras que envolvem vários campos (como datas de início/fim), use uma mensagem no nível do formulário e destaque o campo mais relevante para facilitar a correção.

Ainda preciso de validação no cliente se tenho restrições no banco de dados?

A validação no cliente deve capturar problemas óbvios (campos obrigatórios vazios, formatação básica) para reduzir tentativas de envio falhas. O banco de dados ainda precisa das restrições para condições de corrida e caminhos alternativos de escrita, como dois usuários submetendo o mesmo número de fatura ao mesmo tempo.

Quais são os erros mais comuns que levam a mensagens confusas ou dados sujos?

Não dependa apenas de regras na UI, não torne as restrições mais rígidas que os fluxos reais e não esqueça atualizações e transições de status. Evite permitir que usuários digitem IDs para relações; prefira seletores e mantenha a restrição como a garantia final no banco de dados.

Como aplico essa abordagem no AppMaster sem complicar demais o aplicativo?

Modele seus dados e restrições primeiro no Data Designer, depois construa o formulário e mapeie as falhas de restrição para mensagens amigáveis no fluxo da UI. No AppMaster, isso normalmente significa definir regras unique/check/FK no modelo, ligar os saves no Business Process Editor e manter o texto de erro consistente entre web e mobile; comece com um formulário de alto impacto e tente quebrá‑lo com dados bagunçados.

Fácil de começar
Criar algo espantoso

Experimente o AppMaster com plano gratuito.
Quando estiver pronto, você poderá escolher a assinatura adequada.

Comece