IO caso contra SQL gerado

O modelo não deveria
escrever o SQL.

Text-to-SQL é a forma óbvia de apontar um agente para um banco de dados, e a demo é genuinamente impressionante. É em produção que a coisa vira: a mesma pergunta compila para SQL diferente, um erro silencioso de join desloca a receita em 15%, e a saída do modelo vira uma superfície de ataque. Há outro caminho.

IICrédito primeiro

Text-to-SQL fez jus ao hype. No seu domínio.

Onde é a ferramenta certa

  • Protótipos com dados descartáveis
  • Explorar um schema desconhecido, com supervisão humana
  • Perguntas pontuais que alguém vai verificar
  • A demo — funciona muito bem em demos

Onde falha

  • Números que vão embasar decisões
  • Texto não confiável em qualquer parte do contexto
  • Credenciais de produção na conexão
  • Respostas que precisam ser reproduzíveis ou auditadas
  • Agentes que operam sem supervisão

O padrão não é o problema. O raio de impacto é. Cada risco nesta página decorre de uma única escolha de design: a saída do modelo é executada como código.

IIIOs dois caminhos

Mesma pergunta. Duas arquiteturas.

Acompanhe uma pergunta pelos dois caminhos — uma string SQL livre à esquerda, um plano tipado à direita. Os marcadores numerados referenciam o registro de riscos abaixo.

a pergunta

Qual região tem a maior receita total?

Caminho A

O modelo escreve SQL

  1. o modelo improvisa uma string 010304

    Tudo que o modelo leu — uma mensagem do usuário, uma linha recuperada — pode moldar essa string.

    execução 1SELECT region, SUM(total) FROM orders GROUP BY region;execução 2 · mesma perguntaSELECT o.region, SUM(i.amount) FROM orders o LEFT JOIN order_items i ON i.order_id = o.id GROUP BY 1;
  2. sua conexão executa 05

    Com toda a autoridade da conexão. Leitura, junção — e, salvo alguém ter lembrado da flag, escrita.

a resposta

run 1 → east · 2130.50

run 2 → east · 2450.08+15% — fan-out de join 02

Duas execuções, dois números. Ambos plausíveis. Nenhum sinal de qual — se algum — está correto.

Caminho B

O modelo envia um plano tipado

  1. intenção tipada

    Não é uma string — é um valor com schema. Só pode nomear operações definidas pelo contrato.

    { "kind": "query", "version": "1", "source": "revenue", "op": "sum", "group_by": "region" }
  2. verificação de contrato

    Fixado por hash. Uma operação desconhecida retorna unsupported_operation com as correspondências mais próximas — nunca uma suposição.

  3. verificação de política

    Sua lista de permissões em nível de código. Uma requisição pode restringir a superfície, nunca ampliá-la.

  4. execução determinística

    float64, thread único, runtime fixo. Mesmo plano, mesmos bytes, mesma resposta.

a resposta

east · 2130.50

plan_hash f87610d8afeb…

decision_path "exact_spec"

Uma resposta, com os hashes para reproduzi-la — na semana seguinte, no trimestre seguinte, em qualquer das duas linguagens.

IVO registro de riscos

Cinco formas como SQL gerado falha

  1. 01

    P2SQLarXiv 2308.01990

    Injeção migrada para o canal de saída

    A sanitização de entrada inspeciona o que entra no modelo. Ataques P2SQL chegam pelo que sai: SQL bem formado e malicioso, montado a partir de instruções ocultas em uma mensagem do usuário ou em uma linha recuperada. Nenhum filtro de entrada o vê — o ataque é a própria saída.

  2. 02

    −15%o dashboard que mentiu

    Joins errados falham silenciosamente

    Um join com fan-out duplica linhas e a receita aparece 15% distorcida. Nenhuma exceção, nenhum aviso — SQL errado não falha, ele reporta. O resultado é sempre um número, e um número plausível não carrega nenhum sinal de que está errado.

  3. 03

    1 → numa pergunta, n consultas

    Mesma pergunta, SQL diferente

    Pergunte duas vezes e o modelo pode compilar a questão de duas formas distintas — às vezes chegando a duas respostas diferentes. Não há consulta canônica para revisar, cachear ou reproduzir. O número de ontem não pode ser recriado, nem mesmo para conferência.

  4. 04

    91.2 → 21.3% correto · benchmark → schema empresarial

    O abismo de precisão

    Em schemas de benchmark limpos, um modelo de fronteira gerou SQL correto em 91,2% das vezes. Em schemas empresariais reais: 21,3%. Na mesma onda de pesquisa, cerca de 40% das execuções de agentes text-to-SQL falharam completamente ou retornaram resultados incorretos. Benchmarks são organizados. Seu schema não é.

  5. 05

    1 BD em proddeletado por um agente — o incidente do Replit

    O caminho de escrita sempre existiu

    O agente de codificação do Replit deletou um banco de dados de produção mesmo com instruções explícitas para não tocá-lo. A lição é essa: uma instrução de somente leitura é um pedido. Se a conexão pode escrever, o caminho de escrita existe — e eventualmente uma conclusão errada o encontra. Somente leitura precisa ser uma propriedade da ferramenta, não uma linha no prompt.

Não filtre a saída.
Não a gere.

Sem string SQL, sem injeção · sem suposição, sem deriva

VO certificado

Cinco dimensões, lado a lado

Não é um gerador LLM-para-SQLREADME do engine

Certificado de diferença

superfície de autoriaSQL geradouma string SQL de forma livreplano tipadouma intenção tipada e versionada
superfície de execuçãoSQL geradotudo que a conexão permiteplano tipado4.574 capacidades somente leitura
caminho de escritaSQL geradopresente salvo bloqueioplano tipadonenhum, por construção
governançaSQL geradonível de prompt, melhor esforçoplano tipadoallow-lists em código que o modelo não pode ampliar
reprodutibilidadeSQL geradonenhumaplano tipadoum hash de replay em cada resultado

coluna direita fixada ao contratosha256:79f1c5a6…924be9a1

As letras miúdas se sustentam: a única saída de emergência do engine — getUnsafeRuntime — está ausente de toda superfície exposta ao modelo, portanto o modelo não consegue alcançá-la. E o README enuncia a doutrina sem rodeios: isto não é um gerador LLM-para-SQL.

VIPerguntas

Feitas em produção

Como bloqueio DELETE e DROP em SQL gerado por LLM?

Não filtre o SQL — pare de gerá-lo. Denylists inspecionam strings, e modelos são inesgotavelmente criativos em produzir novas. SQAI elimina a classe: o modelo registra um plano tipado contra 4.574 capacidades somente leitura, e nenhuma capacidade de escrita existe para qualquer plano nomear.

O que é injeção P2SQL?

Injeção prompt-para-SQL: SQL malicioso que aparece na saída do modelo, montado a partir de instruções ocultas no que o modelo leu — uma mensagem do usuário, um documento, uma linha recuperada. A sanitização de entrada nunca o detecta, pois o ataque vive no canal de saída. Está documentado em arXiv 2308.01990.

Text-to-SQL é alguma vez a escolha certa?

Sim — para protótipos e exploração supervisionada em dados não produtivos, é rápido e genuinamente útil. É a escolha errada quando o número será usado para tomar decisões, o contexto contém texto não confiável ou a resposta precisa ser reprodutível.

Como concedo a um agente de IA acesso somente leitura a um banco de dados?

Torne o somente leitura estrutural, não configurado. Um flag de somente leitura em uma conexão é uma configuração que alguém pode alterar. A superfície de execução do SQAI contém apenas capacidades de leitura — o caminho de escrita está ausente por construção, e até a saída de emergência do engine é inacessível a qualquer ferramenta exposta ao modelo.

Em que um plano tipado difere do SQL gerado?

Uma string SQL pode dizer qualquer coisa que a gramática permite. Um plano tipado só pode dizer o que o contrato define. Cada plano é validado contra um contrato fixado por hash, verificado pela sua política de allow-list e executado em um engine determinístico — com um hash de replay em cada resultado.

Escolha o outro caminho.

Sem conta. Sem chave. Dados locais ficam locais.