Что не так с MariaDB в отношении неправильных или отсутствующих значений в SQL?

Я выполняю следующий запрос к таблице: <br/> <pre><code class="lua">function DelAcc_GET_PersonsCreate(sid)
    local query = [[
        SELECT PersonsCreate FROM qq_player_acc WHERE SteamID = '^sid'
    ]]
    query = query:gsub("%^sid", sid)
    return tonumber(do_query_data(query))
end</code></pre> <br/> Результат запроса может быть либо nil, либо 2 (в случае, когда данные собираются) - <br/> <pre><code class="lua">function DelAcc_Start_MySQL(login, sid, time)
    local query = [[
        INSERT INTO qq_player_acc(
        Login,
        SteamID,
        qqCoin,
        Rep,
        Persons,
        PersonsCreate,
        DateCreate,
        LastVisit)
        SELECT 
            '^login',
            '^sid',
            '50',
            '0',
            '0',
            '2',
            '^time',
            '^time'
        
        WHERE NOT EXISTS(SELECT * FROM qq_player_acc WHERE SteamID='^sid');
        ]];
    
    query = query:gsub("%^login", login)
    query = query:gsub("%^sid", sid)
    query = query:gsub("%^time", time)

    do_query(query)
end</code></pre> <br/> Здесь аналогия заключается в том, что при отсутствии данных они создаются и заполняются конкретной информацией с сервера. 
  • 9 декабря 2024 г. 9:43
Ответы на вопрос 2
В вашем коде есть несколько моментов, которые могут вызвать проблемы, особенно в контексте работы с MariaDB и в отношении обработки неправильных или отсутствующих значений в SQL. Ниже приведены основные моменты, на которые стоит обратить внимание:

1. **SQL-инъекции**: Ваш метод замены строк для подстановки значений в запрос подразумевает наличие уязвимости для SQL-инъекций. Используйте подготовленные выражения и параметры для безопасной работы с пользовательскими данными.

2. **Проверка на наличие данных**: В вашем запросе `DelAcc_Start_MySQL`, вы проверяете существование записи в таблице `qq_player_acc` перед вставкой новых данных с помощью конструкции `WHERE NOT EXISTS`. Это хороший подход для предотвращения дублирования, но если ваше условие не срабатывает (например, если `SteamID` неправильно), вставка не будет выполнена.

3. **Значения по умолчанию**: Если в вашей таблице есть поля, которые могут принимать `NULL` или имеют значения по умолчанию, убедитесь, что они правильно обрабатываются. Например, если вы захотите добавить ещё один параметр и не передадите для него значение, это может привести к ошибкам.

4. **Тип данных**: Убедитесь, что передаваемые в запрос значения соответствуют ожидаемым типам данных в базе данных. Например, если вы ожидаете `INTEGER`, передачи строкового значения может привести к ошибкам.

5. **Обработка NULL значений**: Функция `tonumber` может возвращать `nil`, если преобразование не удалось. Убедитесь, что ваше приложение корректно обрабатывает `nil` значения, чтобы избежать дальнейших ошибок.

6. **Отладка запросов**: Если запросы не работают, полезно выводить их в логи для отладки. Таким образом, вы сможете увидеть, какие именно запросы отправляются на сервер и какие именно данные они содержат.

Пример улучшенной обработки входных данных с использованием подготовленных выражений на синтаксисе Lua (это гипотетический пример, так как не все базы данных поддерживают такой синтаксис):

```lua
function DelAcc_Start_MySQL(login, sid, time)
    local query = [[
        INSERT INTO qq_player_acc(Login, SteamID, qqCoin, Rep, Persons, PersonsCreate, DateCreate, LastVisit)
        VALUES (?, ?, 50, 0, 0, 2, ?, ?)
        WHERE NOT EXISTS(SELECT 1 FROM qq_player_acc WHERE SteamID=?)
    ]]

    -- Вставьте параметры вместо подстановок (конкретная реализация зависит от используемой библиотеки для работы с БД)
    do_query_prepared(query, login, sid, time, time, sid)
end
```

Это только пример, и он будет зависеть от того, какую библиотеку вы используете для работы с MariaDB в Lua. Основная цель - минимизировать риски и быть уверенным в корректности передаваемых данных.
По смыслу происходящего во втором блоке кода - значение в поле SteamID таблицы qq_player_acc должно быть уникальным. 

Соответственно два вопроса.

1. Объявлено ли указанное поле в структуре указанной таблицы уникальным? Если нет - то почему? Добавьте требование уникальности.

2. Что мешает выполнить обычный INSERT IGNORE или, если надо обновлять существующую запись введёнными значениями, то INSERT ODKU или REPLACE INTO?

PS. INSERT {table} .. WHERE EXISTS ( {table} ) - вообще-то недопустимый синтаксис.
Похожие вопросы