Профиль пользователя заблокирован сроком с 10 апреля 2022 г. и навсегда по причине: систематические нарушения правил сервиса
Ответы пользователя по тегу MySQL
  • Как привести к числу строку в mysql?

    FanatPHP
    @FanatPHP
    Чебуратор тега РНР
    У художника Франсиско Гойи есть известная картина, "Сон разума рождает чудовищ".
    Вот этот запрос как раз и есть такое чудовище.

    Он тем смешнее, что БД как раз и приводит строку 3, 5, 7 к числу. Получая в результате единственно возможный результат - 3.

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

    Либо сделать нормальный джойн и сгруппировать в вызывающем скрипте
    Ответ написан
    5 комментариев
  • Как перенести базу данных с одного хостинга на другой?

    FanatPHP
    @FanatPHP
    Чебуратор тега РНР
    сначала конечно надо запустить базу на старом.
    а потом зайти на новый по SSH и выполнить простую команду,
    ssh user@remote.host 'mysqldump -uuser -ppassword --all_databases | gzip' > dump.sql.gz
    Ответ написан
  • Как добавить данные в БД через HTML-форму?

    FanatPHP
    @FanatPHP
    Чебуратор тега РНР
    Сначала учимся правильно соединяться.
    В случае mysqli это
    mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
    $link = mysqli_connect($host, $user, $pass, $db_name);
    $link->set_charset("utf8mb4");

    И никаких ужасов с "Соединение не установлено" тут быть не должно.

    После этого выполняем запрос INSERT. Причем запросы мы всегда пишем так, чтобы данные в БД попадали отдельно от самого запроса. Это непреложное правило, которое надо соблюдать всегда.
    Для этого надо
    • Заменить все переменные в запросе на специальные маркеры, которые называются плейсхолдеры или параметры, а по сути - просто знаки вопроса
    • Подготовить запрос к исполнению с помощью функции prepare(). Эта функция принимает строку запроса и возвращает экземпляр специального класса stmt, с которым в дальнейшем и производятся все манипуляции
    • Привязать переменные к запросу.
    • Выполнить подготовленный ранее запрос с помощью с помощью execute()

    В mysqli это будет так
    $sql = "INSERT INTO `events` (`title`, `discription`, `date`, `img`) VALUES (?,?,?,?)";
    $stmt = $link->prepare($sql);
    $stmt->bind_param("sssss", $title, $discription, $date, $path);
    $stmt->execute();

    bind_param() принимает в качестве параметров все переменные, которые должны попасть в запрос, в том же самом порядке, в котором стоят плейсхолдеры в запросе. Но кроме того, сначала в этой функции должны быть указаны типы для всех переменных, в виде строки, где тип переменной обозначается одной буквой. То есть букв в этой строке должно быть ровно столько, сколько дальше будет переменных. К счастью, можно особо не париться с типами и для всех переменных указывать тип "s".

    И тогда никаких ошибок запроса уже никогда не будет. Не говоря уже о том что при любых других вариантах твой сайт поломает любой пятиклассник.

    Весь код, который добавляет запись в БД, должен быть расположен ДО любого вывода.
    После обработки запроса методом POST необходимо перенаправить клиента куда-нибудь методом GET и завершить работу скрипта. Делается это функцией header с заголовком location: . после которой написать exit;
    Соответственно, никаких ужасов с "Запись добавлена".

    Кстати, немного удобнее с БД работать не через mysqli, а чрез PDO, Тем более что там колупаться с bind_param не нужно, а можно сразу отправить все данные в execute

    Подключение
    $host = '127.0.0.1';
    $db   = 'test';
    $user = 'root';
    $pass = '';
    $port = "3306";
    $charset = 'utf8mb4';
    $options = [
        \PDO::ATTR_ERRMODE            => \PDO::ERRMODE_EXCEPTION,
        \PDO::ATTR_DEFAULT_FETCH_MODE => \PDO::FETCH_ASSOC,
        \PDO::ATTR_EMULATE_PREPARES   => false,
    ];
    $dsn = "mysql:host=$host;dbname=$db;charset=$charset;port=$port";
    $pdo = new \PDO($dsn, $user, $pass, $options);


    Выполнение запроса
    $sql = "INSERT INTO `events` (`title`, `discription`, `date`, `img`) VALUES (?,?,?,?)";
    $stmt = $link->prepare($sql);
    $stmt->execute([$title, $discription, $date, $path]);
    Ответ написан
    1 комментарий
  • Как сформировать запрос к 3-м таблицам сразу?

    FanatPHP
    @FanatPHP
    Чебуратор тега РНР
    с точки зрения оптимизации правильнее чтобы это была одна таблица
    тогда и дурацких вопросов задавать не придётся
    Ответ написан
    4 комментария
  • Почему возникает ошибка SQLSTATE[42000] при запросе обновления в базе данных?

    FanatPHP
    @FanatPHP
    Чебуратор тега РНР
    Потому что бессмысленный говнокод.
    У меня племянница трёхлетняя так дом строит: деревья, мишку плюшевого, колеса от грузовика - всё в дело идёт.
    Но ей хотя бы ума хватает не класть сверху мороженое. А тут всё вперемешку - SQL кривой, prepare используется там где не нужно, и не используется где нужно, каким-то боком mysqli...

    Переменные не пишут прямо в запрос. А передают отдельно. Потому что именно от этого все ошибки и происходят.
    И как раз для этого и используют PDO, с pepare и execute

    $options = [
        \PDO::ATTR_ERRMODE            => \PDO::ERRMODE_EXCEPTION,
        \PDO::ATTR_DEFAULT_FETCH_MODE => \PDO::FETCH_ASSOC,
        \PDO::ATTR_EMULATE_PREPARES   => false,
    ];
    $dbh = new PDO('mysql:dbname=database;host=localhost;charset=$charset', 'usr', 'password', $options);
    
    $stmt = $dbh->prepare("UPDATE posts SET content = ? WHERE id = ?");
    $stmt->execute([$content,$id]);
    echo "Пост - " . $id . PHP_EOL;
    Ответ написан
    Комментировать
  • Как получить имя первичного ключа?

    FanatPHP
    @FanatPHP
    Чебуратор тега РНР
    1. выполняем код
    create table new_tab (id int);
    alter table new_tab add constraint my_primary primary key (id);
    alter table new_tab add key my_primary (id);
    SHOW INDEX FROM new_tab;

    2. думаем
    3. пишем 100 раз на доске фразу, "Я всегда буду задавать вопрос про исходную задачу (как удалить первичный ключ), а не про косяки, с которыми столкнулся при её решении (как узнать имя первичного ключа, чтобы его удалить)"
    Ответ написан
  • Как вывести строку по id php ?id=1?

    FanatPHP
    @FanatPHP
    Чебуратор тега РНР
    Вопрос хороший, но здесь мы упираемся в главную беду пхп - ВСЕ учебники в интернете, и особенно видео - показывают как писать адов говнокод из прошлого века.

    1. Получение значения из адресной строки

    Чтобы получить значение переменной, которую передали в строке запроса (это то что после знака вопроса), надо обратиться к переменной $_GET

    То есть в данном случае можно написать $id = $_GET['id']. Имя получаемой переменной ($id) может быть любым и не обязательно совпадать с переданным значением. А вот в индекс массива $_GET разумеется надо писать именно то имя, которое в адресной строке. То есть если site.com/?id=1 то в $_GET['id'] будет значение 1.

    2. Валидация данных

    Далее очень желательно проверить, что мы в переменной получили то что хотели, а так же что мы вообще хоть что-то получили.

    Сначала надо проверить наличие в массиве $_GET нужного ключа. В данном случае это можно сделать с помощью оператора isset() (хотя вообще она для проверки наличия ключей в массивах не рекомендуется)
    Если для показа информации используем отдельную, специальную страницу, которая только занимается показом данных по айди, то после проверки на существование надо выдать ошибку.

    Затем, поскольку id может быть только целым числом больше нуля, то лучше проверить и это тоже и тоже выдать ошибку.

    3. Соединение с БД.

    в "config.php" должно быть написано не то что там сейчас а вот это (со своими параметрами подключения разумеется)
    mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
    $link = mysqli_connect($host, $user, $pass, $db_name);
    $link->set_charset("utf8mb4");


    4. SQL

    Запрос, который нам нужен, выглядит так:
    SELECT * FROM `product` WHERE id=1

    5. Выполнение запроса в РНР

    Но разумеется вместо 1 надо подставить значение переменной.
    Это самое сложное. Но надо один раз выучить и потом везде применять

    Важно, чтобы данные в БД всегда попадали отдельно от самого запроса. Это непреложное правило, которое надо соблюдать всегда.
    Для этого надо
    1. Заменить все переменные в запросе на специальные маркеры, которые называются плейсхолдеры или параметры, а по сути - просто знаки вопроса
    2. Подготовить запрос к исполнению с помощью функции prepare(). Эта функция принимает строку запроса и возвращает экземпляр специального класса stmt, с которым в дальнейшем и производятся все манипуляции
    3. Привязать переменные к запросу.
    4. Выполнить подготовленный ранее запрос с помощью с помощью execute()
    5. Получить результат запроса через get_result()
    6. и дальше конкретную строку из БД с помощью уже знакомой fetch_assoc


    В коде это будет так
    $sql = "SELECT * FROM `product` WHERE id=?";
    $stmt = $link->prepare($sql);
    $stmt->bind_param("s", $id);
    $stmt->execute();
    $result = $stmt->get_result();
    $row = $result->fetch_assoc();


    bind_param() принимает в качестве параметров все переменные, которые должны попасть в запрос, в том же самом порядке, в котором стоят плейсхолдеры в запросе. Но кроме того, сначала в этой функции должны быть указаны типы для всех переменных, в виде строки, где тип переменной обозначается одной буквой. То есть букв в этой строке должно быть ровно столько, сколько дальше будет переменных. К счастью, можно особо не париться с типами и для всех переменных указывать тип "s".

    6. Вывод данных.

    Важно понимать, что в момент вывода данных никакой работы с БД уже быть не должно!
    Должны быть только переменные РНР с уже полученными данными.
    Ответ написан
    1 комментарий
  • Как взламывают бд крупных компаний?

    FanatPHP
    @FanatPHP
    Чебуратор тега РНР
    Взламывают точно так же как и мелкие.
    В статье описана обычная SQL инъекция, когда данные подставляются прямо в SQL запрос.

    Я просто сомневаюсь, что valve может нанять таких людей в backend

    Не надо сомневаться.
    Нету никаких "особенных способов взлома".
    А есть такое явление как "эффективные менеджеры". У которых размер премии зависит от того, сколько денег они сэкономили акционерам.

    Если бы там были подготовленные выражения, то и взлома бы не было.
    Но вместо подготовленных выражений в больших компаниях есть эффективные менеджеры. Которые экономят на нормальных программистах, и заказывают разработку в Индии, в штате Бангалор. Где живет какой-нибудь Хамишь Кумар, который родился в касте вычерпывателей говна из сортиров. И вот у него только один шанс не черпать говно всю жизнь - всеми правдами и неправдами научиться программировать, путь даже за еду. Сравниваем с силиконовым программером с запросами $250k в месяц. Экономия налицо!

    На всякий случай напомню, для стопроцентной защиты от инъекций необходимо всегда следовать двум простым правилам:

    1. данные подставляем в запрос только через плейсхолдеры
    2. идентификаторы и ключевые слова подставляем только из белого списка, прописанного в нашем коде.


    Ключевое слово здесь - "всегда". Как только начинаются рассуждения вида "ну эти данные и так безопасные, их защищать не надо", то в этот момент мы добавляем инъекцию к себе на сайт. Следует понимать, что защищаем мы не данные, а запрос. Данные нас вообще не интересуют - какие они, откуда пришли, являются "безопасными" или нет. Важно не то откуда они пришли, а то, куда они идут. В SQL запрос? Используем подготовленные выражения, точка.
    Ответ написан
    1 комментарий
  • Как правильно хранить несколько значений внутри поля в MySQL?

    FanatPHP
    @FanatPHP
    Чебуратор тега РНР
    "несколько значений внутри поля" в терминах реляционных баз данных - это отдельная таблица, которая ссылается на строку в исходной таблице. по ид публикации можно будет получить из неё все фотографии
    Ответ написан
    6 комментариев
  • Как ускорить mysql?

    FanatPHP
    @FanatPHP
    Чебуратор тега РНР
    Любые вопросы про "ускорение mysql" необходимо сопровождать не голословными заявлениями "Слющай, использует индексы, мамом клянус!", а ВЫВОДОМ EXPLAIN
    Без которого вопрос в принципе не имеет смысла, и должен удаляться.

    Плюс неплохо сразу выкатить результат SHOW ENGINE INNODB STATUS
    Ответ написан
    Комментировать
  • Ошибка в запросе?

    FanatPHP
    @FanatPHP
    Чебуратор тега РНР
    1. Надо включать отображение ошибок РНР.
    Тогда ПХП тебе бы прямым текстом сказал, что в нет никакой переменной "priceMan". Хотя если смотреть на полный запрос, то скорее отсутствует parpage
    2. Надо использовать для запросов подготовленные выражения
    Тогда даже при отсутствии переменной не будет ошибки запроса. Не говоря уже про взлом сайта

    Даже такая параша, как тухлая фасоль, и то умеет в замещение переменных в запросе

    $params = [
    'min' => $_GET['priceMin'],
    'max' => $_GET['priceMax'],
    'cnt' => $cnt,
    'start' =>$start, 
    'perpage' =>$perpage,
    ]
    $idparam = '';
    foreach ($ids as $i => $item)
    {
        $key = ":id$i";
        $idparam .= $idstr? "," : "" . $key;
        $params[$key] = $item; 
    }
    $filterparam = '';
    foreach ($ids as $i => $item)
    {
        $key = ":f$i";
        $filterparam .= $filterparam? "," : "" . $key;
        $params[$key] = $item; 
    }
    
    
    
    $sql = "SELECT id, articul, category_id, brand_id, title, alias, content, price, old_price, status, keywords, description, img, hit, novinki  
    FROM product 
    WHERE status = '1' AND category_id IN ($idparam) 
    AND price > :min AND price < :max
    AND id IN (SELECT product_id FROM attribute_product WHERE attr_id IN ($filterparam) 
    GROUP BY product_id 
    HAVING COUNT(product_id) = :cnt)
    LIMIT :start, :perpage"
    
    $rows = \R::getAll($sql, $params);
    Ответ написан
  • Как правильно организовать базу даных?

    FanatPHP
    @FanatPHP
    Чебуратор тега РНР
    вопрос довольно сумбурный
    структура БД не определяется структурой "меню".
    непонятна связь между "контентом" и "каталогом"
    непонятно, зачем таблица с меню

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

    обычно каталог - это совсем отдельная тема
    состоит, условно, из двух таблиц - категории и товары
    в твоем случае наверное надо добавить таблицу-связку товаров и городов. Ведь не может же быть так, что в каждом городе продается свой отдельный вариант дверей?
    Ответ написан
    Комментировать
  • Как понять есть ли нагрузка на БД?

    FanatPHP
    @FanatPHP
    Чебуратор тега РНР
    Почему больше всего подписчиков всегда слетается на самые дурацкие вопросы?
    Которым место в мусорке, а не на главной Хабра.
    Ну ведь как в прошлый раз же, весь текст - какие-то бессвязные эротические фантазии, не имеющие ничего общего ни с реальностью, ни друг с другом, ни - главное - с собственно вопросом, который был задан.

    Так вот: я смотрю, что получил 1500 строк из базы за 0.0316 секунд. Это нормально?

    Нет, это ненормально.
    За исключением очень редких и специфических случаев, в РНР мы никогда не запрашиваем больше, чем пользователь может комфортно просмотреть. Ну как бы есть конечно комменты под статьями на хабре, и в отдельных случаях там бывает за тыщу. Но это очень редкий случай. И что-то мне подсказывает, что здесь совсем не он.

    База растёт и строк к выводу станет больше.

    С КАКОГО, я стесняюсь спросить, перепугу, с ростом базы строк к выводу станет больше?
    На тостере с каждым днем прибавляется сотня дебильных вопросов.
    Ты уверен что количество запрашиваемых из базы строк тоже растёт? А если подумать? А если прям вот хорошенько подумать?

    Этот ход мысли напоминает старый еврейский анекдот, который рассказывал Джоэл Спольский в далёком 2001 году:
    Маляр Шлёма подрядился красить пунктирные осевые линии на дорогах. В первый день он получил банку краски, поставил её на дорогу, и к концу дня покрасил 300 метров осевой линии. «Отлично! — сказал прораб. — Быстро работаешь!» и заплатил ему.
    На следующий день Шлёма покрасил 150 метров. «Мда, это, конечно, не так здорово, как вчера, но приемлемо», — сказал прораб и снова заплатил ему.
    Ещё через день Шлёма покрасил всего 30 метров. «Всего лишь 30! — заорал прораб. — Это никуда не годится! В первый день было в десять раз больше! В чём дело?»

    «Ничего не могу поделать, — говорит Шлемиэль. — Каждый день я ухожу всё дальше и дальше от банки!»


    Тебе не кажется что эта логика напоминает твоё "но с каждым днём в БД появляется всё больше и больше записей!"?

    На что ориентироваться? На показатели загрузки процессора или время выполнения запроса или расход памяти?

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

    И вопрос в догонку: если одним запросом я получаю 1500 строк и если в запросе я установлю select нужных мне столбиков - это усложняет запрос или нет? Ведь в первом случае я получаю информацию как есть, а во втором случае процессору надо время чтобы перебрать нужные столбики?!

    Судя по количеству восклицательных знаков - это самый важный вопрос во всём этом и так целиком гениальном тексте. Процессор опасносте!!! Срочно надо спасать!

    Запрос выполняется три сотых секунды, дом рисуется 10, но вопрос почему-то "как узнать , не тормозит ли база?"
    Ну ей-богу, снова как в анекдоте - "Где логика??! Где разум??".

    Сейчас я кеширую результаты php на 60 минут,

    Вот это я понимаю. Сразу заходим с козырей.
    странно что на 60 минут, а не на 24 часа. или вообще сделать сайт статикой. тогда вообще всё летать будет. Или вообще перенести всю БД на клиента. Чего не сделаешь ради борьбы за миллисекунды.

    Как понять есть ли нагрузка на БД?/

    Посмотреть, есть ли нагрузка.
    Тормозит ли сайт, есть ли загрузка по процу и памяти, есть ли отказы в обслуживании, ошибки в логах.
    Если ничего этого нет, то сидеть на попе ровно и ничего не трогать!

    А вместо всяких "оптимизаций" типа кэширования на 60 минут запроса, который выполняется пару сотых секунды, или не на покупки бессмысленного диска, а на букварь про работе с БД. И прочитать там про нормализацию, индексы, базовые команды SQL, пагинацию, в конце концов.

    И тогда и твоя микроскопическая БД в 10 тыщ записей, и нормальная база с миллионами строк, будут работать одинаково быстро и эффективно.
    Ответ написан
    8 комментариев
  • Какой collation выбрать для Mysql базы данных?

    FanatPHP
    @FanatPHP
    Чебуратор тега РНР
    Никакой не выбирать. Выбрать надо charset. utf8mb4.
    А collation подставится сам, по умолчанию.
    Ответ написан
    1 комментарий
  • Как сделать json в mysql пустым, чтобы rowCount возвращал 0?

    FanatPHP
    @FanatPHP
    Чебуратор тега РНР
    $query = $db->prepare("SELECT * FROM `followers` WHERE `author_id`=? AND follower_id=?");
    $query->execute([$authorsID,$followersID]);


    и о чудо! rowCount() внезапно работает!!!!

    if ($query->rowCount() > 0) {
          echo 'subscribed';
    } else {
          echo 'unsubscribed';
    }
    Ответ написан
    Комментировать
  • Как вернуть и кол строк выборки и данные из этой же выборки с заданным лимитом?

    FanatPHP
    @FanatPHP
    Чебуратор тега РНР
    В африке есть такая птица - страус.
    В случае опасности она втыкает голову в песок.
    Поскольку при этом она перестает видеть хищника, и думает что хищник тоже её теряет из виду.

    Все эти попытки и на ёлку влезть и на пони покататься - получить одним запросом и кусок данных, и полное количество - это как раз такое втыкание головы в песок. В наивной надежде что бд там у себя внутри как-то волшебным образом откуда-то прочитает полное количество и отдаст его без напряга. Не отдаст. Там внутри будет все равно два запроса. И хорошо если без временной таблицы.

    Для тех, кому ехать, а не шашечки. единственный реальный и осмысленный вариант
    SELECT COUNT(*) FROM ## задача с блекджеком и JOIN'ами
    SELECT * FROM /* задача с блекджеком и JOIN'ами */ LIMIT 150


    а "ресурсоёмкие" запросы надо оптимизировать. чтобы они перестали быть ресурсоёмкими.
    Ответ написан
  • В mysql для быстрого поиска по дате лучше использовать timestamp как int или как date (datetime)?

    FanatPHP
    @FanatPHP
    Чебуратор тега РНР
    Для скорости абсолютно без разницы, а для хранения даты и времени надо использовать предназначенные для этого типы данных
    Ответ написан
    6 комментариев
  • Выгрузка картинки из базы mysql?

    FanatPHP
    @FanatPHP
    Чебуратор тега РНР
    Этот вопрос надо отлить в граните и поместить в палате мер и весов, в виде большой квадратной доски.
    И всех любителей хранить картинки в базе "это же так удобно!!!" заставлять биться об нее головой, пока вся эта дурь из головы не вылетит.
    Ответ написан
    7 комментариев