Заметки про запросы. Последовательность.




Принцип обмена данными из 1С с сайтом (на MySQL) и выдачи (публикации) этих данных по запросу.
PHP-Скрипт автоматической загрузки данных из файла данных в формате CSV в базу данных сайта работающего на WordPress.

В продолжение моей темы: 1С:Альфа-Авто Автосалон Автосервис: обмен с сайтом.
С помощью данного скрипта можно загружать в автоматическом режиме, по расписанию, данные сервисных книжек (ремонтов авто) из 1С:Альфа-Авто Автосалон Автосервис.
Также можно загружать данные в ручном режиме: для этого делается скрытая страница, где размещается специальная кнопка.
Комментарии размещенные внутри скрипта разъяснят логику и порядок действия.
Комментарии с "/////    echo" использовались для отладки.
Дополнительно создана таблица для журналирования результатов загрузки данных.
Скрипт включает в себя защиту от SQL инъекций (думаю безопасность соблюдена в полной мере).
В кратце:
1. Пишется скрипт, который запускает этот.
2. Создается регламентное задание в WordPress, по которому запускается скрипт из п.1. 
3. Этот скрипт осуществляет проверку на существование файла обмена в папке.
4. Если данные не новые, загрузка не производится.
5. Если данные новые, очищается таблица сервисных книжек.
6. Загружаются новые данные.

Собственно сам скрипт:

<?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='\

27 Comments

  1. ashvik

    А где же условия виртуальных таблиц?

    Reply
  2. vasilev2015

    Да, спасибо, формирование виртуальных таблиц происходит еще раньше соединений.

    Reply
  3. vasilev2015

    Очень ценный комментарий. Статья будет дополнена.

    Reply
  4. starik-2005

    Есть мнение, что SQL делает так, как ему лучше будет (в соответствии со статистикой). Главное — чтобы результат был таким, какой требует пользователь. Не знаю, как сейчас, но раньше если во временную таблицу вытаскиваешь всю таблицу, а потом агрегируешь ее и берешь оттуда только количество значений, то запрос вообще не выполнялся (на мелкософт скуле по крайней мере).

    Reply
  5. ProgrammistC

    Статистикой пользуется анализатор запроса и на ее основе выбирает оптимальный план запроса, планы запроса надо читать для разных случаев

    Reply
  6. tormozit

    Утверждение

    Сначала выполняются команды ПЕРВЫЕ <ХХ>– Упорядочить По, затем агрегатные функции с группировкой

    Ошибочно. Оператор TOP (ПЕРВЫЕ) выполняется последним (логически), а ORDER (УПОРЯДОЧИТЬ) предпоследним (логически).

    Reply
  7. starik-2005

    (7) tormozit, ИМХО, автор имел ввиду, что топ и ордер выполняются сначала, а агрегирование — потом. Хотя… Понимать — вообще штука сложная. Может на форуме сделать кнопку «Вы уверены, что поняли текст, на который отвечаете. и хотите ответить именно так, как написали?» Какому-то школьнику за это дали вкусных плюшек.

    Reply
  8. tormozit

    (8) В операторе УПОРЯДОЧИТЬ доступны псевдонимы (результаты) полей оператора ВЫБРАТЬ, в том числе выражений с агрегатными функциями, а также непосредственно в операторе УПОРЯДОЧИТЬ можно указывать выражения, содержащие агрегатные функции.

    Reply
  9. cool.vlad4

    (8) starik-2005, не надо ерничать. как обработается запрос в реальности зависит и от запроса, и от движка обрабатывающего sql (как обрабатывает запросы же файловая версия 1С, я без понятия).поэтому и есть понятие logical processing order, о котором и написал tormozit. чтобы иметь представления при написании запросов.

    например см https://msdn.microsoft.com/en-us/library/ms189499.aspx

    FR OM

    ON

    JOIN

    WH ERE

    GROUP BY

    WITH CUBE or WITH ROLLUP

    HAVING

    SEL ECT

    DISTINCT

    ORDER BY

    TOP

    т.е. топ вообще на последнем месте.

    смотрим запрос автора, но при другой таблице

    ВЫБРАТЬ
    2 КАК Поле1,
    4 КАК Поле2,
    0 КАК Поле3
    
    ПОМЕСТИТЬ ТабПример1
    
    ОБЪЕДИНИТЬ
    
    ВЫБРАТЬ
    1,
    3,
    0
    
    ОБЪЕДИНИТЬ
    
    ВЫБРАТЬ
    1,
    34,
    0
    ОБЪЕДИНИТЬ
    
    ВЫБРАТЬ
    2,
    34,
    0
    
    ;
    ВЫБРАТЬ ПЕРВЫЕ 1
    ТабПример1.Поле1 КАК Поле1,
    СУММА(ТабПример1.Поле2) КАК Поле2
    ИЗ ТабПример1 КАК ТабПример1
    СГРУППИРОВАТЬ ПО ТабПример1.Поле1
    УПОРЯДОЧИТЬ ПО Поле2

    Показать

    Результат будет 1, 37 . т.е. сначала произошло агрегирование и только потом TOP . понятно, что в целях оптимизации в реальности TOP может выполниться сначала. но говорить надо именно о логической последовательности выполнения. там же по ссылке

    Note that the actual physical execution of the statement is determined by the query processor and the order may vary fr om this list.

    автор был бы прав в случае если бы указал, что у меня на таком-то сервере, только в этом запросе, в данной таблице, сначала выполняется…и т.д. и то, как у него происходит сначала упорядочивание по агрегатному полю, а потом агрегация, непонятно. но мало ли. может оптимизировалось выполнение так запроса.

    Reply
  10. Makushimo

    Автор не ссылался на планы запросов, оптимизатор и прочее.

    Значит в этой теме [возможно] глубоко не разбирался.

    А то что он провел исследование и поделился результатами весьма неплохо.

    К тому же в основном его выводы верны.

    Порекомендуйте коллеге материал для изучения планов запросов, оптимизатора и прочее

    и тогда он [возможно] перепишет статью более корректно.

    Reply
  11. Fox-trot

    (11) Makushimo, ты не поверишь, но есть БД у которых нет ни оптимизаторов, ни планов

    Reply
  12. Makushimo

    (12) Fox-trot, которые из тех,что использует 1С?

    я не ерничаю, а правда кроме SQL ничего и не знаю.

    Reply
  13. vasilev2015

    (10) cool.vlad4, Скорее всего, Вы правы: топ на последнем месте. Проверю еще раз, изменю статью. Спасибо.

    Reply
  14. Fragster

    Вот тут майкрософт дает хорошее пояснение:

    FROM

    ON

    JOIN

    WHERE

    GROUP BY

    WITH CUBE or WITH ROLLUP // этого в 1с нет

    HAVING

    SELECT

    DISTINCT

    ORDER BY

    TOP

    остается вопрос с «итоги … по …», которые делаются 1сом программно, вероятно это происходит уже с результатом всех операций с БД

    Reply
  15. starik-2005

    (17) Вам лечиться надо.

    Reply
  16. cool.vlad4

    (16) starik-2005, это тот самый редкий случай , когда starik-2005 знает лучше , что имел в виду автор, нежели сам автор. см.

    (10) cool.vlad4, Скорее всего, Вы правы: топ на последнем месте. Проверю еще раз, изменю статью. Спасибо.
    Reply
  17. Fox-trot

    (13) Makushimo, пусть так, но это все равно не имеет никакого отношения к синтаксису

    Reply
  18. qwinter

    (12) Fox-trot, оптимизатор запросов есть даже внутри платформы. А еще есть оптимизатор СКД, со своими блекджеками и ш***)))

    Reply
  19. Fox-trot

    (22) qwinter, пусть так, но это все равно не имеет никакого отношения к синтаксису )

    Reply
  20. Makushimo

    (23) Fox-trot, этот аргумент ничем не перекрыть :-)) ну просто уложил на обе лопатки.

    красава.

    Reply
  21. 1cmax

    (22) qwinter, c преферансом и куртизанками

    Reply
  22. asved.ru

    Статья не имеет никакого отношения к оптимизации и хайлоаду. Это теория программирования в чистом виде.

    Потому, что узнать, какие операции и в какой последовательности выполняются в действительности, можно только посмотрев план запроса. Но вот если различный порядок исполнения операций запроса допускает различные результаты, то результат исполнения плана будет логически соответствовать изложенному порядку

    Иначе при выполнении


    1. Соединение

    2. Проверка условия «ГДЕ»

    SQL был бы вынужден прочитать все содержимое всех таблиц даже при существовании идеально покрывающих индексов. Вы представляете себе, во что бы вылился запрос чтения, скажем, документа с табличной частью, если их ввведено несколько миллионов?

    Фактически SQL первым делом стремится применить имеющиеся условия к исходным таблицам.

    Смысла в порядке выполнения TOP вообще никакого нет, он просто прерывает исполнение плана, получив достаточно строк результата.

    Reply
  23. Dem1urg
    Сначала выполняется Соединение таблиц. Об этом написано в учебниках SQL

    Не совсем.

    Не буду утверждать про все СУБД, но MS SQL если в условии WHERE (ГДЕ) одна из частей условия является константой, а соединение INNER (внутреннее), то движок MS SQL сначала выполняет предварительную фильтрацию таблицы и только потом уже соединение.

    Reply
  24. Fragster

    (27) Dem1urg, физическое выполнение и «логическое» — немного разные вещи. если результат от разного порядка действий одинаковый — оптимизатор СУБД может извращаться как ему удобно, но логический порядок определен в (15), он не меняется и задается программистом.

    Reply
  25. JesteR

    (5) starik-2005, ТормозИТ не зря в скобочках написал ЛОГИЧЕСКИ.

    Не путайте логическое исполнение и физическое. В статье автор описывает логическое исполнение запросов.

    Reply
  26. speshuric

    (29) JesteR, Есть нюанс. Оптимизатор может нашаманить план так, что, например, будете ловить деление на 0 или другие арифметические ошибки, хотя «логически» эта строка уже должна быть отфильтрованной. Причем ловить нестабильно от статистики. Но, да, логический порядок обработки программист знать обязан. Но применительно к 1С его ломают дополнительные возможности 1С (которые эмулируются) например:

    • составные типы (да, я до сих пор их люблю, хотя уже 2 года на 1С не пишу),
    • виртуальные таблицы
    • (expr1, exp2) В (ВЫБРАТЬ)
    • в иерархии
    • команды построителю и прочий наш сахер синтаксический

    После них в SQL такой милый фарш иногда выходит, что внятно предсказать (да еще для всех СУБД) могут только астрологи-телепаты (причем с опытом 10+ лет разработки на 1С и SQL)

    Reply

Leave a Comment

Ваш адрес email не будет опубликован. Обязательные поля помечены *