Данните рядко се раждат в базата
Списъкът на класа идва от секретаря в Excel. Резултатите от олимпиадата — като CSV от сайта на организатора. Разписанието — като JSON от друго приложение. Отворените данни на държавата — в CSV и XML. И обратно: счетоводството иска Excel, сайтът иска JSON, а моделът за машинно обучение в урок 12 ще иска CSV.
Преносът изглежда тривиален — таблица е таблица — и точно затова е източник на най-упоритите грешки: дати, разбъркани като ден и месец, „5,50“, станало 550, кирилица, станала въпросителни. Днес учим форматите, инструментите и — най-важното — проверката.
Форматите
CSV — таблица като текст
id,ime,klas,ocenka,data
1,Александра Иванова,11А,6.00,2026-02-10
2,"Петров, Борислав",11А,4.50,2026-02-10- Разделител: запетая по стандарт, но българският Excel записва с
;, защото запетаята му е десетичен знак. При импорт разделителят се посочва изрично. - Кавички: стойност, която съдържа разделителя или нов ред, се огражда с
"…"— иначе „Петров, Борислав“ става две колони. - Кодиране: винаги UTF-8. Файл в Windows-1251, прочетен като UTF-8, дава „Ð�лек…“; обратното — „????“.
- Десетичен знак: базата разбира само точка. „5,50“ в числова колона става 5 (MySQL спира на запетаята) или грешка.
- Първият ред е обикновено заглавие с имената на колоните — при импорт се казва, че е такъв.
Excel — през CSV
phpMyAdmin импортира CSV, не .xlsx. В Excel: Запази като → „CSV UTF-8 (разделен със запетаи)“. Преди това: датите да са в една колона и в един формат, без обединени клетки, без формули (записва се стойността), без празни редове под таблицата. При експорт от базата обратната посока е същата — CSV, който Excel отваря директно.
XML и JSON — структура, не таблица
JSON: XML:
[ <ucenici>
{"id": 1, <uchenik id="1">
"ime": "Александра Иванова", <ime>Александра Иванова</ime>
"klas": "11А", <klas>11А</klas>
"ocenki": [6.00, 5.50]}, <ocenka>6.00</ocenka>
{"id": 4, <ocenka>5.50</ocenka>
"ime": "Георги Стоянов", </uchenik>
"klas": "11Б", <uchenik id="4">
"ocenki": [3.50, 4.00], ...
"telefon": null} </uchenik>
] </ucenici>И двата описват дърво: обект в обект, списък в обект. Ученикът има списък от оценки — в релационната база това са два реда в marks, не една клетка. Поле telefon има само при един запис — в таблицата колоната е за всички, с NULL. Затова JSON и XML не се „импортират“ в таблица направо: първо се решава кое ниво на дървото коя таблица става (това е нормализацията от Модул 3), после се пренасят. phpMyAdmin умее експорт към JSON и XML; импорт от тях приема само своя собствен формат.
| CSV | JSON / XML | |
|---|---|---|
| Форма | редове и колони — таблица | дърво — обекти, списъци, вложеност |
| Типове | всичко е текст; типът се решава при импорт | JSON различава число, текст, null, списък |
| Липсващо поле | празна клетка | полето просто го няма или е null |
| Къде се среща | Excel, отворени данни, експорт от системи | уеб API, конфигурации, отговори на AI модел (урок 20) |
Инструментите в phpMyAdmin
- Импорт: изберете базата (или таблицата) → раздел „Импорт“ → файл → формат CSV → задайте разделител, знак за кавички, кодиране и отметка „Първият ред съдържа имената на колоните“ → „Импорт“.
- Ако таблицата не съществува, phpMyAdmin я създава от заглавния ред — но всички колони стават текст. По-добре я създайте предварително с вярни типове, или импортирайте в текстова „междинна“ таблица и после прехвърлете с INSERT … SELECT.
- Експорт: таблица → раздел „Експорт“ → формат CSV / JSON / XML / SQL → при CSV изберете разделителя, който ще разбере получателят (за Excel в България често „;“).
- Под резултата на всеки импорт пише колко реда са вмъкнати и има ли предупреждения — четете ги, преди да продължите.
-- Същото без phpMyAdmin - LOAD DATA (само за четене; сървърът трябва да го позволява)
LOAD DATA LOCAL INFILE 'ocenki.csv'
INTO TABLE ocenki_raw
CHARACTER SET utf8mb4
FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"'
LINES TERMINATED BY '\n'
IGNORE 1 LINES; -- заглавния ред
-- Експорт на резултат от заявка във файл на сървъра
SELECT name, klas, sreden FROM v_uspeh
INTO OUTFILE '/tmp/uspeh.csv'
FIELDS TERMINATED BY ',' ENCLOSED BY '"' LINES TERMINATED BY '\n';Почистване при пренос
Всеки от тези проблеми сте виждали в Excel таблица, попълвана от няколко души. В базата те не са досадни — те са грешни резултати: дубликат = двойна оценка в средния успех, „ 11А“ с интервал = отделен клас в GROUP BY.
| Проблем | Как изглежда | Поправка в MySQL |
|---|---|---|
| Дати в различни формати | 2026-02-10, 10.02.2026, 10/02/2026 | STR_TO_DATE(data, '%d.%m.%Y') |
| Празен низ вместо NULL | ocenka = '' — не е нула, не е липса | NULLIF(ocenka, '') |
| Водещи и крайни интервали | ' Борислав', '11А ' | TRIM(ime) |
| Десетична запетая | '5,50' | REPLACE(ocenka, ',', '.') |
| Различен регистър и правопис | математика / Математика, 11 А / 11А | UPPER(LEFT(…)), REPLACE(klas, ' ', '') |
| Дублирани редове | същият ред два пъти | GROUP BY … HAVING COUNT(*) > 1 |
| Стойност извън обхвата | оценка 55, дата 2062 | WHERE ocenka NOT BETWEEN 2 AND 6 — гледа се на ръка |
Проверка след импорт
SELECT COUNT(*) FROM ocenki; -- колкото реда във файла (без заглавието)?
SELECT MIN(ocenka), MAX(ocenka), AVG(ocenka) FROM ocenki; -- в обхвата 2-6? средното разумно?
SELECT MIN(data), MAX(data) FROM ocenki; -- датите в учебната година?
SELECT klas, COUNT(*) FROM ocenki GROUP BY klas; -- три класа, не пет варианта на три класа?
SELECT COUNT(*) FROM ocenki WHERE ocenka IS NULL; -- колко липсват и защо?
SELECT * FROM ocenki ORDER BY id DESC LIMIT 3; -- последните редове стигнаха ли?Шест заявки, една минута — и знаете дали преносът е верен. Същите заявки се пускат и след експорт, върху получателя: отворете CSV в Excel и проверете броя редове и една сума.
Какво трябва да запомниш
- CSV е таблица като текст: разделител, кавички, UTF-8 и десетична точка се проверяват преди импорт; Excel минава през CSV UTF-8.
- JSON и XML са дърво — първо се решава кое ниво коя таблица става, после се пренася.
- Мръсен файл се внася в междинна таблица с текстови колони, чисти се с UPDATE и се прехвърля с INSERT … SELECT.
- Типични поправки: STR_TO_DATE, NULLIF, TRIM, REPLACE, GROUP BY … HAVING COUNT(*) > 1.
- Всяко решение при почистване се записва — кой ред, какво и защо.
- След импорт и след експорт: COUNT, MIN/MAX, GROUP BY по категория, NULL, последни редове.