Skip to main content

Mudar de SQL para SOQL

Objetivos de aprendizagem

Após concluir esta unidade, você estará apto a:

  • Compreender os benefícios dos objetos de Force.com.
  • Identificar as semelhanças e as diferenças entre SQL e SOQL.
  • Criar um demonstrativo SOQL simples usando o Workbench.
  • Criar consultas de relacionamento mais complicadas.
  • Criar consultas agregadas.

Compreendendo os objetos de Force.com

A plataforma Force.com oferece um banco de dados potente com muitos recursos que tornam a criação de aplicativos mais rápida e fácil. Se você já lidou com o SQL Server, sabe que os dados são armazenados em tabelas e linhas. O banco de dados no Force.com, por outro lado, usa objetos para armazenar dados. Os objetos contêm todas as funcionalidades que você espera de uma tabela, com mais algumas melhorias que os tornam mais poderosos e versáteis. Cada objeto comporta diversos campos, que correspondem às colunas de um banco de dados. Os dados são armazenados em registros do objeto, que correspondem às linhas de um banco de dados. Mas espere um pouco… Ainda não acabou!

Existem dois tipos de objeto:

  1. Objetos padrão – São aqueles objetos que vêm integrados ao Salesforce. Entre os objetos de CRM mais comuns, estão Accounts, Contacts, Opportunities e Leads.
  2. Objetos personalizados – São objetos novos que você cria para armazenar informações exclusivas em seu aplicativo. Os objetos personalizados ampliam as funcionalidades oferecidas pelos objetos padrão. Por exemplo, se você estiver criando um aplicativo para rastrear o inventário de produtos, pode criar objetos personalizados chamados Mercadorias, Pedidos ou Faturas (Merchandise, Orders ou Invoices).

Como você provavelmente já imaginou, os objetos podem ter campos de relacionamento que definem como os registros de um objeto se relacionam com os registros de outro objeto. Esses campos são, em essência, quaisquer chaves primárias e estrangeiras; porém, eles são muito mais flexíveis, facilitando o planejamento e a implementação de seu modelo de dados.

Independentemente de serem padrão ou personalizados, os objetos do Force.com não só oferecem uma estrutura para o armazenamento de dados como são a base dos elementos da interface que permitem que os usuários interajam com os dados, como as guias, o layout dos campos em uma página e as listas de registros relacionados. No caso das funcionalidades padrão, não há necessidade de implementar ORM, escrever UI para fazer CRUD de dados ou desenvolver tabelas. A plataforma oferece automaticamente essas funcionalidades padrão. Os objetos também têm suporte integrado a recursos como gerenciamento de acesso, validação, fórmulas e rastreamento de histórico. Todos os atributos de um objeto são descritos com metadados, facilitando a criação e modificação dos registros por meio de uma interface visual ou de forma programática.

Como você pode ver, os objetos são muito mais do que simples contêineres de armazenamento de dados. Eles oferecem um conjunto valioso de funcionalidades que deixam você livre para criar recursos exclusivos para o seu aplicativo. Para saber mais sobre como criar objetos personalizados, campos, relacionamentos e muito mais, confira o módulo Modelagem de dados.

Parecido, mas não igual

Como desenvolvedor .NET, é muito provável que você se sinta confortável para trabalhar com o SQL Server. E também é muito provável que você já saiba como escrever consultas ad hoc usando SQL. Então, pensamos que o melhor jeito de apresentar você a uma linguagem semelhante criada especificamente para o Salesforce, chamada SOQL (Salesforce Object Query Language, linguagem de consulta de objetos do Salesforce), seria comparar ambas.

A primeira coisa que você precisa saber é que, embora as duas sejam chamadas de linguagens de consulta, o SOQL é usado apenas para realizar consultas com o demonstrativo SELECT. O SOQL não tem demonstrativos equivalentes a INSERT, UPDATE e DELETE. No universo do Salesforce, a manipulação de dados é feita usando um conjunto de métodos chamado de DML (Data Manipulation Language, linguagem de manipulação de dados). Falaremos mais sobre o DML em breve. Por enquanto, você só precisa saber como consultar dados do Salesforce usando o demonstrativo SELECT proporcionado pelo SOQL.

Uma grande diferença que você perceberá imediatamente é que o SOQL não tem nada como SELECT *. Como o SOQL retorna os dados do Salesforce, que ficam em um ambiente multilocatário onde todos praticamente compartilham o banco de dados, usar um caractere curinga como * é procurar encrenca. Honestamente, é demasiado fácil fazer uma nova consulta SQL e digitar SELECT * FROM SOME-TABLE, principalmente quando você não sabe quais são os nomes dos campos da tabela. Em ambientes compartilhados, essa ação pode prejudicar imensamente os outros locatários. Você cortaria a grama às 7 horas da manhã de um domingo? Isso seria rude e desrespeitoso.

No SOQL, você especifica o nome de cada campo a ser retornado. Além disso, o demonstrativo SELECT oferecido pelo SOQL é parecido com o do SQL. Você verá que escrever consultas SOQL é muito fácil. Mas você precisa saber disso: embora o SQL e o SOQL sejam parecidos, eles não são iguais. O SOQL não é compatível com alguns recursos mais avançados oferecidos pelo demonstrativo SELECT do SQL. Na plataforma do Salesforce, porém, não precisamos de todos esses recursos extras. O SOQL oferece exatamente o que é necessário de um jeito que faz você se sentir em casa.

Criando uma consulta com o Workbench

Falando em escrever consultas SOQL, talvez você esteja se perguntando: “Mas como eu faço isso?”. Um jeito fácil de começar é usar o Workbench, a ferramenta do Salesforce baseada na web. Sabemos o quanto os desenvolvedores .NET adoram ferramentas, e essa é uma ferramenta potente que oferece vários meios para os administradores e desenvolvedores acessarem as próprias organizações usando as APIs do Force.com.

Por enquanto, vamos nos concentrar no uso do Workbench para criar consultas SOQL. Se tiver algum tempo livre, porém, explore o Workbench e confira tudo o que ele oferece. Achamos que você vai gostar. Inscreva-se em uma organização gratuita do Developer Edition (DE) e depois:

  1. Navegue até https://workbench.developerforce.com/login.php.
  2. Em Ambiente, selecione Production (Produção).
  3. Selecione a última versão da API no menu suspenso API Version.
  4. Aceite os termos de serviço e clique em Login with Salesforce (Fazer login com o Salesforce).
  5. Digite as credenciais de login e clique em Log in.
  6. Para permitir que o Workbench acesse suas informações, clique em Allow (Permitir).
  7. Depois de fazer login, selecione queries > SOQL Query.
  8. Selecione Account como objeto.

Observe que você está escolhendo um objeto em vez de uma tabela. Os dados são mantidos dentro de objetos. Estes são chamados de sObjects, que significa “Salesforce Objects”, e estão fortemente integrados à plataforma Force.com, o que torna mais fácil trabalhar com eles.

  1. Mantenha a tecla Ctrl pressionada e selecione CreatedDate, Name, Phone, Type na lista de campos. Conforme você seleciona o objeto e os campos, a consulta SOQL é criada na caixa de texto. Fica assim:
    SELECT CreatedDate, Name, Phone, Type FROM Account
    
  2. Clique em Query para ver os resultados retornados como lista. Nos resultados, procure o valor retornado no campo CreatedDate.

A má notícia é que os campos de data/hora do Salesforce são tão complicados e trabalhosos em SOQL quanto em SQL. A boa notícia é que o Salesforce oferece várias funções de data que facilitam um pouco o trabalho em SOQL. Quando for dar uma olhada na documentação, confira como o SOQL lida com os campos de moeda, porque eles também são um pouco diferentes, principalmente para as organizações que trabalham com várias moedas.

Filtrando os resultados

O SOQL tem só duas cláusulas obrigatórias: SELECT e FROM. A cláusula WHERE é opcional. Mas um bom desenvolvedor como você vai querer incluir a cláusula WHERE em praticamente toda consulta. Não faz sentido retornar mais dados do que o necessário.

Novamente, o jeito mais fácil de ver como isso funciona é usar o Workbench.

  1. Depois de fazer login no Workbench, selecione queries > SOQL Query.
  2. Selecione Contact como objeto.
  3. Mantenha a tecla Ctrl pressionada e selecione AccountId, Email, Id, LastName na lista de campos. Conforme você seleciona o objeto e os campos, a consulta SOQL é criada na caixa de texto.
  4. Clique em Query para ver os resultados retornados como lista. Fica assim:
    SELECT AccountId, Email, Id, LastName FROM Contact
    

Essa consulta retorna todos os contatos da sua organização. No caso da organização de desenvolvimento, pode ser que essa lista seja pequena. Na maioria das organizações do mundo real, porém, milhares de contatos podem ser retornados. Por isso, sempre considere filtrar as consultas SOQL com a cláusula WHERE, principalmente aquelas usadas em código do Apex.

  1. Na lista suspensa Filter results by, selecione Email.
  2. Pressione Tab para acessar o próximo campo e clique na seta da caixa suspensa para ver a lista de possíveis operadores.
  3. Selecione contains na lista, pressione Tab para ir ao campo seguinte e digite .net. A consulta construída fica assim:
    SELECT AccountId, Email, Id, LastName FROM Contact WHERE Email LIKE '%.net%'
    

Percebeu o que aconteceu? A consulta construída não inclui a palavra contains. Em vez disso, ela usa LIKE. A consulta também contém as aspas simples obrigatórias (porque Email é um campo de texto), além dos sinais de porcentagem antes e depois do termo pesquisado para indicar que é uma pesquisa com curinga.

Nota: Não é recomendável usar curingas, principalmente antes e depois do termo pesquisado, como no exemplo acima. Explicaremos melhor como criar consultas eficientes em uma unidade posterior, mas por enquanto lembre-se de evitar ao máximo pesquisas com curinga como a do exemplo.

  1. Aproveitando a ocasião, ordene os resultados por sobrenome selecionando LastName na lista suspensa nos resultados de Sort.
  2. Deixe os outros padrões como A to Z e Nulls First. Agora, a consulta ficou assim:
    SELECT AccountId,Email,Id,LastName FROM Contact
      WHERE Email LIKE '%.net%' ORDER BY LastName ASC NULLS FIRST
    
  3. Clique em Query para retornar os resultados como lista ordenada.

Algo muito importante a observar nos resultados são os dois campos de ID: AccountId e Id. Esses campos contêm uma sequência de 18 caracteres que foi atribuída pela plataforma durante a criação dos registros de Account e Contact. O campo AccountId está associado ao registro de conta (Account) ao qual foi atribuído esse contato (Contact) em particular. Em termos de SQL, é um relacionamento de chave estrangeira. O campo Id está relacionado ao contato. Em termos de SQL, ele representa a chave primária.

Enquanto tratamos dos relacionamentos de chave estrangeira, talvez você se pergunte como juntar tabelas em SOQL. Resumindo: isso não é possível. O SOQL não tem equivalente à cláusula JOIN. Mas não se preocupe, porque isso é bom.

Outro tipo de junção

Com certeza você não se surpreenderá com isso, mas o Salesforce combina objetos, ou tabelas, de um jeito um pouco diferente. Em vez de combinar tabelas com uma cláusula JOIN, você escreve algo que é chamado de consulta de relacionamento.

Conseguimos até ouvir você perguntando: “E o que é isso?”. Que bom que você perguntou.

O Salesforce usa o relacionamento pai-filho para combinar dois objetos. Assim como o SQL, o SOQL usa uma chave estrangeira para relacionar esses dois objetos, mas tem uma sintaxe de consulta diferente. Não vamos mentir. A princípio, é meio estranho usar essa nova sintaxe porque você está trabalhando com objetos em vez de linhas. Mas depois de se acostumar com o básico, você descobrirá que escrever consultas de relacionamento é bem mais fácil do que escrever junções no SQL.

No SOQL, você precisa guardar na memória dois tipos básicos de consulta de relacionamento:

  • Filho para pai
  • Pai para filhos

Cada um deles tem seu próprio funcionamento. Como você já viu alguns campos dos objetos Account e Contact, que costumam ser combinados, começaremos com esses objetos. É importante saber que a conta (Account) é o pai e o contato (Contact) é o filho.

Escrever uma consulta de filho para pai

Digamos que você queira escrever uma consulta que retorne informações de conta e contato. A primeira opção é escrever uma consulta de filho para pai. Essa consulta de relacionamento usa “notação de ponto” para acessar os dados do pai, ou seja, um ponto separa o nome do relacionamento do nome do campo consultado.

Para mostrar como isso funciona, faremos um processo passo a passo que mostra como escrever uma consulta de relacionamento que retorna uma lista de contatos, incluindo o nome da conta associada. Mas, dessa vez, em vez de usar o Workbench, usaremos a guia Query Editor (Editor de consulta) no Developer Console.

  1. Clique em ConfiguraçãoConfiguração e clique em Developer Console.
  2. No Developer Console, clique na guia Query Editor (Editor de consulta) no painel inferior.
  3. Exclua o código existente e insira o seguinte trecho:
    SELECT FirstName, LastName, Account.Name FROM Contact
    
  4. Clique em Executar.
  5. Os resultados da consulta mostram três colunas. Navegue pelos resultados. Alguns resultados no campo Account.name são nulos porque nem todos os contatos se relacionam a uma conta.

Como você provavelmente ainda está pensando em termos de SQL, imagine a situação a seguir. Se você tivesse duas tabelas SQL chamadas Account e Contact com um relacionamento de um para muitos entre elas, como escreveria uma consulta SQL que retornasse essas mesmas informações?

Você usaria uma junção, é claro. Nesse caso, seria uma junção externa direita, porque você quer uma consulta equivalente que retorne todos os contatos, até mesmo aqueles que não estão relacionados a uma conta. Provavelmente, ficaria assim:

    SELECT c.FirstName, c.LastName, a.Name FROM Account a
    RIGHT JOIN Contact c ON (c.AccountId = a.Id)

Agora, volte e observe a consulta SOQL equivalente – caso não se lembre dela, era assim:

    SELECT FirstName, LastName, Account.Name FROM Contact

A consulta SOQL parece bem mais simples, não é?

Para falar a verdade, as consultas de relacionamento podem ser um pouco complicadas, principalmente quando tentamos descobrir o nome de relacionamentos para objetos personalizados. Para saber mais sobre a conversão de consultas SQL em consultas SOQL, confira este vídeo de treinamento prático.

Algo superimportante a se considerar com esses tipos de consulta é que a notação de ponto permite percorrer até cinco níveis em sentido ascendente. Então, é possível ir do filho para o pai, o avô, o bisavô e assim por diante.

Escrevendo consultas de pai para filhos

Consultas de pai para filhos também usam o nome do relacionamento, mas ele é usado dentro de uma consulta de seleção aninhada. Assim como no caso da nossa última consulta, é melhor explicar com um exemplo.

Dessa vez, escreveremos uma consulta do objeto pai Account e faremos com que ela contenha uma consulta aninhada que também retorne informações sobre cada contato (Contact) associado.

  1. No Developer Console, clique na guia Query Editor (Editor de consulta) no painel inferior.
  2. Exclua o código existente e insira o seguinte trecho:
    SELECT Name, (Select FirstName, LastName FROM Contacts) FROM Account
    

O nome do relacionamento dentro da consulta aninhada usa o plural Contacts, em vez de Contact. É importante compreender esse detalhe, e é aí que muitas pessoas se confundem. Quando trabalhamos com consultas de relacionamento, o nome do relacionamento de pai para filho precisa estar no plural.

Quando trabalhamos com objetos personalizados, o nome do relacionamento precisa estar no plural e ter dois sublinhados e um r. Por exemplo, o nome do relacionamento do objeto personalizado My_Object__c é My_Objects__r.

  1. Clique em Executar.
  2. Os resultados da consulta mostram duas colunas. Observe na imagem a seguir como os resultados da coluna Contacts são exibidos. Como cada conta costuma estar associada a vários contatos, o nome e o sobrenome são mostrados em formato JSON.

Resultados da consulta SOQL exibidos no Developer Console

Mais uma vez, vejamos como essa consulta é escrita em SQL. No caso desta consulta, o equivalente em SQL é uma junção externa esquerda parecida com a seguinte:

    SELECT a.Name, c.FirstName, c.LastName
    FROM Account a
    LEFT JOIN Contact c ON (a.Id = c.AccountId)

A consulta SQL reúne todos os registros de conta e os contatos associados a essas contas. O resultado retornado pelo SQL não está formatado como JSON. Fora isso, as consultas SQL e SOQL produzem os mesmos resultados.

A essa altura, você deve estar se perguntando se o SOQL aceita alias. Sim, mas não da forma que você está acostumado a trabalhar em SQL. O SOQL não tem palavra-chave AS. É possível usar um alias para representar o nome do objeto nas consultas SOQL, mas, no caso dos nomes de campo, os alias só funcionam nas consultas agregadas, que veremos a seguir.

Lembre-se: para se aprofundar nesse tópico, confira o vídeo de treinamento prático através do link, na seção Resources.

E a agregação?

É mesmo, o SOQL tem agregações que funcionam do jeito que esperamos. Bem, mais ou menos. Ao trabalhar com agregações, é importante considerar que, na maioria das funções, o resultado é retornado como o tipo AggregateResult.

Quanto às funções que podem ser usadas, o SOQL conta com as relacionadas na tabela abaixo. Confira os documentos oficiais para ver as especificidades de cada função.

Funções de agregação do SOQL

Função Descrição
AVG() Retorna o valor médio de um campo numérico.
COUNT() e COUNT(fieldName) e COUNT_DISTINCT() Retornam o número de linhas que correspondem ao critério da consulta.
MIN() Retorna o valor mínimo de um campo.
MAX() Retorna o valor máximo de um campo.
SUM() Retorna a soma total de um campo numérico.

Para calcular a contagem de registros de determinada tabela chamada Account no SQL, você faria assim:

SELECT COUNT(*) FROM Account

No SOQL, essa mesma consulta fica assim:

SELECT COUNT() FROM Account

Bem parecido, não é?

Há alguns pontos que variam conforme a versão da função de contagem usada, pois cada versão retorna resultados diferentes. A função COUNT() sem nome de campo é uma versão mais antiga que foi disponibilizada antes das outras funções de agregação. Ela retorna um número inteiro e é a mais parecida com a função count(*) oferecida no SQL.

Count(fieldName) é uma versão mais recente que retorna o número de linhas, sendo que fieldName tem um valor não nulo. A diferença é que ela retorna o resultado como uma lista de AggregateResults, em vez de um valor único.

Vejamos como isso funciona na prática.

  1. No Developer Console, clique na guia Query Editor (Editor de consulta) no painel inferior.
  2. Exclua o código existente e insira o seguinte trecho:
    SELECT COUNT() FROM Account
    
  3. Clique em Executar. Os resultados da consulta mostram o número total de linhas com outro número ao lado dele.
  4. Retorne à guia Query Editor e altere a consulta para que ela fique assim:
    SELECT COUNT(Id) FROM Account
    
  5. Clique em Executar. Agora, os resultados da consulta retornam apenas uma linha e uma coluna, que mostra o número total de registros.

Até este ponto, não falamos muito de como lidar com os dados retornados pelas consultas SOQL. Mas por que adiar o inevitável? Vamos arregaçar as mangas e pôr as mãos à obra com alguns dados agregados.

Teremos de lidar com um pouco de Apex, mas não fique preocupado se esse trecho não fizer muito sentido para você. Mais tarde, nos aprofundaremos nesse assunto.

  1. No Developer Console, selecione Debug (Depurar) > Open Execute Anonymous Window (Abrir janela Executar no modo anônimo).
  2. Exclua o código existente e insira o seguinte trecho:
    List<AggregateResult> results  = [SELECT Industry, count(Id) total
        FROM Account GROUP BY Industry];
    for (AggregateResult ar :results) {
        System.debug('Industry:' + ar.get('Industry'));
        System.debug('Total Accounts:' + ar.get('total'));
    }
    

Observe como usamos um alias para representar o total junto à cláusula GROUP BY. No SOQL, só é possível usar campos de alias em consultas agregadas que usem a cláusula GROUP BY.

  1. Verifique se a opção Open Log está selecionada e clique em Execute. É carregada uma tabela que mostra o registro de execução.
  2. Selecione a opção Debug Only para ver apenas os demonstrativos de depuração no registro.

Quero saber mais

Além da cláusula GROUP BY, o SOQL oferece outras cláusulas de agrupamento, como GROUP BY ROLLUP, GROUP BY CUBE e GROUPING. Essas cláusulas são úteis para analisar os resultados quando a consulta retorna valores de várias tabelas relacionadas. GROUP BY CUBE é uma cláusula que permite somar os subtotais de todas as combinações dos campos agrupados nos resultados da consulta. Para saber mais sobre essas cláusulas, confira o documento GROUP BY em Recursos.

As funções agregadas também são compatíveis com uma cláusula HAVING opcional que é semelhante à cláusula HAVING do SQL Server; então, você vai se sentir em casa. Em essência, ela permite filtrar os resultados que uma função agregada retorna. Confira os Resources para saber mais.

Recursos

Continue a aprender de graça!
Inscreva-se em uma conta para continuar.
O que você ganha com isso?
  • Receba recomendações personalizadas para suas metas de carreira
  • Pratique suas habilidades com desafios práticos e testes
  • Monitore e compartilhe seu progresso com os empregadores
  • Conecte-se a orientação e oportunidades de carreira