Category Archives: SQL

Ubuntu Apparmor impedindo MySQL Workbench de guardar senhas

Ao tentar criar uma conexão, me deparei com um erro quando tentava armazenar a senha.

Depois de muito pesquisar identifiquei que se tratava do apparmor, um serviço que garante ou remove privilégios de programas.

O mysql-workbench foi instalado pela Loja do Ubuntu no diretório /snap.

Depois de tentar criar uma entrada pelo apparmor vi uma solução mais simples.

Na apresentação do aplicativo na loja tem as opções de permissões. Depois de acessá-la foi só garantir ao programa a letira/edição de senhas.

Permissões para o apparmor

Instalação MySQL via Docker com acesso pelo workbench

O que parece ser trivial pode acabar demandando configurações extras além do que escrito no Docker hub.

No guia de instalação em https://hub.docker.com/r/mysql/mysql-server o comando docker run permite o acesso via -it com docker exec sem problemas.

O problema surge quando necessário acessar via workbench, o que é mais usual.

O problema: o usuário root com senha padrão gerada na instalação não tem permissão para acessar pelo localhost via TCP/IP. Que no caso do docker é tido como uma conexão remota.

Solução: primeiramente foi necessário expor a porta 3306 da imagem. Também aproveitei para setar uma senha por meio de parâmetro no comando run.

docker run --name mysql-server -e MYSQL_ROOT_PASSWORD=password-p3306:3306 -d mysql/mysql-server:5.6

Após a imagem instalada foi necessário garantir privilégios ao usuário root para acesso de qualquer host por meio dos comandos a seguir:

docker exec -it mysql-server mysql -uroot -p

grant all privileges on *.* to 'root'@'%' identified by 'password' with grant option;

Para entender melhor o esquema de senhas e hash do MySQL segue o tópico da documentação: https://dev.mysql.com/doc/refman/5.6/en/password-hashing.html

Depois de garantido o acesso é só configurar a conexão pelo workbench com o host localhost e senha previamente criada.

E pronto!

Cross Apply no Sql Server

Precisava criar um relatório que listasse a média das 3 primeiras vendas de clientes novos do ano atual (2018).

A query então deve conter 2 tabelas: cliente e pedidos. O filtro do cliente e dos pedidos é básico. O difícil é fazer com que os pedidos recebam o código do cliente do Select e aplicá-lo na query que traz os pedidos.

A princípio tentei fazer um Join, depois uma subquery mas por conta da operador TOP não conseguia. Logicamente o TOP 3 retornaria apenas três registros da tabela pedido e não três pedidos da tabela pedido para cada cliente da query principal.

Pesquisando um pouco eu cheguei a uma query com dois joins que não deu muito certo, mas a lógica até que é boa:

SELECT
A1_COD,
Z7.Z7_CONSULT,
Z7.Z7_NUM,
Z7.Z7_DTFECHA,
B.*
FROM
SA1010 A1
LEFT JOIN (SELECT TOP 3 Z7_NUM, Z7_CONSULT FROM SZ7010 WHERE D_E_L_E_T_ = '' AND Z7_STATUS = 'F' ORDER BY Z7_DTFECHA) B ON A1.A1_COD = B.Z7_CONSULT
LEFT JOIN SZ7010 Z7 ON Z7.Z7_NUM = B.Z7_NUM
WHERE
A1.D_E_L_E_T_ = '' AND
A1.A1_DTCAD > 20180101 AND
A1.A1_STATUS = 1
ORDER BY
A1.A1_COD

Porém não funcionou. : (

A solução foi a utilizar o operador CROSS APPLY, que utiliza uma query como entrada para outra e as uni. Analisando o problema das novatas em questão fica fácil entender o funcionamento. Veja a query:

SELECT
A1_COD,
A1_NOME,
A1_DTCAD,
CA.*
FROM
SA1010 A1
CROSS APPLY (
SELECT TOP 3
Z7_NUM,
Z7_CONSULT,
Z7_QTDCOMD,
Z7_REGIAO,
Z7_DTFECHA
FROM
SZ7010 B
WHERE
B.D_E_L_E_T_ = '' AND
B.Z7_STATUS = 'F' AND
B.Z7_SERIE <> 'DIR' AND
A1.A1_COD = B.Z7_CONSULT
ORDER BY
Z7_DTFECHA) CA
WHERE
A1.D_E_L_E_T_ = '' AND
A1.A1_DTCAD > 20180101 AND
A1.A1_STATUS = 1
ORDER BY
A1.A1_COD

A query então traz os 3 primeiros pedidos para cada cliente retornado na query inicial e junta os resultados.

109244 <<NOME>> 20180102 842355 109244 23 000122 20180203
109244 <<NOME>> 20180102 844817 109244 45 000122 20180312
109244 <<NOME>> 20180102 862112 109244 54 000122 20180419
109255 <<NOME>> 20180102 839520 109255 17 000072 20180204
109255 <<NOME>> 20180102 854113 109255 28 000072 20180313
109255 <<NOME>> 20180102 861392 109255 42 000072 20180417
109260 <<NOME>> 20180105 838082 109260 25 000093 20180205
109260 <<NOME>> 20180105 851091 109260 41 000093 20180314
109260 <<NOME>> 20180105 863113 109260 41 000093 20180418

Depois disso apenas alterei a query para que ao invés dos três pedidos retornasse a média de peças vendidas e pronto. Relatório concluido com performance e acuracidade.

Seguem dois links que tratam do operador Cross Apply que me ajudaram:

https://www.tutorialti.com/2015/02/o-que-e-cross-apply-sql-server.html

http://blog.dbaacademy.com.br/sql-server-cross-apply-e-cross-join/

Espero ter ajudado e até!