
Todo mundo está falando de agente de IA, de MCP, de ligar um chat no banco. Eu mesmo testei isso há duas semanas (está aqui) e funcionou, mas precisava de um servidor no meio, de um cliente, de um monte de peça. Enquanto isso a Oracle fez diferente: botou a IA dentro do banco. No 26ai voce escreve SELECT AI e a pergunta em português, e o próprio Oracle monta o prompt, manda pro modelo, recebe o SQL, valida e executa. É o gênio da lâmpada: esfrega, pede, e o SQL aparece. A pergunta é o que ele entende, e o que ele faz quando não entende.
Isso se chama Select AI. Era exclusivo do Autonomous Database, e desde janeiro de 2026 roda no 26ai on-premises, o que mudou tudo: agora dá pra ter no banco da empresa, no servidor da empresa, sem Autonomous. Como exemplo usei um Protheus de desenvolvimento, porque é o ERP que mais vejo em cima de Oracle e porque o modelo de dados dele é o teste perfeito: nome de coluna de seis letras, data gravada como texto, exclusão lógica. Se a IA entende isso, entende qualquer banco.
Vou mostrar o que foi preciso pra instalar, os quatro erros que apareceram antes da primeira resposta (nenhum está na documentação do jeito que aparece), o que o banco manda pra fora, e onde a IA acertou e errou. Adianto o final: ela acerta o que está escrito em qualquer lugar da internet, e erra justamente o que só o seu financeiro sabe. E isso tem conserto, dentro do próprio banco.
O que é o Select AI, em duas linhas
É um pacote PL/SQL, o DBMS_CLOUD_AI, e uma palavra reservada nova. A sintaxe é SELECT AI ação pergunta. As ações que usei: showsql só mostra o SQL gerado, runsql gera e executa (é o padrão, dá pra omitir), narrate executa e pede pro modelo contar o resultado em texto, explainsql explica o SQL, e showprompt mostra o que o banco mandou pro modelo. Essa última foi a mais útil do teste.

A própria Oracle avisa, no mesmo manual, o que todo mundo que usa IA já sabe mas esquece na hora de confiar num número:
LLMs are subject to hallucinations and results are not always correct.
Oracle AI Database Select AI User’s Guide, Use AI Keyword to Enter Prompts, Usage Notes
Funciona fora do Autonomous?
Funciona, e isso é novo. Até o 23.7 o Select AI era coisa de Autonomous Database. A Oracle publicou uma matriz de capacidades (Select AI Capability Matrix, documento G50041) com uma coluna “Oracle AI Database 23.26.1”, que é o 26ai on-premises que saiu em janeiro de 2026. Nessa coluna, NL2SQL é Y, e a lista de provedores tem OpenAI, Anthropic, Google, Cohere, Azure, OCI Generative AI, Hugging Face, Amazon, provedores compatíveis com a API da OpenAI e “Private LLM”.

Só que a doc inteira do Select AI foi escrita pensando no Autonomous, onde o DBMS_CLOUD já vem instalado e a rede já está configurada. On-premises nada disso vem. Tem até uma pergunta no fórum da Oracle, de fevereiro, de alguém com o 26ai Enterprise instalado procurando o script de instalação. É exatamente o buraco que eu caí.

Instalando no 26ai Free (a imagem lite não serve)
Usei o 26ai Free em container, versão 23.26.3, numa máquina ARM. Primeira pegadinha: a imagem free:latest-lite, que é a que todo mundo usa porque tem 1,6 GB, vem com a pasta rdbms/admin praticamente vazia. Um arquivo. A imagem completa tem 2.445, e entre eles os três que interessam: catclouduser.sql, dbms_cloud_install.sql e dbms_cloud_ai.sql.

A instalação em si são dois comandos com o catcon.pl, o primeiro cria o usuário C##CLOUD$SERVICE e o segundo instala os pacotes. É o mesmo procedimento do 23.7 em diante, não tem segredo:
$ORACLE_HOME/perl/bin/perl $ORACLE_HOME/rdbms/admin/catcon.pl \
-u sys/senha --force_pdb_mode 'READ WRITE' \
-b dbms_cloud_user -d $ORACLE_HOME/rdbms/admin/ -l /tmp catclouduser.sql
$ORACLE_HOME/perl/bin/perl $ORACLE_HOME/rdbms/admin/catcon.pl \
-u sys/senha --force_pdb_mode 'READ WRITE' \
-b dbms_cloud_install -d $ORACLE_HOME/rdbms/admin/ -l /tmp dbms_cloud_install.sql


Depois disso criei dois usuários: PROTHEUS, dono das tabelas, e FINANCEIRO, que é quem vai perguntar. O FINANCEIRO recebeu EXECUTE no DBMS_CLOUD_AI e no DBMS_CLOUD, CREATE CREDENTIAL, e por enquanto nenhum GRANT nas tabelas. De propósito, voce vai ver por quê.
Quatro erros antes da primeira resposta
Criei a credencial com a chave da Anthropic, o perfil apontando pro claude-sonnet-5-5, dei a ACL de rede pro FINANCEIRO como manda a doc, e fiz a primeira pergunta. Daí começou.
Erro 1. ORA-20000: Database property SSL_WALLET not found. O DBMS_CLOUD exige uma wallet SSL configurada como propriedade do banco, mesmo que ela esteja vazia. Criei uma com orapki, auto-login, e apontei a propriedade. Detalhe: o ALTER DATABASE PROPERTY só funciona no CDB$ROOT, na PDB dá ORA-65040. Também dei o privilégio de uso da wallet pro FINANCEIRO e pro C##CLOUD$SERVICE.
orapki wallet create -wallet /opt/oracle/wallet_ssl -pwd "senha" -auto_login
-- como SYS, no CDB$ROOT
ALTER DATABASE PROPERTY SET SSL_WALLET='/opt/oracle/wallet_ssl';
-- na PDB
BEGIN
DBMS_NETWORK_ACL_ADMIN.APPEND_WALLET_ACE(
wallet_path => 'file:/opt/oracle/wallet_ssl',
ace => xs$ace_type(privilege_list => xs$name_list('use_client_certificates','use_passwords'),
principal_name => 'C##CLOUD$SERVICE', principal_type => xs_acl.ptype_db));
END;
/
Erro 2. ORA-20401: Authorization failed for URI (e a URI da Anthropic no fim da mensagem). Esse me tomou mais de uma hora, porque a mensagem diz que a Anthropic recusou a chave, e a chave estava certa (testei com curl, respondeu 200). Botei um tcpdump na interface do container e descobri que o banco nem abria conexão. O erro era de ACL, mas disfarçado. A doc do Select AI manda dar a ACL de rede pro usuário que pergunta, e eu tinha dado. Mas o DBMS_CLOUD roda com direitos do dono, o C##CLOUD$SERVICE, que é um usuário comum (C##), e a ACL que ele checa é a do CDB$ROOT. Ou seja: on-premises, tem uma ACL a mais, no container raiz, pro dono do pacote. A doc não fala disso porque no Autonomous isso já vem feito.
-- como SYS, no CDB$ROOT (a da PDB sozinha nao resolve)
BEGIN
DBMS_NETWORK_ACL_ADMIN.APPEND_HOST_ACE(
host => '*',
ace => xs$ace_type(privilege_list => xs$name_list('http','http_proxy','connect'),
principal_name => 'C##CLOUD$SERVICE', principal_type => xs_acl.ptype_db));
DBMS_NETWORK_ACL_ADMIN.APPEND_HOST_ACE(
host => '*',
ace => xs$ace_type(privilege_list => xs$name_list('resolve'),
principal_name => 'C##CLOUD$SERVICE', principal_type => xs_acl.ptype_db));
END;
/
-- na PDB, pro usuario que pergunta (essa a doc fala)
BEGIN
DBMS_NETWORK_ACL_ADMIN.APPEND_HOST_ACE(
host => 'api.anthropic.com',
ace => xs$ace_type(privilege_list => xs$name_list('http'),
principal_name => 'FINANCEIRO', principal_type => xs_acl.ptype_db));
END;
/
Erro 3. ORA-20011: Invalid object uri (SSL validation failed). Agora o banco chegou na Anthropic e não confiou no certificado. Aqui tem uma coisa curiosa do 26ai: o UTL_HTTP puro valida o certificado pelo cert store do sistema operacional, e funciona sem wallet nenhuma. Eu testei antes de tudo e recebi um 401 limpo, que é o TLS fechando e a API reclamando que não tinha chave. Mas o DBMS_CLOUD valida pela wallet. Então a wallet vazia do erro 1 precisa dos certificados da cadeia da api.anthropic.com, que hoje é GlobalSign Root CA, GTS Root R4 e WE1 (Google Trust Services). Peguei com openssl s_client e importei os três com orapki.

echo | openssl s_client -connect api.anthropic.com:443 -servername api.anthropic.com -showcerts
# salvei os certificados da cadeia e a raiz (GlobalSign Root CA, do ca-bundle do SO)
orapki wallet add -wallet /opt/oracle/wallet_ssl -trusted_cert -cert root.pem -pwd "senha"
orapki wallet add -wallet /opt/oracle/wallet_ssl -trusted_cert -cert chain1.pem -pwd "senha"
orapki wallet add -wallet /opt/oracle/wallet_ssl -trusted_cert -cert chain2.pem -pwd "senha"
Erro 4. ORA-20400: Request failed with status HTTP 400, e a Anthropic explicando: temperature is deprecated for this model. O DBMS_CLOUD_AI manda o parâmetro temperature em toda chamada, mesmo quando voce não configura nada no perfil, e os modelos Claude 5.5 não aceitam mais. Troquei o modelo pro claude-sonnet-4-5 e passou. Se a Oracle não mudar isso num RU, quem usar Claude vai ficar preso nos modelos 4.x.

E uma pegadinha que não é erro: o Select AI guarda a resposta da mesma pergunta no mesmo perfil. Repeti uma pergunta e ela voltou em 0,00 segundo, com o mesmo SQL, em outra sessão. Isso me atrapalhou depois do GRANT, porque a pergunta continuou devolvendo o erro antigo. Apagar e recriar o perfil zera.
O que sai do banco
Antes de perguntar qualquer coisa eu queria ver o pacote que o Oracle manda pra fora, porque é isso que o jurídico vai perguntar. Fiz um servidor HTTPS falso respondendo como api.anthropic.com, apontei o DNS do container pra ele e botei o certificado dele na wallet. O banco mandou isso:

Vazia porque o FINANCEIRO ainda não tinha GRANT em tabela nenhuma. O Select AI só manda o metadado das tabelas que o usuário consegue ler. Isso é a melhor notícia do teste: a segurança continua sendo o GRANT, não é um filtro novo de IA. Depois do GRANT, a ação showprompt mostra o pacote completo:

Então: nome de tabela, nome de coluna, tipo, e os comentários se voce ligar. Dado mesmo só sai no narrate, porque ele manda o resultado da consulta pro modelo pra ganhar um texto. Existe um DISABLE_DATA_ACCESS no pacote justamente pra desligar isso pra todo mundo. A doc de boas práticas é direta sobre o metadado:
Object names, column names, annotations, and comments may be sent to the AI provider. Avoid sensitive metadata content in the object list.
Oracle AI Database Select AI User’s Guide, Best Practices for SQL Generation with Select AI
O lab: um Protheus de desenvolvimento
O banco do teste é um Protheus de desenvolvimento, pequeno, com dado de teste. Do lado do Oracle são as tabelas de sempre: SA1010, SA3010, SB1010, SB2010, SF2010, SD2010 e SE1010, com as colunas que todo mundo conhece (A1_COD, A1_LOJA, E1_VENCREA, E1_SALDO, F2_VALBRUT), as colunas de controle D_E_L_E_T_, R_E_C_N_O_ e R_E_C_D_E_L_, data gravada como texto AAAAMMDD, texto preenchido com espaço à direita. E o dicionário no banco, como fica desde a 12.1.2210: SX2010, SX3010 e SIX010 com X3_TITULO, X3_DESCRIC e as chaves. Nessa base tem 60 clientes, 420 notas, 940 títulos, 25 deles com D_E_L_E_T_ marcado, e alguns NCC e RA com saldo, que é a pegadinha clássica de quem soma contas a receber sem conhecer o sistema. Pra quem não é do Protheus: troque esses nomes pelos do seu ERP, o problema é o mesmo.
O perfil de IA é isso. O object_list diz quais tabelas entram no prompt, e comments diz se os COMMENT ON das tabelas vão junto. Criei dois perfis iguais, um com comments false e outro true, pra medir a diferença.
BEGIN
DBMS_CLOUD.CREATE_CREDENTIAL(credential_name => 'ANTHROPIC_CRED',
username => 'ANTHROPIC', password => 'sk-ant-...');
DBMS_CLOUD_AI.CREATE_PROFILE(
profile_name => 'PROTHEUS_CRU',
attributes => '{"provider": "anthropic",
"credential_name": "ANTHROPIC_CRED",
"model": "claude-sonnet-4-5",
"comments": "false",
"object_list": [{"owner": "PROTHEUS", "name": "SA1010"},
{"owner": "PROTHEUS", "name": "SA3010"},
{"owner": "PROTHEUS", "name": "SB1010"},
{"owner": "PROTHEUS", "name": "SB2010"},
{"owner": "PROTHEUS", "name": "SF2010"},
{"owner": "PROTHEUS", "name": "SD2010"},
{"owner": "PROTHEUS", "name": "SE1010"}]}');
END;
/
EXEC DBMS_CLOUD_AI.SET_PROFILE('PROTHEUS_CRU');
As quatro perguntas foram sempre as mesmas, do jeito que chegam: quantos clientes ativos a empresa tem, qual o total em reais de títulos a receber vencidos e ainda em aberto, quais os 5 clientes com maior valor vencido em aberto, e total faturado por vendedor em outubro de 2026. Antes de perguntar eu escrevi o SQL de cada uma na mão, pra ter gabarito.
Primeira rodada: sem GRANT, a IA inventa

Era esperado, mas vale o print porque explica o comportamento: o Select AI não dá erro de permissão, ele manda o prompt com a lista vazia e o modelo inventa um schema genérico. Quem barra é o parse do SQL depois. Se o usuário tiver GRANT em metade das tabelas, o modelo vai responder com metade, e vai parecer certo.
Segunda rodada: com GRANT e sem comentário nenhum


Aqui eu me surpreendi. Sem nenhuma dica, o modelo filtrou D_E_L_E_T_ = ‘ ‘ em todas, comparou E1_VENCREA com TO_CHAR(SYSDATE, ‘YYYYMMDD’) em vez de tratar como data, fez o join de cliente por A1_COD e A1_LOJA, e pra “ativo” usou A1_MSBLQL diferente de ‘1’. Tudo isso é conhecimento de Protheus que ele já tinha, porque esses nomes de coluna estão em fórum, em TDN, em milhares de scripts públicos. Não precisou do meu dicionário pra isso. Se o seu sistema for caseiro, sem nada publicado, essa rodada vai sair bem pior.
Errou duas coisas, e as duas são de dinheiro. No vencido somou todo título com saldo, incluindo NCC e RA, que são crédito do cliente e abatem. No faturamento somou toda SF2, sem filtrar F2_TIPO, então uma devolução entraria como venda. Nenhum erro de sintaxe, os dois SQLs rodam e devolvem número. É o pior tipo de erro.
Terceira rodada: o SX3 vira COMMENT
A doc de boas práticas do Select AI diz pra enriquecer o metadado com comentários de tabela e coluna, e ligar comments no perfil. Quem tem Protheus já tem esse texto pronto: X3_TITULO e X3_DESCRIC. Então em vez de escrever 112 comentários na mão, escrevi um bloco PL/SQL que lê o SX2 e o SX3 e gera os COMMENT ON:

-- roda como dono das tabelas. Le o SX2 e o SX3 e grava COMMENT ON TABLE / COLUMN
SET SERVEROUTPUT ON
DECLARE
n NUMBER := 0;
PROCEDURE cm(p_obj VARCHAR2, p_txt VARCHAR2) IS
BEGIN
EXECUTE IMMEDIATE 'COMMENT ON '||p_obj||' IS '''||REPLACE(p_txt,'''','''''')||'''';
n := n + 1;
END;
BEGIN
FOR t IN (SELECT x2_chave, x2_arquivo, x2_nome FROM sx2010 WHERE d_e_l_e_t_ = ' ') LOOP
cm('TABLE '||t.x2_arquivo, t.x2_nome||' (alias '||t.x2_chave||' do Protheus). Registro valido so quando D_E_L_E_T_ = '' '' (espaco)');
FOR c IN (SELECT x3_campo, x3_titulo, x3_descric, x3_tipo, x3_relacao
FROM sx3010 WHERE x3_arquivo = t.x2_chave AND d_e_l_e_t_ = ' ' ORDER BY x3_ordem) LOOP
cm('COLUMN '||t.x2_arquivo||'.'||c.x3_campo,
TRIM(c.x3_titulo)||': '||TRIM(c.x3_descric)
||CASE c.x3_tipo WHEN 'D' THEN '. Data gravada como texto AAAAMMDD'
WHEN 'C' THEN '. Texto preenchido com espacos a direita'
ELSE '' END
||CASE WHEN TRIM(c.x3_relacao) IS NOT NULL THEN '. Relaciona com a tabela '||TRIM(c.x3_relacao)||'010' ELSE '' END);
END LOOP;
cm('COLUMN '||t.x2_arquivo||'.D_E_L_E_T_', q'[Marca de exclusao logica do Protheus: ' ' (espaco) = registro ativo, * = registro excluido. Sempre filtrar D_E_L_E_T_ = ' ']');
cm('COLUMN '||t.x2_arquivo||'.R_E_C_N_O_', 'Numero sequencial interno do registro (chave fisica), sem significado de negocio');
cm('COLUMN '||t.x2_arquivo||'.R_E_C_D_E_L_', 'Recno do registro no momento da exclusao, 0 quando ativo');
END LOOP;
DBMS_OUTPUT.PUT_LINE(n||' comentarios gravados');
END;
/

Num Protheus de produção voce ainda tem o SX5 (as tabelas genéricas, tipo os tipos de título na tabela 05) e o X3_CBOX com as opções dos combos, que dá pra concatenar no mesmo comentário. Eu parei no SX3 pra ficar simples. Criei o segundo perfil, PROTHEUS_SX3, igual ao primeiro mas com comments true, e repeti as quatro perguntas.

Melhorou onde o dicionário explica. Ativo passou a ser exatamente o combo do campo, e o faturamento filtrou tipo N sozinho. Mas o vencido continuou somando NCC e RA. E faz sentido: o SX3 diz que NCC é “Nota de Credito Cliente”, não diz que isso abate do contas a receber. Isso não está no dicionário de ninguém, está na cabeça do financeiro.
Quarta rodada: a regra que não está no dicionário
Então escrevi dois comentários na mão, por cima dos gerados. Um no E1_TIPO dizendo quais tipos são abatimento, outro no F2_TIPO dizendo que faturamento é só N. É o tipo de coisa que o DBA senta com o financeiro meia hora e escreve.


Rodando de verdade: runsql, narrate e explainsql
Com o perfil final, tirei o showsql e deixei executar. O total vencido deu 267.640,61, que é o mesmo número do meu SQL escrito na mão. Os cinco maiores devedores também bateram, na mesma ordem.


Uma coisa que voce vê nos dois prints: o SQL que a IA gerou está cheio de aspas duplas e aliases, e usa TO_DATE em cima de E1_VENCREA numa das versões. Funciona, mas o TO_DATE na coluna mata o índice da SIX se a tabela for grande. É o mesmo problema de qualquer SQL gerado, por gente ou por máquina: alguem precisa olhar o plano antes de botar isso num relatório que roda toda hora. O Select AI gera, não otimiza.
E se pedir pra apagar?
Pedi: “apague todos os títulos vencidos do cliente 000012”. O modelo obedeceu e escreveu um DELETE bonito, até com o NOT IN dos abatimentos que ele aprendeu no comentário. O Oracle barrou antes de executar, com ORA-41900, porque o FINANCEIRO não tem DELETE. A palavra AI só aceita SELECT por definição, e mesmo assim quem segurou foi o privilégio.

Repare no showprompt desse perfil, embaixo: agora cada coluna vai com o comentário ao lado. É mais texto por chamada, portanto mais token e mais custo. Com sete tabelas e 112 comentários ficou em uns 6 mil caracteres por pergunta. Num ERP inteiro, com o dicionário todo, não cabe, e nem faz sentido. A doc tem um object_list_mode automated que escolhe as tabelas relevantes por busca vetorial, mas o jeito mais simples é o que eu fiz: um perfil por assunto, com as dez ou quinze tabelas daquele assunto.
Quando chamar um especialista
Se voce tem Oracle e quer deixar o financeiro, o comercial ou a diretoria perguntar em português sem abrir o banco inteiro pra IA, esse lab é o roteiro: instalar o DBMS_CLOUD, acertar wallet e ACL (inclusive a do CDB$ROOT que a doc não fala), gerar os comentários a partir do dicionário do sistema, escrever as regras de negócio com quem conhece, e deixar o usuário de pergunta só com SELECT em views. A gente faz isso dentro do suporte de banco de dados Oracle, e se o seu ERP for Protheus, junto com a sustentação de Protheus. Se quiser começar vendo como está o seu banco hoje, o health check é gratuito, e se quiser só conversar sobre o seu caso, fala com a gente.
Capa: o gênio azul saindo da lâmpada, ilustração gerada com IA pra este post. Os prints de documentação são das páginas públicas da Oracle, reproduzidos para citação, com link na lista abaixo. Os prints de terminal são de um Oracle AI Database 26ai Free 23.26.3 de laboratório, em container, com um Protheus de desenvolvimento e dados de teste. O modelo usado foi o claude-sonnet-4-5 da Anthropic. A chave de API foi revogada depois do teste.
Referências
- Oracle: Select AI Capability Matrix (G50041), coluna Oracle AI Database 23.26.1
- Oracle: Select AI User’s Guide, Use AI Keyword to Enter Prompts (ações e usage notes)
- Oracle: Select AI User’s Guide, Best Practices for SQL Generation (comentários, object_list, governança)
- Oracle: Select AI User’s Guide, AI Profiles (pré-requisitos, ACL, credencial, Use Anthropic)
- Oracle Forums: Enabling Select AI on Oracle AI Database 26ai Standalone Installation (12/02/2026)
- ORACLE-BASE: DBMS_CLOUD Installation on 19c, 21c and 23ai On-Prem Databases (procedimento do 23.7 em diante)
- Ron Ekins: Getting started with DBMS_CLOUD and Oracle AI Database 26ai (10/06/2026)
- Oracle Blogs (Core Tec, em alemão): Private KI mit Oracle AI Database, que cita a ACL do C##CLOUD$SERVICE e o ORA-20401
- Oracle: Oracle AI Database Free, Quick Start (imagens de container)
- TOTVS TDN: Banco de Dados Homologados (Protheus)