Ako spúšťať MySQL dotazy z príkazového riadku Linuxu


Ak máte na starosti správu databázového servera, čas od času budete možno musieť spustiť dotaz a starostlivo ho preskúmať. Hoci to môžete urobiť z prostredia MySQL/MariaDB, tento tip vám umožní vykonávať MySQL/MariaDB dotazy priamo z príkazového riadku Linuxu a zároveň uložiť výstup do súboru na neskoršiu kontrolu (čo je obzvlášť užitočné, ak dotaz vráti veľa záznamov).

Pozrime sa na niekoľko jednoduchých príkladov spúšťania MYSQL dotazov priamo z príkazového riadku, než sa presunieme k pokročilejšiemu dotazu.

Nastavenie ukážkových databáz

Skôr než sa pustíme do príkazov, nastavme si príkladové databázy, s ktorými budeme pracovať počas tohto návodu, aby ste mohli postupovať spolu a cvičiť tieto techniky na vlastnom systéme.

Vytváranie databázy tecmintdb

Najprv vytvoríme databázu tecmintdb a tabuľku tutorials:

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

Ďalej, na vytvorenie tabuľky databázy s názvom tutorials v databáze tecmintdb, spustite nasledujúci príkaz:

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

Overte, či boli údaje vložené:

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

Overiť dáta v tabuľke databázy MySQL

Vytváranie databázy zamestnancov

Teraz vytvorme zložitejšiu databázu employees s viacerými prepojenými tabuľkami, toto je databáza, ktorú použijeme pre pokročilejšie príklady dotazov:

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

Vytvorte tabuľku 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

Vytvorte tabuľku 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

Vytvorte tabuľku departments pre zložitejšie spojenia:

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

Vytvorte tabuľku dept_emp na prepojenie employees s 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

Skontrolujte, či je všetko nastavené správne:

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

Overiť nastavenie našej databázy MySQL

Teraz máte obe databázy nastavené s ukážkovými dátami a môžete sledovať všetky príklady v tomto návode. Databáza tecmintdb je ideálna pre jednoduché dotazy, zatiaľ čo databáza employees vám umožní precvičovať zložitejšie operácie ako spojenia a agregácie.

Základné vykonávanie dotazu

Ak chcete zobraziť všetky databázy na vašom serveri, môžete použiť nasledujúci príkaz:

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

Ďalej, na vytvorenie tabuľky databázy s názvom tutorials v databáze tecmintdb, spustite nasledujúci príkaz:

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));"

Ukladanie výsledkov MySQL dotazu do súboru

Použijeme nasledujúci príkaz a jeho výstup presmerujeme do príkazu tee, za ktorým bude názov súboru, kam chceme výstup uložiť.

Na ilustráciu použijeme databázu s názvom employees a jednoduché spojenie medzi tabuľkami employees a salaries. Vo vašom prípade stačí zadať SQL dotaz medzi úvodzovkami a stlačiť Enter.

Všimnite si, že budete vyzvaní na zadanie hesla pre používateľa databázy:

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

Prezrite si výsledky dotazu pomocou príkazu cat.

cat queryresults.txt

Spúšťanie dotazov MySQL/MariaDB z príkazového riadku

S výsledkami dotazu v obyčajných textových súboroch môžete záznamy spracovávať ľahšie pomocou iných príkazových nástrojov. Teraz, keď ste videli základy, poďme preskúmať niektoré pokročilejšie techniky, ktoré urobia vašu prácu s databázou v príkazovom riadku ešte efektívnejšou.

Formátovanie výstupu pre lepšiu čitateľnosť

Predvolený formát tabuľky je skvelý na prezeranie v termináli, ale niekedy potrebujete iné formáty. Výsledky môžete zobraziť vo vertikálnom formáte, čo je obzvlášť užitočné pri práci s tabuľkami, ktoré majú veľa stĺpcov:

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

\G na konci zobrazí každý riadok vertikálne namiesto v tabuľke, takže namiesto toho, aby ste videli stiesnenú horizontálnu tabuľku, dostanete niečo ako:

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

Exportovanie do formátu CSV

Keď potrebujete importovať výsledky dopytov do tabuľkových aplikácií alebo iných nástrojov, formát CSV je tá najlepšia voľba:

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

Toto presmeruje výstup cez sed, aby nahradil tabuátory čiarkami, čím vytvorí správny súbor CSV, ktorý sa dá ľahko otvoriť v Excel, LibreOffice Calc alebo v inom tabuľkovom programe.

Spúšťanie dotazov bez výziev na zadanie hesla

Ak automatizujete úlohy databázy pomocou cron úloh alebo skriptov, nechcete zakaždým manuálne zadávať heslá, práve tu prichádzajú na rad konfiguračné súbory MySQL.

Vytvorte súbor na ~/.my.cnf s vašimi prihlasovacími údajmi:

[client]
user=root
password=your_password_here

Potom ho zabezpečte tak, aby ho mohol čítať len vy:

chmod 600 ~/.my.cnf

Teraz môžete spúšťať dotazy bez príznaku -p a bez toho, aby ste boli vyzvaní:

mysql -e "SHOW DATABASES;"

Len si pamätajte, že ukladanie hesiel do súborov v obyčajnom texte má bezpečnostné dôsledky, takže tento prístup používajte iba na serveroch, kde kontrolujete prístup, a zvážte použitie bezpečnejších autentifikačných metód MySQL pre produkčné prostredia.

Vykonávanie zložitých viacriadkových dotazov

Niekedy sú vaše dotazy príliš zložité na to, aby sa dali napísať v jednom príkazovom riadku, najmä keď pracujete s viacerými spojeniami, poddotazmi alebo zložitými podmienkami.

Svoj SQL môžete uložiť do súboru a spustiť ho:

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

Teraz to vykonaj.

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

Tento prístup udržiava vaše dopyty usporiadané a znovupoužiteľné, a môžete ich spravovať pomocou verzionovania v gite rovnako ako akýkoľvek iný kód.

Hromadné spracovanie viacerých dotazov

Ak potrebujete spustiť niekoľko súvisiacich dopytov a výsledok každého uložiť zvlášť, môžete to napísať ako skript:

#!/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

Uložte to ako skript, spravte ho spustiteľným pomocou chmod +x a budete mať možné znovu použiteľný nástroj na hromadné dotazy.

Monitorovanie dlhodobých dotazov

Keď spúšťate dotazy, ktoré môžu trvať dlhšie, chcete vidieť priebeh alebo aspoň vedieť, že sú stále aktívne.

Skombinujte svoj dopyt s výstupom stavu:

(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

Pre ešte dlhšie dotazy ich spúšťajte na pozadí a sledujte zoznam procesov 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"'

Toto spustí váš dotaz na pozadí a zároveň každých 5 sekúnd zobrazí zoznam procesov, takže môžete vidieť, že stále pracuje a koľko pokroku dosiahol.

Filtrovanie a spracovanie výsledkov

Keď budete mať výsledky dotazu v textovom súbore, môžete použiť štandardné nástroje Linuxu na ich ďalšie spracovanie. Tu je niekoľko užitočných vzorov:

Spočítajte počet výsledkových riadkov (bez hlavičky):

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

Extrahujte konkrétne stĺpce pomocou awk:

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

Vyhľadajte konkrétne vzory vo výsledkoch:

grep -i "engineering" dept_distribution.txt

Zoradiť výsledky podľa číselného stĺpca:

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

Spracovanie špeciálnych znakov a veľkých dátových súborov

Keď vaše údaje obsahujú špeciálne znaky, tabuľátory alebo nové riadky, predvolený výstup môže byť chaotický, preto použite možnosti --batch a --raw pre čistejší výstup:

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

Pre dotazy, ktoré vracajú milióny riadkov, môžete naraziť na problémy s pamäťou, namiesto načítania všetkého do pamäte si výsledky streamujte:

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

Možnosť --quick príkazuje MySQL načítavať riadky jeden po druhom namiesto toho, aby uchovával celý výsledný súbor v pamäti, a presmerovanie cez gzip komprimuje výstup priebežne, čím šetrí miesto na disku.

Vytváranie rýchlych záloh databázy

Hoci toto technicky neznamená vykonávanie dotazov, môžete použiť podobné techniky príkazového riadku na vytvorenie rýchlych záloh databázy pomocou príkazu mysqldump.

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

Alebo zálohovať len konkrétne tabuľky:

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

Plánovanie automatizovaných správ

Spojte všetko, o čom sme doteraz hovorili, aby ste vytvorili automatizované denné správy pomocou cron s pomocou nasledujúceho bash skriptu.

#!/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"

Pridajte ho do cronu, aby sa spúšťal každý deň o 6:00 ráno:

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

Zdieľali sme niekoľko tipov pre Linux, ktoré by ste ako systémový administrátor mohli považovať za užitočné pri automatizácii svojich každodenných úloh v Linuxe alebo ich jednoduchšom vykonávaní.

Hlavné zhrnutie je, že nemusíte vždy spúšťať MySQL shell alebo používať náročné grafické nástroje na prácu s databázami; príkazový riadok vám poskytuje rýchlosť, možnosti automatizácie a schopnosť integrovať databázové operácie do vašich existujúcich shell skriptov a pracovných postupov.

Máš nejaké ďalšie tipy, ktoré by si chcel/a zdieľať s ostatnou komunitou? Ak áno, prosím urob to pomocou formulára na komentáre nižšie. :