Импорт товаров без дублей: SKU, штрихкод, external_id и конфликтные записи
Дубли товаров после импорта появляются не потому, что “импорт плохой”. Обычно у системы нет чёткого ответа на вопрос: как понять, что строка из файла — это уже существующий товар? Если сегодня сопоставление идёт по названию, завтра по артикулу, а послезавтра по штрихкоду, база быстро превращается в набор похожих карточек.
Перед импортом нужно выбрать стабильный ключ и честно обработать конфликтные ситуации.
Название не подходит как ключ
Название товара почти никогда не должно быть главным ключом сопоставления. Оно меняется, содержит ошибки, пробелы, регистр, маркетинговые добавки и разные варианты написания.
Крем для рук 50 мл
Крем д/рук, 50мл
Крем для рук, 50 мл, новый дизайн
Для человека это один товар. Для строгого импорта — три разные строки, если нет нормального ключа.
Возможные ключи
На практике используют:
- external_id из внешней системы;
- supplier_id + supplier_article;
- barcode;
- system_sku;
- marketplace offer_id;
- связку нескольких полей.
Лучший ключ — тот, который стабилен и не меняется при правке названия, цены или описания.
Нормализация артикула
Артикулы часто отличаются пробелами, регистром и лишними символами. Перед сравнением их стоит нормализовать.
$sku = trim($sku);
$sku = mb_strtoupper($sku);
$sku = preg_replace('/\s+/', '', $sku);
Но нормализация должна быть осторожной. Иногда дефис или слеш в артикуле значимы. Правила лучше согласовать с реальными данными поставщика.
Уникальный индекс
Если выбран ключ supplier_id + article, база должна защищать его уникальность.
CREATE UNIQUE INDEX ux_supplier_products_supplier_article
ON supplier_products (supplier_id, article_normalized);
Без индекса два параллельных импорта или повторный запуск всё равно могут создать дубль.
Конфликтные записи
Иногда строка совпала по артикулу, но отличается штрихкодом. Или совпала по штрихкоду, но другой поставщик прислал другое название. Это не нужно молча перетирать.
Лучше создать отчёт конфликтов:
- тип конфликта;
- строка файла;
- существующий товар;
- новые значения;
- что было обновлено;
- что требует ручной проверки.
Upsert вместо слепого insert
Повторный импорт должен обновлять существующую запись, а не создавать новую.
INSERT INTO supplier_products (supplier_id, article_normalized, name, price)
VALUES (:supplier_id, :article, :name, :price)
ON DUPLICATE KEY UPDATE
name = VALUES(name),
price = VALUES(price),
updated_at = UNIX_TIMESTAMP();
Такой подход работает только при правильно выбранном уникальном индексе.
Связь с системным товаром
Если есть системные товары и товары поставщика, связь нужно хранить явно. Не стоит каждый раз искать системный товар по названию.
supplier_product_id
supplier_id
product_id
external_id
supplier_article
Если связь потерялась, импорт должен показывать это как проблему маппинга, а не создавать новый системный товар без контроля.
Отчёт после импорта
После каждого запуска нужен итог:
- строк прочитано;
- товаров создано;
- товаров обновлено;
- строк пропущено;
- конфликтов найдено;
- дублей предотвращено;
- ошибок валидации.
Если после импорта есть только сообщение “готово”, поддержка всё равно будет разбираться вручную.
Чек-лист
- Не использовать название товара как основной ключ.
- Выбрать стабильный ключ сопоставления.
- Нормализовать артикулы и штрихкоды по понятным правилам.
- Добавить уникальный индекс на выбранный ключ.
- Использовать upsert вместо слепого insert.
- Фиксировать конфликтные строки отдельно.
- Хранить связь товара поставщика с системным товаром.
- Формировать отчёт после каждого импорта.
Импорт без дублей начинается не с кода парсера, а с правил идентификации товара. Когда ключ выбран правильно и защищён индексом, повторные загрузки становятся штатной операцией, а не лотереей.
Комментарии (0)
Пока нет комментариев. Будьте первым!