Pesquisa de site

Como Executar Consultas MySQL a Partir da Linha de Comando do Linux


Se você é responsável por gerenciar um servidor de banco de dados, de vez em quando pode ser necessário executar uma consulta e inspecioná-la cuidadosamente. Embora você possa fazer isso a partir do shell do MySQL/MariaDB, esta dica permitirá que você execute as consultas do MySQL/MariaDB diretamente usando a linha de comando do Linux E salve a saída em um arquivo para inspeção posterior (isso é particularmente útil se a consulta retornar muitos registros).

Vamos olhar alguns exemplos simples de execução de consultas MYSQL diretamente da linha de comando antes de passarmos para uma consulta mais avançada.

Configurando Bancos de Dados de Exemplo

Antes de mergulharmos nos comandos, vamos configurar os bancos de dados de exemplo com os quais trabalharemos ao longo deste guia, para que você possa acompanhar e praticar essas técnicas em seu próprio sistema.

Criando o banco de dados tecmintdb

Primeiro, vamos criar o banco de dados tecmintdb e a tabela tutorials:

mysql -u root -p -e "CREATE DATABASE IF NOT EXISTS tecmintdb;"

Em seguida, para criar uma tabela de banco de dados chamada tutorials no banco de dados tecmintdb, execute o comando abaixo:

sudo mysql -u root -p tecmintdb << 'EOF'
CREATE TABLE IF NOT EXISTS tutorials (
    tut_id INT NOT NULL AUTO_INCREMENT,
    tut_title VARCHAR(100) NOT NULL,
    tut_author VARCHAR(40) NOT NULL,
    submission_date DATE,
    PRIMARY KEY (tut_id)
);

INSERT INTO tutorials (tut_title, tut_author, submission_date) VALUES
('Getting Started with Linux', 'John Smith', '2024-01-15'),
('Advanced Bash Scripting', 'Sarah Johnson', '2024-02-20'),
('MySQL Database Administration', 'Mike Williams', '2024-03-10'),
('Apache Web Server Configuration', 'Emily Brown', '2024-04-05'),
('Python for System Administrators', 'David Lee', '2024-05-12'),
('Docker Container Basics', 'Lisa Anderson', '2024-06-18'),
('Kubernetes Orchestration', 'Robert Taylor', '2024-07-22'),
('Linux Security Hardening', 'Jennifer Martinez', '2024-08-30');
EOF

Verifique se os dados foram inseridos:

sudo mysql -u root -p -e "USE tecmintdb; SELECT * FROM tutorials;"

Verificar Dados da Tabela do Banco de Dados MySQL

Criando o banco de dados de funcionários

Agora, vamos criar um banco de dados employees mais complexo com várias tabelas relacionadas, este é o banco de dados que usaremos para os exemplos de consultas mais avançadas:

sudo mysql -u root -p -e "CREATE DATABASE IF NOT EXISTS employees;"

Crie a tabela employees:

sudo mysql -u root -p employees << 'EOF'
CREATE TABLE IF NOT EXISTS employees (
    emp_no INT NOT NULL AUTO_INCREMENT,
    birth_date DATE NOT NULL,
    first_name VARCHAR(14) NOT NULL,
    last_name VARCHAR(16) NOT NULL,
    gender ENUM('M','F') NOT NULL,
    hire_date DATE NOT NULL,
    PRIMARY KEY (emp_no)
);

INSERT INTO employees (emp_no, birth_date, first_name, last_name, gender, hire_date) VALUES
(10001, '1953-09-02', 'Georgi', 'Facello', 'M', '1984-06-02'),
(10002, '1964-06-02', 'Bezalel', 'Simmel', 'F', '1984-11-21'),
(10003, '1959-12-03', 'Parto', 'Bamford', 'M', '1984-08-28'),
(10004, '1954-05-01', 'Chirstian', 'Koblick', 'M', '1984-12-01'),
(10005, '1955-01-21', 'Kyoichi', 'Maliniak', 'M', '1984-09-15'),
(10006, '1953-04-20', 'Anneke', 'Preusig', 'F', '1985-02-18'),
(10007, '1957-05-23', 'Tzvetan', 'Zielinski', 'F', '1985-03-20'),
(10008, '1958-02-19', 'Saniya', 'Kalloufi', 'M', '1984-07-11'),
(10009, '1952-04-19', 'Sumant', 'Peac', 'F', '1985-02-18'),
(10010, '1963-06-01', 'Duangkaew', 'Piveteau', 'F', '1984-08-24');
EOF

Crie a tabela salaries:

sudo mysql -u root -p employees << 'EOF'
CREATE TABLE IF NOT EXISTS salaries (
    emp_no INT NOT NULL,
    salary INT NOT NULL,
    from_date DATE NOT NULL,
    to_date DATE NOT NULL,
    PRIMARY KEY (emp_no, from_date),
    FOREIGN KEY (emp_no) REFERENCES employees(emp_no) ON DELETE CASCADE
);

INSERT INTO salaries (emp_no, salary, from_date, to_date) VALUES
(10001, 60117, '1984-06-02', '1985-06-02'),
(10001, 62102, '1985-06-02', '1986-06-02'),
(10001, 66074, '1986-06-02', '9999-01-01'),
(10002, 65828, '1984-11-21', '1985-11-21'),
(10002, 65909, '1985-11-21', '9999-01-01'),
(10003, 40006, '1984-08-28', '1985-08-28'),
(10003, 43616, '1985-08-28', '9999-01-01'),
(10004, 40054, '1984-12-01', '1985-12-01'),
(10004, 42283, '1985-12-01', '9999-01-01'),
(10005, 78228, '1984-09-15', '1985-09-15'),
(10005, 82507, '1985-09-15', '9999-01-01'),
(10006, 40000, '1985-02-18', '1986-02-18'),
(10006, 43548, '1986-02-18', '9999-01-01'),
(10007, 56724, '1985-03-20', '1986-03-20'),
(10007, 60605, '1986-03-20', '9999-01-01'),
(10008, 46671, '1984-07-11', '1985-07-11'),
(10008, 48584, '1985-07-11', '9999-01-01'),
(10009, 60929, '1985-02-18', '1986-02-18'),
(10009, 64604, '1986-02-18', '9999-01-01'),
(10010, 72488, '1984-08-24', '1985-08-24'),
(10010, 74057, '1985-08-24', '9999-01-01');
EOF

Crie a tabela departments para junções mais complexas:

sudo mysql -u root -p employees << 'EOF'
CREATE TABLE IF NOT EXISTS departments (
    dept_no CHAR(4) NOT NULL,
    dept_name VARCHAR(40) NOT NULL,
    PRIMARY KEY (dept_no),
    UNIQUE KEY (dept_name)
);

INSERT INTO departments (dept_no, dept_name) VALUES
('d001', 'Marketing'),
('d002', 'Finance'),
('d003', 'Human Resources'),
('d004', 'Production'),
('d005', 'Development'),
('d006', 'Quality Management');
EOF

Crie a tabela dept_emp para vincular employees aos departments:

sudo mysql -u root -p employees << 'EOF'
CREATE TABLE IF NOT EXISTS dept_emp (
    emp_no INT NOT NULL,
    dept_no CHAR(4) NOT NULL,
    from_date DATE NOT NULL,
    to_date DATE NOT NULL,
    PRIMARY KEY (emp_no, dept_no),
    FOREIGN KEY (emp_no) REFERENCES employees(emp_no) ON DELETE CASCADE,
    FOREIGN KEY (dept_no) REFERENCES departments(dept_no) ON DELETE CASCADE
);

INSERT INTO dept_emp (emp_no, dept_no, from_date, to_date) VALUES
(10001, 'd005', '1984-06-02', '9999-01-01'),
(10002, 'd005', '1984-11-21', '9999-01-01'),
(10003, 'd004', '1984-08-28', '9999-01-01'),
(10004, 'd004', '1984-12-01', '9999-01-01'),
(10005, 'd003', '1984-09-15', '9999-01-01'),
(10006, 'd005', '1985-02-18', '9999-01-01'),
(10007, 'd004', '1985-03-20', '9999-01-01'),
(10008, 'd005', '1984-07-11', '9999-01-01'),
(10009, 'd006', '1985-02-18', '9999-01-01'),
(10010, 'd006', '1984-08-24', '9999-01-01');
EOF

Verifique se tudo está configurado corretamente:

sudo mysql -u root -p -e "USE employees; SHOW TABLES;"

Verificar a Configuração do Nosso Banco de Dados MySQL

Agora você configurou ambos os bancos de dados com dados de exemplo e pode acompanhar todos os exemplos deste guia. O banco de dados tecmintdb é perfeito para consultas simples, enquanto o banco de dados employees permite praticar operações mais complexas, como joins e agregações.

Execução Básica de Consulta

Para visualizar todos os bancos de dados no seu servidor, você pode emitir o seguinte comando:

sudo mysql -u root -p -e "show databases;"

Em seguida, para criar uma tabela de banco de dados chamada tutorials no banco de dados tecmintdb, execute o comando abaixo:

sudo mysql -u root -p -e "USE tecmintdb; CREATE TABLE tutorials(tut_id INT NOT NULL AUTO_INCREMENT, tut_title VARCHAR(100) NOT NULL, tut_author VARCHAR(40) NOT NULL, submissoin_date DATE, PRIMARY KEY (tut_id));"

Salvando os Resultados de uma Consulta MySQL em um Arquivo

Usaremos o seguinte comando e encaminharemos a saída para o comando tee, seguido pelo nome do arquivo onde queremos armazenar a saída.

Para ilustração, usaremos um banco de dados chamado employees e um join simples entre as tabelas employees e salaries. No seu caso, basta digitar a consulta SQL entre as aspas e pressionar Enter.

Observe que você será solicitado a inserir a senha do usuário do banco de dados:

sudo mysql -u root -p -e "USE employees; SELECT DISTINCT A.first_name, A.last_name FROM employees A JOIN salaries B ON A.emp_no = B.emp_no WHERE hire_date < '1985-01-31';" | tee queryresults.txt

Visualize os resultados da consulta com a ajuda do comando cat.

cat queryresults.txt

Executar Consultas MySQL/MariaDB pelo Linha de Comando

Com os resultados da consulta em arquivos de texto simples, você pode processar os registros mais facilmente usando outras utilidades de linha de comando. Agora que você viu o básico, vamos explorar algumas técnicas mais avançadas que tornarão seu trabalho com bancos de dados na linha de comando ainda mais eficiente.

Formatando a Saída para Melhor Legibilidade

O formato de tabela padrão é ótimo para visualização no terminal, mas às vezes você precisa de formatos diferentes. Você pode exibir os resultados em formato vertical, o que é particularmente útil ao lidar com tabelas que possuem muitas colunas:

sudo mysql -u root -p -e "USE employees; SELECT * FROM employees LIMIT 1\G"

O \G no final exibe cada linha verticalmente em vez de em uma tabela, então em vez de ver uma tabela horizontal compacta, você obtém algo como:

*************************** 1. row ***************************
    emp_no: 10001
birth_date: 1953-09-02
first_name: Georgi
 last_name: Facello
    gender: M
 hire_date: 1984-06-02

Exportando para o formato CSV

Quando você precisa importar resultados de consultas para aplicativos de planilha ou outras ferramentas, o formato CSV é a sua melhor opção:

sudo mysql -u root -p -e "USE employees; SELECT first_name, last_name, hire_date FROM employees WHERE hire_date < '1985-01-31';" | sed 's/\t/,/g' > employees.csv

Isso envia a saída através do sed para substituir tabulações por vírgulas, criando um arquivo CSV adequado que abre corretamente no Excel, LibreOffice Calc ou qualquer outro software de planilhas.

Executando Consultas Sem Solicitação de Senha

Se você está automatizando tarefas de banco de dados com jobs do cron ou scripts, você não vai querer digitar senhas manualmente toda vez; é aí que entram os arquivos de configuração do MySQL.

Crie um arquivo em ~/.my.cnf com suas credenciais:

[client]
user=root
password=your_password_here

Então proteja-o para que apenas você possa lê-lo:

chmod 600 ~/.my.cnf

Agora você pode executar consultas sem a opção -p e sem receber um prompt:

mysql -e "SHOW DATABASES;"

Apenas lembre-se, armazenar senhas em arquivos de texto simples tem implicações de segurança, portanto, use essa abordagem apenas em servidores onde você controla o acesso e considere usar os métodos de autenticação mais seguros do MySQL em ambientes de produção.

Executando Consultas Complexas de Múltiplas Linhas

Às vezes, suas consultas são complexas demais para serem escritas em uma única linha de comando, especialmente quando você está lidando com múltiplos joins, subconsultas ou condições complexas.

Você pode colocar seu SQL em um arquivo e executá-lo:

cat > complex_query.sql << 'EOF'
USE employees;
SELECT 
    e.first_name,
    e.last_name,
    d.dept_name,
    s.salary
FROM employees e
INNER JOIN dept_emp de ON e.emp_no = de.emp_no
INNER JOIN departments d ON de.dept_no = d.dept_no
INNER JOIN salaries s ON e.emp_no = s.emp_no
WHERE e.hire_date BETWEEN '1985-01-01' AND '1985-12-31'
    AND s.from_date = (
        SELECT MAX(from_date) 
        FROM salaries 
        WHERE emp_no = e.emp_no
    )
ORDER BY s.salary DESC
LIMIT 10;
EOF

Agora execute.

sudo mysql -u root -p < complex_query.sql > top_earners_1985.txt

Essa abordagem mantém suas consultas organizadas e reutilizáveis, e você pode controlá-las por versão com o git assim como qualquer outro código.

Processamento em Lote de Múltiplas Consultas

Se você precisar executar várias consultas relacionadas e salvar cada resultado separadamente, você pode escrever um script para isso:

#!/bin/bash

QUERIES=(
    "SELECT COUNT(*) as total_employees FROM employees"
    "SELECT dept_name, COUNT(*) as employee_count FROM dept_emp de JOIN departments d ON de.dept_no = d.dept_no GROUP BY dept_name"
    "SELECT YEAR(hire_date) as year, COUNT(*) as hires FROM employees GROUP BY YEAR(hire_date) ORDER BY year"
)

FILENAMES=(
    "total_count.txt"
    "dept_distribution.txt"
    "yearly_hires.txt"
)

for i in "${!QUERIES[@]}"; do
    echo "Running query $((i+1))..."
    mysql -u root -p -e "USE employees; ${QUERIES[$i]}" > "${FILENAMES[$i]}"
    echo "Results saved to ${FILENAMES[$i]}"
done

Salve isso como um script, torne-o executável com chmod +x e você terá uma ferramenta de consulta em lote reutilizável.

Monitoramento de Consultas de Longa Duração

Quando você está executando consultas que podem levar um tempo, você quer ver o progresso ou pelo menos saber que ainda estão funcionando.

Combine sua consulta com a saída de status:

(sudo mysql -u root -p -e "USE employees; SELECT COUNT(*) FROM large_table WHERE complex_condition;" && echo "Query completed at $(date)") | tee query_log.txt

Para consultas ainda mais longas, execute-as em segundo plano e monitore a lista de processos do MySQL:

sudo mysql -u root -p -e "USE employees; SELECT * FROM massive_table;" > output.txt &
sudo watch -n 5 'mysql -u root -p -e "SHOW PROCESSLIST\G" | grep -A 5 "SELECT"'

Isso executa sua consulta em segundo plano enquanto exibe a lista de processos a cada 5 segundos, para que você possa ver que ela ainda está funcionando e quanto progresso foi feito.

Filtrando e Processando Resultados

Uma vez que você tenha os resultados da consulta em um arquivo de texto, pode usar ferramentas padrão do Linux para processá-los ainda mais. Aqui estão alguns padrões úteis:

Conte o número de linhas de resultado (excluindo o cabeçalho):

tail -n +2 queryresults.txt | wc -l

Extraia colunas específicas usando awk:

awk '{print $1, $3}' queryresults.txt

Procurar por padrões específicos nos resultados:

grep -i "engineering" dept_distribution.txt

Classificar resultados por uma coluna numérica:

tail -n +2 queryresults.txt | sort -k3 -n

Manipulação de Caracteres Especiais e Grandes Conjuntos de Dados

Quando seus dados contêm caracteres especiais, tabulações ou quebras de linha, a saída padrão pode ficar bagunçada, então use as opções --batch e --raw para uma saída mais limpa:

sudo mysql -u root -p --batch --raw -e "SELECT description FROM products WHERE category='electronics';" > products.txt

Para consultas que retornam milhões de linhas, você pode enfrentar problemas de memória; em vez de carregar tudo na memória, faça o streaming dos resultados:

sudo mysql -u root -p --quick -e "SELECT * FROM huge_table;" | gzip > huge_results.txt.gz

A opção --quick diz ao MySQL para recuperar as linhas uma de cada vez em vez de armazenar em buffer todo o conjunto de resultados, e enviar para gzip comprime a saída em tempo real, economizando espaço em disco.

Criando Backups Rápidos de Banco de Dados

Embora isso não seja tecnicamente executar consultas, você pode usar técnicas semelhantes de linha de comando para criar dumps rápidos de banco de dados com o comando mysqldump.

sudo mysqldump -u root -p employees | gzip > employees_backup_$(date +%Y%m%d).sql.gz

Ou faça backup apenas de tabelas específicas:

sudo mysqldump -u root -p employees employees salaries | gzip > critical_tables_$(date +%Y%m%d).sql.gz

Agendamento de Relatórios Automatizados

Combine tudo o que abordamos para criar relatórios diários automatizados usando cron com a ajuda do seguinte script bash.

#!/bin/bash
REPORT_DATE=$(date +%Y-%m-%d)
REPORT_FILE="/var/reports/daily_stats_${REPORT_DATE}.txt"

{
    echo "Database Statistics Report - ${REPORT_DATE}"
    echo "=========================================="
    echo
    
    echo "Total Employees:"
    mysql -e "USE employees; SELECT COUNT(*) FROM employees;"
    echo
    
    echo "New Hires This Month:"
    mysql -e "USE employees; SELECT COUNT(*) FROM employees WHERE MONTH(hire_date) = MONTH(CURRENT_DATE()) AND YEAR(hire_date) = YEAR(CURRENT_DATE());"
    echo
    
    echo "Department Distribution:"
    mysql -e "USE employees; SELECT d.dept_name, COUNT(*) as count FROM dept_emp de JOIN departments d ON de.dept_no = d.dept_no WHERE de.to_date = '9999-01-01' GROUP BY d.dept_name ORDER BY count DESC;"
    
} > "$REPORT_FILE"

echo "Report generated: $REPORT_FILE"

Adicione ao cron para executar diariamente às 6h:

0 6 * * * /usr/local/bin/generate_db_report.sh
Resumo

Compartilhamos várias dicas de Linux que você, como administrador de sistemas, pode achar úteis quando se trata de automatizar suas tarefas diárias no Linux ou realizá-las com mais facilidade.

A principal lição aqui é que você nem sempre precisa abrir o shell do MySQL ou usar ferramentas GUI pesadas para trabalhar com seus bancos de dados; a linha de comando oferece velocidade, capacidades de automação e a possibilidade de integrar operações de banco de dados aos seus scripts e fluxos de trabalho existentes.

Você tem alguma outra dica que gostaria de compartilhar com o restante da comunidade? Se sim, por favor, faça isso usando o formulário de comentários abaixo. :