Azure SQL Database – Como fazer um join entre tabelas de bases diferentes?
Fala Pessoal,
Continuando a série de posts sobre o Azure SQL Database, no meu dia a dia de Consultorias é bem comum ver sistemas que utilizam mais de uma base de dados para realizar operações.
E no Azure SQL Database? Isso funciona?
Vamos testar juntos?
Criei duas bases (database01 e database02) no meu portal do azure conforme pode ser visto abaixo:
Em seguida criei uma tabela em cada uma dessas bases de dados e populei com algumas informações:
Database01:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
CREATE TABLE sqlfamily( ID int IDENTITY(1, 1) NOT NULL PRIMARY KEY, Nome VARCHAR(50), Mais_Conhecido_Como VARCHAR(100) ) INSERT INTO sqlfamily(Nome, Mais_Conhecido_Como) VALUES ( 'Fabricio Lima' ,'Fabricio Lima'), ( 'Fabiano Amorim' ,'Expert em vídeos fakes de futebol'), ( 'Luiz Gareth','Morango do Nordeste' ), ( 'Arthur Luz', 'Vagalume' ), ( 'Edvaldo Castro', 'Oldvaldo Castro' ) |
Database02:
1 2 3 4 5 6 7 8 9 10 11 12 |
CREATE TABLE sqlfamily( ID int IDENTITY(1, 1) NOT NULL PRIMARY KEY, Nome VARCHAR(50), Hobby VARCHAR(100)) INSERT INTO sqlfamily(Nome, Hobby) VALUES ( 'Fabricio Lima' ,'Futebol, Corrida, Seriados, Viajar, Rock com a galera, ...'), ( 'Fabiano Amorim' ,'Desafinar uma guitarra...'), ( 'Luiz Gareth','Tomar aquela batida de morango...' ), ( 'Edvaldo Castro', 'Jogar dominó na praça...' ), ( 'Arthur Luz', 'Ilimunar Ambientes...' ) |
Após criar e popular as duas tabelas com mesmo nome, mas em bases diferentes, vamos tentar fazer um join nelas para ver o que acontece:
Vixe… Deu ruim… E agora Fabrício???
Pois é… No Azure SQL Database não temos suporte para realizar um CROSS database igual realizamos em nossas instâncias On-Premise. Só no Azure SQL Managed Instance que isso será possível.
Mas… Contudo…Entretanto…Todavia…
Conseguimos chegar perto disso com a utilização de EXTERNAL TABLES.
Para fazer isso, vamos executar TODOS os comandos abaixo na database01.
Primeiro temos que criar uma master key:
1 |
CREATE MASTER KEY ENCRYPTION BY PASSWORD = 'senhadificil->123456' |
Quando criei a database02, eu também criei um login chamado dba_admin para acessar essa base.
Dito isso, vamos criar uma credencial para acessar a database02 com esse login:
1 |
CREATE DATABASE SCOPED CREDENTIAL Db02Credential WITH IDENTITY = 'dba_admin', SECRET = 'senha_user_dba_admin' |
O próximo passo é criar um DATA SOURCE que vamos utilizar para acessar o servidor lógico e a database02. Utilizamos a credencial do passo anterior:
1 2 3 4 5 6 |
CREATE EXTERNAL DATA SOURCE Db02DataSource WITH (TYPE = RDBMS, --Query LOCATION = 'srvfabriciolimasolucoes.database.windows.net', --Servidor logico no azure onde está a base database02 DATABASE_NAME = 'database02', --base que queremos acessar com a credencial Db02Credential CREDENTIAL = Db02Credential --Db02Credential - credencial que criamos para acessar a base database02 ) ; |
Finalmente vamos criar nossa EXTERNAL TABLE:
1 2 3 4 5 6 7 8 9 10 11 |
CREATE EXTERNAL TABLE dbo.sqlfamily_ext( --ID int, --Conseguimos retornar menos colunas em uma external table. Ela fica parecida com uma view. Não vou usar a coluna ID. Nome VARCHAR(50), --se criar a coluna na external table com um tipo de dados diferente, da erro. Hobby VARCHAR(100) ) WITH ( DATA_SOURCE = Db02DataSource, SCHEMA_NAME = 'dbo', --Schema da tabela na database02 OBJECT_NAME = 'sqlfamily' --Nome da tabela que eu quero referenciar na database02 ); |
Essa EXTERNAL TABLE é como se fosse um objeto da base database01, tanto que não conseguimos criar ela com o mesmo nome sqlfamily. Tive que colocar um sufixo “_ext” no nome para diferenciar o nome dos objetos.
Podemos conferir os objetos que criamos nas DMV’s abaixo:
1 2 3 4 |
SELECT * FROM sys.symmetric_keys select * from sys.external_data_sources; select * from sys.database_scoped_credentials select * from sys.external_tables; |
Criada nossa External Table, agora conseguimos usar ela para acessar a tabela sqlfamily da database02.
Nosso JOIN fica da seguinte forma:
1 2 3 4 5 |
SELECT A.nome, A.Mais_Conhecido_Como, B.Hobby FROM database01.dbo.sqlfamily A JOIN database01.dbo.sqlfamily_ext B ON A.Nome = B.nome |
Agora conseguimos acessar a database02 e pegar a informação da coluna Hobby:
Essa EXTERNAL TABLE é estática Fabrício? Se eu fizer novos inserts na database02 eles vão ser retornados automaticamente?
A external table é como se fosse um Linked Server para a database02. Ou seja, novos inserts serão retornados normalmente por esse join.
Vamos inserir uma linha em cada base para conferir.
1 2 3 4 5 6 7 |
--Rodar na database01 INSERT INTO sqlfamily(Nome, Mais_Conhecido_Como) VALUES ( 'Diego Nogare' ,'NogareDBA') --Rodar na database02 INSERT INTO sqlfamily(Nome, Hobby) VALUES ( 'Diego Nogare' ,'Fazer shrink em arquivos MDF...') |
Executando o JOIN novamente, nossas linhas que foram inseridas nas duas databases já são retornadas:
Legal Fabrício. Eu consigo fazer um insert nessa EXTERNAL TABLE?
Resposta:
Não conseguimos fazer um insert. Ela é utilizada apenas para consultas.
E a performance disso Fabrício? É boa?
Excelente pergunta.
Você já deve imaginar a resposta, mas vamos deixar os detalhes para um próximo post. Aguardem!
Posts Relacionados:
- https://www.fabriciolima.net/blog/2018/07/10/azure-sql-database-funcao-getdate-com-valor-errado-no-azure-e-isso-mesmo/
- www.fabriciolima.net/blog/2018/03/17/azure-sql-db-managed-instance-introducao/
Gostou da dica?
Curta, comente, compartilhe com os coleguinhas…
Assine meu canal no Youtube e curta minha Página no Facebook para receber Dicas de Leituras e Eventos sobre SQL Server.
Abraços,
Fabrício Lima
Microsoft Data Platform MVP
Consultor e Instrutor SQL Server
Trabalha com SQL Server desde 2006