Архив рубрики: MySQL

Обновление «Учет оргтехники и ТМЦ в браузере» до версии 3.49

Выложено на sourceforge.net

В основном эволюционные изменения. Ничего революционного нет. Исправлено ряд незначительных ошибок.

Из нового:

  • добавлено поле «в пути» в журнале имущества и в перемещениях
  • каждому пользователю можно добавить роли
  • добавлен модуль «управление устройствами» — можно например использовать для перезагрузок устройств
  • добавлен виджет — модуль «кто онлайн»
  • еще ряд мелочей

Работа с транзакциями MySQL на PHP

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

$err="";
 $lb=new Tsql();
 $lb->connect($myrow["host"], $myrow["username"], $myrow["pass"], $myrow["basename"]);
 $lb->start_transaction();
 $sql="INSERT INTO payments (agrm_id,amount,comment,receipt,pay_date,local_date,status,mod_person,amount_cur) VALUES ('$agrm_id','$amount','Автоматически загруженный платеж','$uniid','$dat',now(),0,'$manager_id','$amount')";
 if ($err==""){
 $result2 = $lb->ExecuteSQL($sql);
 if ($result2=='') {$err="Error!";};
 };
 $sql="UPDATE agreements SET balance=balance+$amount where agrm_id='$agrm_id'";
 if ($err==""){
 $result2 = $lb->ExecuteSQL($sql);
 if ($result2=='') {$err="Error!";};
 };
 if ($err==""){
 $lb->commit();
 } else {
 $lb->rollback();
 PutLog('----ошибка занесения платежа(2): ' . $err);
 };
 unset($lb);

Использованный класс:

<?php
// Данный код создан и распространяется по лицензии GPL v3
// Изначальный автор данного кода - Грибов Павел
// http://грибовы.рф

class Tsql {
    var $idsqlconnection; // идентификатор соединения с БД

// соеденяемся с БД и выбираем таблицу, получаем $idsqlconnection    
function connect($host,$name,$pass,$base){
    global $codemysql;
      $this->idsqlconnection=new mysqli($host,$name,$pass,$base);
        if (mysqli_connect_errno()) {
            $serr=mysqli_connect_error();
            die("Error connect to Mysql or select base: $serr");
            }      
    $result = mysqli_query($this->idsqlconnection,"SET NAMES $codemysql");    
    mysqli_set_charset($this->idsqlconnection, "$codemysql");
    
 }   
 
function ExecuteSQL($sql){
    //echo "$sql<br>";
    $result = mysqli_query($this->idsqlconnection,$sql);               
    if ($result==""){echo mysqli_connect_error();};
    return $result;
 }   
 
 function start_transaction(){
     return mysqli_query($this->idsqlconnection,"START TRANSACTION");
   //return mysqli_begin_transaction($this->idsqlconnection);  
 }
 
 function commit (){
     return mysqli_query($this->idsqlconnection,"COMMIT");
   //return mysqli_commit($this->idsqlconnection);  
 }
 
 function rollback(){
     return mysqli_query($this->idsqlconnection,"ROLLBACK");
   //return mysqli_rollback($this->idsqlconnection);  
 }
 function close(){
 return mysqli_close($this->idsqlconnection);
 }
}

Как оказалось, главной фишкой — нельзя использовать внутри цикла begin transaction — commit (или rollback) обработку ошибок при помощи mysqli_error — PHP падает в FATAL ERROR.. Почему? Вопрос интересный.

Запрос с условием IF в MySQL..

Синтаксис:

IF(выражение, значение если true, значение если false)

Например:

select if (now()>timefrom and now()<=timeto,1,0) as act,if (now()<=timefrom,1,0) as futo,categories.descr,categories.above,usbox_services.mul,usbox_services.person_id,usbox_services.comment,usbox_services.created,usbox_services.timefrom,usbox_services.timeto from usbox_services inner join categories on (categories.tar_id=usbox_services.tar_id and categories.cat_idx=usbox_services.cat_idx) where usbox_services.vg_id=6861 order by usbox_services.timeto desc;

Возвратит act=1 если текущий момент времени между timefrom и timeto, а так-же futu=1 если timefrom>=now()

Коварный UNION..

Иной раз не знаешь где затупишь. Казалось бы простой запрос с использованием UNION, а потратил кучу времени, чтобы выяснить, почему он иногда не корректно отрабатывает.

Было:

$sql="select * from (select amount,local_date as date,managers.fio as tar_id,'enter' as type from payments inner join managers on payments.mod_person=managers.person_id where agrm_id='$agrm_id' UNION  "
 . "SELECT amount,DATE_ADD(period, INTERVAL 1 DAY) as date,tarifs.descr as tarif,'inet' as type FROM rentcharge inner join tarifs on rentcharge.tar_id=tarifs.tar_id where rentcharge.agrm_id='$agrm_id' and amount<>0 UNION "
 . "select usbox_charge.amount,usbox_charge.charge_date,tarifs.descr as tarif,'tv' from usbox_charge inner join usbox_services on usbox_charge.serv_id=usbox_services.serv_id inner join tarifs on tarifs.tar_id=usbox_services.tar_id where usbox_charge.amount<>0 and usbox_charge.agrm_id='$agrm_id') as res order by date";

Стало:

$sql="select * from (select amount,local_date as date,managers.fio as tar_id,'enter' as type from payments inner join managers on payments.mod_person=managers.person_id where agrm_id='$agrm_id' UNION ALL "
 . "SELECT amount,DATE_ADD(period, INTERVAL 1 DAY) as date,tarifs.descr as tarif,'inet' as type FROM rentcharge inner join tarifs on rentcharge.tar_id=tarifs.tar_id where rentcharge.agrm_id='$agrm_id' and amount<>0 UNION ALL "
 . "select usbox_charge.amount,usbox_charge.charge_date,tarifs.descr as tarif,'tv' from usbox_charge inner join usbox_services on usbox_charge.serv_id=usbox_services.serv_id inner join tarifs on tarifs.tar_id=usbox_services.tar_id where usbox_charge.amount<>0 and usbox_charge.agrm_id='$agrm_id') as res order by date";

В чем соль? Оператор UNION без опции ALL оказывается обладает свойствами группировки одинаковых значений в запросе. Например у меня, при одинаковых одновременных значениях даты и суммы происходила группировка этих строчек в одну…

Сортировка в MySQL кириллицы utf8-general-ci

загруженное (1)Дано: MySQL 5.1.72, таблицы созданные в utf8-general-ci, установка соединения вызывается следующей функцией:

function connect($host,$name,$pass,$base){
 $this->idsqlconnection=new mysqli($host,$name,$pass,$base);
 if (mysqli_connect_errno()) {
 $serr=mysqli_connect_error();
 die("Error connect to Mysql or select base: $serr");
 } 
 $result = mysqli_query($this->idsqlconnection,"SET NAMES utf8_general_ci"); 
 mysqli_set_charset($this->idsqlconnection, "utf8_general_ci");
 
 }

И хоть ты тресни, запрос вида:

$SQL = "SELECT * FROM places WHERE orgid='$orgid' AND active=1 ORDER BY name";
 $result = $sqlcn->ExecuteSQL( $SQL ) or die("Не могу выбрать список помещений!".mysqli_error($sqlcn->idsqlconnection));

Сортировался по непонятно каким критериям. Потеряв на поиск причины  несколько часов, перепробовав кучу «рецептов», пришлось заворачивать сортировку запросов в команду binary(), т.е. вот так:

$SQL = "SELECT * FROM places WHERE orgid='$orgid' AND active=1 ORDER BY binary(name)";

Костыль конечно.. И сортирует различая большие и маленькие буквы. Но таки лучше так чем никак. Ищу лучшее решение.