<?php // Полная загрузка сервисных книжек, создан 2024-01-05 12:44:55
global $wpdb2;
global $failure;
global $file_hist;
///// echo '<H2><b>Старт загрузки</b></H2><br>';
$failure=FALSE;
//подключаемся к базе
$wpdb2 = include_once 'connection.php'; ; // подключаемся к MySQL
// если не удалось подключиться, и нужно оборвать PHP с сообщением об этой ошибке
if (!empty($wpdb2->error))
{
///// echo '<H2><b>Ошибка подключения к БД, завершение.</b></H2><br>';
$failure=TRUE;
wp_die( $wpdb2->error );
}
$m_size_file=0;
$m_mtime_file=0;
$m_comment='';
/////проверка существования файлов выгрузки из 1С
////файл выгрузки сервисных книжек
$file_hist = ABSPATH.'/_1c_alfa_exchange/AA_hist.csv';
if (!file_exists($file_hist))
{
///// echo '<H2><b>Файл обмена с сервисными книжками не существует.</b></H2><br>';
$m_comment='Файл обмена с сервисными книжками не существует';
$failure=TRUE;
}
/////инициируем таблицу лога
/////если не существует файла то возврат и ничего не делаем
if ($failure){
///включает защиту от SQL инъекций и данные можно передавать как есть, например: $_GET['foo']
///// echo '<H2><b>Попытка вставить запись в лог таблицу</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>$m_mtime_file,'last_size_upload'=>$m_size_file,'comment'=>$m_comment));
wp_die();
///// echo '<H2><b>Возврат в начало.</b></H2><br>';
return $failure;
}
/////проверка лога загрузки, что бы не загружать тоже самое
$masiv_data_file=stat($file_hist); ////передаем в массив свойство файла
$m_size_file=$masiv_data_file[7]; ////получаем размер файла
$m_mtime_file=$masiv_data_file[9]; ////получаем дату модификации файла
////создаем запрос на получение последней удачной загрузки
////выбираем по штампу времени создания (редактирования) файла загрузки AA_hist.csv, $m_mtime_file
///// echo '<H2><b>Размер файла: '.$m_size_file.'</b></H2><br>';
///// echo '<H2><b>Штамп времени файла: '.$m_mtime_file.'</b></H2><br>';
///// echo '<H2><b>Формирование запроса на выборку из лога</b></H2><br>';
////препарируем запрос
$text_zaprosa=$wpdb2->prepare("SELECT * FROM `vin_logs` WHERE `last_mtime_upload` = %s", $m_mtime_file);
$results=$wpdb2->get_results($text_zaprosa);
if ($results)
{ foreach ( $results as $r)
{
////если штамп времени и размер файла совпадают, возврат
if (($r->last_mtime_upload==$m_mtime_file) && ($r->last_size_upload==$m_size_file))
{////echo '<H2><b>Возврат в начало, т.к. найдена запись в логе.</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>$m_mtime_file,'last_size_upload'=>$m_size_file,'comment'=>'Загрузка отменена, новых данных нет, т.к. найдена запись в логе.'));
wp_die();
return $failure;
}
}
}
////если данные новые, пишем в лог запись о начале загрузки
/////echo '<H2><b>Попытка вставить запись о начале загрузки в лог таблицу</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>0, 'last_size_upload'=>$m_size_file, 'comment'=>'Начало загрузки'));
////очищаем таблицу
$clear_tbl_zap=$wpdb2->prepare("TRUNCATE TABLE %s", 'vin_history');
$clear_tbl_zap_repl=str_replace("'","`",$clear_tbl_zap);
$results=$wpdb2->query($clear_tbl_zap_repl);
///// echo '<H2><b>Очистка таблицы сервисных книжек</b></H2><br>';
if (empty($results))
{
///// echo '<H2><b>Ошибка очистки таблицы книжек, завершение.</b></H2><br>';
//// если очистка не удалась, возврат
$failure=TRUE;
wp_die();
return $failure;
}
////загружаем данные
$table='vin_history'; // Имя таблицы для импорта
//$file_hist Имя CSV файла, откуда берется информация // (путь от корня web-сервера)
$delim=';'; // Разделитель полей в CSV файле
$enclosed='"'; // Кавычки для содержимого полей
$escaped='\
а скорость работы какая?
10000 позиций — транзакция нажна
Лучше в excel сохранить и потом при загрузке при помощи метода Range сохранить все нужные данные в Таблицу значений и потом уже из нее восстанавливать нужные данные. А таким методом каждый раз приходится получать область с данными, это не слишком быстро.
ВыгрузкаЗагрузка между идентичными конфигурациями на ИТС
С выгрузкой/загрузкой все хорошо пока вы конфигурацию не поменяли, опять же фильтр писать надо, а это способ. По производительности думаю не особо, но так и делается он на всякие пожарный, а не как средство переноса.
Денис, а если просто таблицу значений сохранить в файл через «ЗначениеВСтрокуВнутр»? При восстановлении через «ЗначениеИзСтрокиВнутр» ссылки остаются.
А есть ещё и сериализация стандартных объектов…
Но да, можно и так, конечно ))
Способ интересный, но мне кажется, что сложноват. Много надо держать в голове. Проще по журналу транзакций откатить базу на 4 минуты назад.
(6) В большинстве случаев, его нет (
(1) Алексей, не мерил, но для 2-5 тысяч позиций вполне приемлемая, секунд 12-15.
(5) Вся фишка этой штуки в том, что не нужно ничего писать предварительно. в 99% случаев вы пишите запрос в консоли, прежде чем запустить его в работу.
(9) Просто добавь в консольку кнопки сохранения/восстановления результатов запроса (таблицы значений). И всё будет работать намного быстрее, чем обход mxl в цикле.
(6)Вместе с со своими изменениями, откатить продажи, уже пробитые в ККМ чеки и созданные кем нибудь элементы справочников. Мои юзеры сразу убивают за такое .
(11) Наверное полагается что то, что автор предложил, будет происходить в
1. Тестовой базе
2. Рабочей базе без пользователей (на случай необходимости отката)
А в рабочей базе и при этом с людьми в ней, я в любом случае не рискнул бы делать подобное. Выгружать в mxl и загружать обратно — это не такая уж и надёжная операция. Однажды что-то упустишь и будешь откатывать к ночному бэкапу продажи, уже пробитые в ККМ, чеки и созданные кем нибудь элементы справочников.
(12)Ну… как то упустил. У меня тестовая база в режиме восстановления «простая». В таком случае да, лог проще откатить.
Один вопрос, а что если в запросе была допущена неочевидная ошибка, как часто бывает. Все данные в итоге коту под хвост.
Очень вредный совет. Как минимум я все равно перед операцией сделал бы бэкап данных.
(14) я здесь предполагаю, что запрос, выполняемый в запроснике, и запрос, выполняемый при изменении данных — один и тот же. Пусть даже и с ошибкой, но отработает он одинаково
Превое. Изменение каких то больших массивов данных чаще всего делают ночью когда база свободна от пользователей.
Второе. В большинстве фирм которые дорожат своими данными кроме ночных бекапов делаются бекапы логов (у нас в организации каждые 5 минут)
Предположим вы сделали ошибку, сразу ее не заметили, прошло несколько дней.
Поднимается бекап на точку с корректными данными и как уже писали выше используется ВыгрузкаЗагрузка между идентичными конфигурациями.
Если структура изменилась то в том чтобы привести тестовую базу(из бекапа) в соответствие с боевой нет ничего сложного, особенно если вы используете хранилище.
Но самый лучший способ это не косячить на боевых серверах)))))
Бакуп сделал мой день!
(17)
Проще по журналу транзакций откатить базу на 4 минуты назад.
На заре юности и желторотости, я, к примеру, реально верил в это. Потом разок попробовал… получилось одного журнала почему-то мало. Долго не мог унять негодования. Но звучит то как красиво! — «на 4 минуты назад»
Жаль, что бакуп так «странно» устроен.
Перед массовым изменениями в боевой базе. 1. Сделать архив. 2. Проверить на копии. 3. Внести изменения.
Хотя сама по себе идея интересная при тестировании.
как вариант, с помощью обработки «Выгрузка и загрузка данных XML»
можно универсальной выгрузкой выгрузить данные в xml. Затем откатить простой загрузкой.
Автор скорее всего свое решение предлагает использовать в случаях, когда один из менеджеров компании меняет несколько реквизитов (100-10000) у определенной группы товаров,например, и допускает ошибку. Т.е. способ предназначен преимущественно для справочников.
Примерно так:
1. ЗначениеВФайл / ЗначениеИзФайла
2. ЗначениеВСтрокуВнутр / ЗначениеИзСтрокиВнутр
3. XML-сериализация (обработка «Выгрузка-загрузка данных в формате XML», вроде есть на ИТС и для 8.2, и для 8.3)
Способ интересный, но я пользуюсь утилитой ежедневного (недельного) копирования БД ..effector saver (если кому понадобится)
(21) Самое простое решение, поддерживаю! Но вообще это актуально только при тестировании обработки. На рабочей базе лучше такие изменения делать в монопольном режиме.