Clique no banner para conhecer e adquirir o meu treinamento de Bancos de Dados no Azure

SQL Server e Power BI: Como carregar dados de Stored Procedure no SQL Server com DirectQuery

Post Views 6,926 views
Reading time 7 minutes

Introduction

Hey guys!

Nesse post eu gostaria de compartilhar com vocês uma situação que aconteceu comigo durante uma consultoria a um cliente, onde ele tinha uma necessidade de ter um relatório do Power BI conectado à uma base de dados SQL Server, mas a fonte de dados era uma Stored Procedure que fazia várias transformações de dados internamente e retornava um conjunto de dados.

O problema é que esse cliente queria que a atualização dos dados fosse em tempo real, ou seja, abriu o relatório, aplicou um filtro ou fez uma interação com o gráfico, os dados teriam que ser atualizados através da execução dessa Stored Procedure. E acontece que o Power BI NÃO tem suporte à isso 🙂

Caso você queira aprender mais sobre o DirectQuery do Power BI, veja esse conteúdo aqui.

Esse é o código da Stored Procedure que eu gostaria de executar como DirectQuery no Power BI:

Resultado esperado da execução:

simulating the problem

Clique aqui para visualizar este conteúdo
O primeiro passo para tentar executar uma procedure com DirectQuery é selecionar esse tipo de armazenamento, digitar o nome do servidor e clicar no botão OK para carregar a lista de objetos:

Na listagem dos objetos, podemos observar que ele só lista tabelas, views e funções:

Vou voltar para a tela de conexão e tentar inserir o comando de execução manualmente na tela de instrução SQL:

Mas ao tentar fazer isso, é retornada uma mensagem de erro:

Vamos tentar de novo, sem colocar a instrução EXEC:

Opa! Parece que carregou!

Parecia que ia funcionar, mas ao tentar carregar os dados..

O PowerQuery até mostra os dados do banco, mas não me deixa carregar para o modelo, mostrando a mensagem do print anterior.

Solução #1 – OpenRowSet

Clique aqui para visualizar este conteúdo
A primeira “solução” que vou apresentar pra vocês, é a utilização do OpenRowSet para executar a procedure no servidor local e retornar os dados. Como essa acaba sendo uma instrução SELECT, o Power BI deve aceitar a execução:

O primeiro ponto a ser considerado, é essa mensagem de erro abaixo:

Msg 15281, Level 16, State 1, Line 43
SQL Server blocked access to STATEMENT ‘OpenRowset/OpenDatasource’ of component ‘Ad Hoc Distributed Queries’ because this component is turned off as part of the security configuration for this server. A system administrator can enable the use of ‘Ad Hoc Distributed Queries’ by using sp_configure. For more information about enabling ‘Ad Hoc Distributed Queries’, search for ‘Ad Hoc Distributed Queries’ in SQL Server Books Online.

Essa mensagem nada mais representa que o recurso de OpenRowset/OpenDatasource está desativado na instância (por padrão, essa configuração vem desativada devido à motivos de segurança). Para utilizar o Openrowset, você precisará habilitar esse recurso, e o seu DBA provavelmente não irá gostar isso:

Uma vez habilitado, agora basta executar o nosso comando de SELECT. E nos deparamos com a 2ª mensagem de erro:

Msg 11526, Level 16, State 1, Procedure sys.sp_describe_first_result_set, Line 1 [Batch Start Line 53] The metadata could not be determined because statement ‘INSERT INTO #Tabelas_Internas
VALUES(965578478, ‘Tabela de Confirmados’), (1013578649, ‘Tabela’ in procedure ‘stpPBI_DirectQuery_Procedure’ uses a temp table.

Agora o SQL Server está reclamando das tabelas temporárias utilizadas na Stored Procedure. Vamos fazer algumas alterações na procedure e substituir as tabelas temporárias (#tabela) por variáveis do tipo tabela (@tabela):

E vamos tentar novamente. Outra mensagem de erro:

Msg 7357, Level 16, State 1, Line 54
Cannot process the object “EXEC eventos.dbo.stpPBI_DirectQuery_Procedure”. The OLE DB provider “SQLNCLI11” for linked server “(null)” indicates that either the object has no columns or the current user does not have permissions on that object.

Para resolver esse problema, vamos incluir a instrução “SET NOCOUNT ON” no começo da Stored Procedure, para que o comando de OPENROWSET consiga identificar corretamente os dados retornados e não sofra interferências com o retorno da quantidade de linhas retornadas:

Com essa alteração, o nosso comando de SELECT foi executado corretamente:

Vamos voltar para o Power BI, repetir todo o processo e agora podemos carregar os dados normalmente pra dentro do Power BI:

E está lá! Estamos consumindo uma Stored Procedure usando DirectQuery no Power BI!

Solução #2 – Utilizando Table-Valued Function

Clique aqui para visualizar este conteúdo
A segunda forma de conseguir consultar objetos complexos utilizando DirectQuery no Power BI, é substituindo a Stored Procedure por uma Table-Valued Function, que acaba sendo uma forma bem mais elegante e correta de realizar essa consulta do que a forma anterior.

Segue o código da função, que realiza exatamente a mesma coisa da Stored Procedure anterior:

Após a criação da função, selecione a opção “Obter Dados” > “SQL Server” e escreva o comando de SELECT para ler os dados da função:

Após clicar no botão de “OK”, seus dados estarão sendo carregados normalmente:

Basta clicar no já conhecido botão “Fechar e Aplicar” e a nossa tarefa está feita.

Limitações

O uso de Stored Procedures ou funções para conectar a dados com DirectQuery tem algumas limitações as quais posso destacar:

  • Não é possível passar parâmetros dinâmicos para Stored Procedure ou Table-valued function dinamicamente
  • Ao utilizar um slicer, por exemplo, os dados são executados no banco de dados para depois filtrar os dados retornados utilizando os slicers, portanto, isso talvez gere problemas de performance em tabelas muito grandes
  • Diferente do relatório paginado, que recalcula todo o conjunto de dados após interações com os usuários, o Power BI não atualiza os dados na fonte a cada filtro aplicado ou interação no DirectQuery
  • As 2 soluções vão apresentar problemas de performance em grandes volumes de dados
  • As 2 técnicas apresentadas exigem um certo conhecimento em T-SQL e só funciona no SQL Server. Talvez isso seja um pouco complexo de trabalhar para um usuário de negócio que não é de TI
  • O DirectQuery por si só, já possui algumas limitações que pode você entrar acessando esse link aqui

And that's it, folks!
Espero que tenham gostado dessa dica, que isso seja útil pra você em alguma necessidade específica e até a próxima!