Ответы пользователя по тегу MySQL
  • Как синхронизировать столбцы в SQL?

    @Akina
    Сетевой и системный админ, SQL-программист.
    Если связь между значениями - статическая, жёсткая и никогда не изменяемая, то используйте вычисляемое поле (generated column). Если значение поля, от которого зависит другое поле - числовое от единицы и далее, можно обойтись одним полем типа ENUM.

    Если же связь более сложная и/или может меняться со временем, то гораздо разумнее не заполнять второе поле в зависимости от первого, а использовать его значение как ссылку (foreign key) в словарную таблицу.

    Крайний случай - использование BEFORE INSERT/UPDATE триггеров.
    Ответ написан
    Комментировать
  • Как правильно будет сделать JOIN?

    @Akina
    Сетевой и системный админ, SQL-программист.
    andry33822, огорчу. Описанная мной в комментарии к вопросу процедура требует ВСТАВКИ записи в таблицу users и ОБНОВЛЕНИЯ существующей записи в таблице users_apikey. То есть INSERT в одну таблицу + UPDATE другой таблицы.

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

    CREATE TRIGGER tr_assign_apikey_to_user
    AFTER INSERT 
    ON users
    FOR EACH ROW
    UPDATE users_apikey SET username = NEW.username WHERE username = '' LIMIT 1;


    DEMO fiddle

    Правда, триггер простейший, и ничего не проверяет. По-хорошему надо как минимум проверить, что свободный apikey - есть, и если нет - то сгенерировать ошибку добавления юзера. Ну и не исключаю дополнительных условий - например, мне лично запись в apikey, не имеющая вменяемого значения в поле namekey, как-то не нравится.
    Ответ написан
    Комментировать
  • Что происходит при повторном запуске команды MySQL source?

    @Akina
    Сетевой и системный админ, SQL-программист.
    Что происходит при повторном запуске? Проверяется наличие уже импортированных записей, они пропускаются и импортируется отсутствующие?

    Никаких проверок. Запуск с самого начала.

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

    В общем, как обычно. Если возникла ошибка, надо не пытаться запустить повторно, типа авось пролезет (почти наверняка - не пролезет), а разбираться, почему возникла ошибка, и устранять причину.
    Ответ написан
    Комментировать
  • Как восстановить базу sql из файлов /var/lib/mysql/* на другом сервере mysql?

    @Akina
    Сетевой и системный админ, SQL-программист.
    При попытки создать mysqldump база выдаёт ошибку:
    Illegal mix of collations (utf8_unicode_ci,COERCIBLE) and (utf8_general_ci,COERCIBLE) for operation 'locate'

    Скорректируйте @@collation_connection.

    Задача сделать копию битой БД mysql ... как из файлов "холодного резерва" создать sql-файл или как эту базу развернуть на другом сервере mysql?

    А смысл? если подключить файлы данных в новом местоположении, ошибки никуда не денутся.

    А так - создать таблицы в новом местоположении. Структура должна совпадать с точностью до запятых, и версия сервера тоже. Самое разумное - сделать бэкап чисто структуры, без данных, и развернуть. А потом DISCARD/IMPORT TABLESPACE, либо замена файлов при остановленном сервисе и последующий запуск с лечением и перезаписью метаданных и статистики.
    Ответ написан
  • Как правильно импортировать много данных из json в mysql?

    @Akina
    Сетевой и системный админ, SQL-программист.
    Artikul2,
    MySQL 8.0.28-0ubuntu0.20.04.3


    Не делай ничего с этим JSON. Отдай его как есть на MySQL - у него парсинг получится лучше...
    INSERT INTO test (name, position, city, postcode, entered_at, income)
    SELECT data ->> '$[0]' name,
           data ->> '$[1]' position,
           data ->> '$[2]' city,
           data ->> '$[3]' postcode,
           STR_TO_DATE(data ->> '$[4]', '%Y\/%m\/%d') entered_at,
           REPLACE(SUBSTRING(data ->> '$[5]' FROM 2), ',', '') income
    FROM JSON_TABLE(@data,
                    '$.data[*]' COLUMNS (data JSON PATH '$')) jsontable


    https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=8c5e1c...

    Если надо отсеивать дубликаты - создать соотв. уникальный индекс, и использовать INSERT ODKU, REPLACE INTO либо INSERT IGNORE.
    Ответ написан
  • Как сменить пользователя в MySQL?

    @Akina
    Сетевой и системный админ, SQL-программист.
    Как сменить пользователя в MySQL?

    В текущем соединении - никак. Только (закрыть это и) создать новое соединение, с использованием другой учётной записи.
    Ответ написан
  • Как работать с готовой базой данных sql?

    @Akina
    Сетевой и системный админ, SQL-программист.
    Это не база данных. Это дамп - переносимая копия структуры и данных, позволяющая воссоздать базу данных.

    В комментариях дампа указано, что источником дампа послужил сервер MySQL версии 8.0.28. Поэтому восстанавливать следует на сервере MySQL, причём крайне желательно на версии не ниже 8.0.4. При восстановлении на более младшей версии или на частично совместимой MariaDB возможны проблемы при восстановлении, которые потребуют ручной корректировки дампа - а для этого нужны определённые знания, которых, скорее всего, нет.

    Для восстановления на локальном MySQL-сервере самое разумное - загрузить клиент командной строки и в нём:
    • создать новую БД (CREATE DATABASE databasename;) (в комментариях дампа указано имя history_futures_binance, так что разумно использовать именно его, если такой БД на сервере нет)
    • сделать её текущей (USE databasename)
    • дать команду на развёртывание дампаSOURCE 'x:\path\filename.sql'.

    Скорее всего, всё будет выполнено без ошибок, и в результате БД будет восстановлена. Если же при выполнении возникнут проблемы, будет выведено какое-то сообщение об ошибке - и в зависимости от него нужно будет предпринимать какие-то корректирующие действия.
    Ответ написан
    Комментировать
  • Как удалить из трех или более таблиц mysql по одному id?

    @Akina
    Сетевой и системный админ, SQL-программист.
    DELETE 
    FROM userdata, moneys, user_roles 
    USING ( SELECT 525300849082105856 userid ) criteria
    LEFT JOIN userdata USING (userid)
    LEFT JOIN moneys USING (userid)
    LEFT JOIN user_roles USING (userid);
    Ответ написан
    1 комментарий
  • Почему LIKE разделяет _E на _ и Е - mysql?

    @Akina
    Сетевой и системный админ, SQL-программист.
    Если ничего не помогает, попробуйте почитать документацию.

    LIKE operator

    With LIKE you can use the following two wildcard characters in the pattern:

    • % matches any number of characters, even zero characters.
    • _ matches exactly one character.
    Ответ написан
    1 комментарий
  • Как посчитать общую длительность времени между строками определенной выборки в MySQL?

    @Akina
    Сетевой и системный админ, SQL-программист.
    WITH cte AS ( SELECT *, 
                         LAG(`datetime`) OVER (PARTITION BY login ORDER BY `datetime`) lag_datetime, 
                         LAG(event) OVER (PARTITION BY login ORDER BY `datetime`) lag_event 
                  FROM history )
    SELECT login, SUM(TIMESTAMPDIFF(MINUTE, lag_datetime, `datetime`)) duration
    FROM cte
    WHERE (event, lag_event) = (2,1)
    GROUP BY login;

    https://dbfiddle.uk/?rdbms=mariadb_10.6&fiddle=398... (исходные данные подправлены).
    Ответ написан
    1 комментарий
  • Как использовать maxmind GeoLite2 на mysql 5.5, где нет inet6_aton?

    @Akina
    Сетевой и системный админ, SQL-программист.
    В результате надо получить таблицу, в которой будут только IPv4 адреса

    Не вижу проблемы. Импорт не использует inet6_aton. Соответственно после импорта можно просто удалить записи с IPv6-адресами. А затем ещё и изменить тип поля на VARBINARY(4).
    Ответ написан
  • Как группировать данные, если у них есть уникальные id?

    @Akina
    Сетевой и системный админ, SQL-программист.
    Вы пытаетесь сделать откровенную глупость, выводя значение id в итоговом наборе.

    Вот есть некая группа, в ней все off_id одинаковы, но id различны. После группировки все эти записи будут сгруппированы в одну. А теперь, внимание, вопрос: ну и какое одно значение id из всех возможных сервер должен вернуть? не знаете? так ведь и сервер не знает... вот он и генерирует ошибку.

    Уберите id из выходного набора. Либо явно и чётко скажите серверу, какое именно значение из всех возможных в группе он должен вернуть. Наименьшее? требуйте MIN(id). Наибольшее? MAX(id). Хоть какое, любое? ANY_VALUE(id).
    Ответ написан
    Комментировать
  • Как выполнить SELECT с таким условием?

    @Akina
    Сетевой и системный админ, SQL-программист.
    aopil,
    а для более старых версий невозможно выполнить то, что я хочу?


    SELECT *
    FROM services
    JOIN (
        SELECT *,
               @row_number := CASE WHEN service_id = @service_id
                                   THEN @row_number + 1
                                   ELSE 1
                                   END rownumber,
               @service_id := service_id
        FROM orders
        CROSS JOIN (SELECT @service_id := 0, @row_number := 0) init_vars
        ORDER BY service_id, id DESC
        ) enumerated_orders USING (service_id)
    WHERE enumerated_orders.rownumber <= services.service_limit

    https://dbfiddle.uk/?rdbms=mysql_5.7&fiddle=1f2a95...
    Ответ написан
    1 комментарий
  • Как изменять значение в бд по времени?

    @Akina
    Сетевой и системный админ, SQL-программист.
    Информация о том, что пользователь оплатил подписку заносится в бд (есть отдельная строка, в которой изначальное значение равно нулю, а при оплате меняется на 1).

    В комплекте с информацией о факте оплаты должна существовать и информация о дате-времени открытия доступа по подписке. Кстати, в этом случае сама информация о факте оплаты не нужна, достаточно просто самого факта наличия момента оплаты либо срока действия оплаченного доступа.

    значение сменилось на 1, а потом через месяц само сменилось на 0.

    Для этого у MySQL есть свой встроенный планировщик. Запускаем, создаём процедуру, которая выполняется, например, ежеминутно, и обнуляет поле доступа для всех записей, у которых разница между текущим штампом времени и штампом времени открытия доступа превышает срок доступа (хардкод, либо взятый из служебной таблицы или даже из обрабатываемой записи).

    MySQL 8.0 Reference Manual / Stored Objects / Usin...
    Ответ написан
    Комментировать
  • База данных MySql, как сделать переменную, с индивидуальным значением для всех аккаунтов?

    @Akina
    Сетевой и системный админ, SQL-программист.
    Ну вообще-то под такие цели обычно создаётся специальная служебная таблица.
    Ответ написан
    2 комментария
  • Есть вариант сохранить в поле json (mysql) массив с нужным порядком?

    @Akina
    Сетевой и системный админ, SQL-программист.
    фишка в том, что в бд порядок меняется, условно скажем, после того, как вытащишь из бд и превратишь обратно в массив, он уже принимает вот такой вид

    Согласно описанию формата, порядок элементов внутри объекта не существует (вернее, не определён), и его поддержание не гарантируется. В отличие от массива.
    Так что если порядок важен, то каждая запись должна быть преобразована в отдельный объект, а все они - сложены в массив в нужном порядке, т.е. JSON должен выглядеть, например, так:
    '[{"a":1}, {"b":2}, {"c":3}]'

    Я его превращаю в json (json_encode), и кладу в бд.

    Покажите точно, как выглядит этот JSON.
    Покажите точный CREATE TABLE таблицы, в которую кладёте.
    Покажите, как точно выглядит в таблице положенное туда JSON значение.
    Покажите точно это же JSON значение после обратного извлечения.

    Да, всё это - для одного и того же JSON.
    Ответ написан
    Комментировать
  • Как заменить строку на цифры у оператора IN?

    @Akina
    Сетевой и системный админ, SQL-программист.
    Если передаваемый параметр - это CSV идентификаторов, то следует использовать
    SELECT *
    FROM `users`
    WHERE FIND_IN_SET(id, ?);


    Примечание 1. CSV не должен содержать никаких паразитных пробелов (а то любят всякие "украшатели" понатыкать пробелов после запятой).
    Примечание 2. Такой запрос - гарантированный фуллскан. Зато не будет инъекции.

    PS. В принципе этот CSV несложно довести до состояния JSON array (всего-то две скобки добавить) - тогда можно применить JSON_CONTAINS(), что может быть немного быстрее. А уж если переданный JSON распарсить на отдельные значения с помощью JSON_TABLE(), так ещё и от фуллскана избавимся (правда, версия сервера нужна достаточно свежая).
    Ответ написан
    2 комментария
  • Почему выдает ошибку 1442?

    @Akina
    Сетевой и системный админ, SQL-программист.
    CREATE DEFINER=root@localhost
    TRIGGER bi_trigger_in_employees
    BEFORE INSERT ON employees 
    FOR EACH ROW 
    SET NEW.entpr_name = COALESCE( NEW.entpr_name, 
                                   ( SELECT ap_name 
                                     FROM companies 
                                     WHERE id = NEW.entpr_id 
                                     LIMIT 1
                                    )
                                  ),
        NEW.employee_name = COALESCE( NEW.employee_name, 
                                      ( SELECT CONCAT_WS(' ',np_surname,np_name,np_patronymic) 
                                        FROM people 
                                        WHERE id = NEW.employee_id
                                        LIMIT 1
                                       )
                                     );

    1) Суть ошибки - именно та, что написана в сообщении. Нельзя UPDATE таблицы, на которой определён триггер (и другие DML - тоже нельзя).
    2) Изменять вставляемые значения надо до вставки, а не после. Потому BEFORE триггер.
    3) По-хорошему, нужен ещё аналогичный BEFORE UPDATE триггер.
    4) Все SET выполняются в одном операторе (см. https://dev.mysql.com/doc/refman/8.0/en/set-variab...). А триггер из одного оператора обходится и без BEGIN-END, и без DELIMITER.
    5) При скалярном присвоении из подзапроса ВСЕГДА добавляйте LIMIT 1. А по-хорошему ещё и ORDER BY. На показанный код ни то, ни другое не влияет - всё равно одна запись, ибо отбор по PK. Но вдруг структура поменяется, а про триггер забудете? Начнутся ошибки - оно надо?

    тогда да, ошибка на бесконечный цикл. Но тут почему?

    Как это ни странно, но в теле триггера неизвестно, на какое событие определён триггер.
    Ответ написан
    1 комментарий
  • Как разбить одну таблицу на две и правильно заполнить её данными из импорта?

    @Akina
    Сетевой и системный админ, SQL-программист.
    CREATE TABLE client ( clientid INT AUTO_INCREMENT PRIMARY KEY,
                          firstname VARCHAR(255),
                          lastname VARCHAR(255),
                          phone BIGINT,                           -- если исходный VARCHAR - поменять, 
                                                                  -- либо соотв. преобразование в INSERT
                          UNIQUE (firstname, lastname, phone) );  -- можно потом удалить
    
    INSERT INTO client (firstname, lastname, phone)
        SELECT DISTINCT firstname, lastname, phone
        FROM orders_old;
    
    CREATE TABLE order ( orderid INT AUTO_INCREMENT PRIMARY KEY,
                         ordernumber INT,
                         clientid INT,
                         FOREIGN KEY (clientid) REFERENCES client (clientid) );
    
    INSERT INTO order (ordernumber, clientid)
        SELECT orders_old.ordernumber, client.clientid
        FROM orders_old
        JOIN client USING (firstname, lastname, phone);

    NOT NULL - по вкусу.
    Ответ написан
    1 комментарий
  • Как задать поиск по совпадения в 2 и более слов?

    @Akina
    Сетевой и системный админ, SQL-программист.
    Нужно каждое слово оборачивать в %?

    Нет. Вернее, этого недостаточно.
    Условие WHERE name LIKE '%сок%перс%', конечно, не пропустит указанные нежелательные записи - но и "Персиковый сок" тоже будет отброшен.

    Нужно проверять наличие каждого слова отдельно.

    SELECT *
    FROM table
    WHERE name LIKE '%сок%'
      AND name LIKE '%перс%';
    Ответ написан
    Комментировать