Знаете что-нибудь о MySQL или SQLite? Если нет, сходите и почитайте.

Все, кто в танке хотя бы раз пользовались базами данных (БД) для хранения каких-либо своих (или чужих) данных. MySQL - думаю, все знают и юзают, SQLite - реже, но тоже неплохой вариант. До недавнего времени приконектится к MySQL серверу можно было только с помощью серверного модуля, и создавать свои собственные SQLite базы данных (БД) в МТА было невозможно. Но благодаря самым активным разработчикам МТА, все эти неудобства ушли в историю. Теперь мы имеем встроенные функции для работы с MySQL / SQLite. О них и пойдет речь.

Для работы с БД нам нужны только эти функции:

dbConnect - приконектится к базе данных / открыть базу данных
dbExec - выполнить запрос без возврата результата
dbQuery - выполнить запрос с возвратом результата
dbPoll - получить результат запроса из памяти
dbFree - удалить результат запроса из памяти
destroyElement - закрыть соединение с базой данных / закрыть базу данных

Сразу даю небольшие разъяснения:

● Ссылка (на соединение или БД), которую возвращает функция dbConnect(при успехе) - это элемент. Поэтому, чтобы закрыть соединение (закрыть БД) нужно юзать destroyElement.
● Ссылка, которую возвращает функция dbQuery (при успехе) - это не элемент, это просто уникальный ИД.
● Много открытий и закрытий БД (соединений) будут ощутимо тормозить ваш сервер, поэтому желательно открывать БД (соединение) при старте ресурса, а закрывать - при остановке ресурса. А саму ссылку на БД можно сохранить в глобальной переменной, например, тогда все скрипты ресурса смогут ее использовать.
● Если вы плохо знаете SQL синтаксис, сначала подучите его до уровня "выше среднего" во избежание глупых ошибок.

MySQL

Чтобы быстро понять способы работы с этими функциями, начнем с примеров.
Допустим, у нас рядом с сервером на том же хосте (локальный IP - 127.0.01) запущен MySQL сервер на 54321 порту.
Имя юзера для доступа - testUser, пароль для этого юзера - testPassword, а имя БД - testDB.

Коннектимся к MySQL серверу ( dbConnect )

Код:
-- создаем глобальную переменную для хранения ссылки на коннект 
sqlLink = dbConnect ( 
    "mysql", -- тип базы данных 
    "host=127.0.0.1;port=54321;dbname=testDB", -- хост, порт, имя БД 
    "testUser", -- юзер 
    "testPassword" -- пароль юзера 
)

Выполняем запросы, результаты которых нам не нужны ( dbExec )
Тексты запросов:

Код:
CREATE TABLE IF NOT EXISTS testTable (  id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,  name VARCHAR(32),  password VARCHAR(24),  money INT); 
INSERT INTO testTable ( name, password, money )  VALUES ( 'MX_Master', '1245', 1500 );
Код:
-- создаем таблицу 
dbExec ( 
    sqlLink, -- ссылка на коннект с базой 
  
    -- запрос 
    -- [[ и ]] это просто кавычки (в языке LUA) для многострочных строк  
    [[CREATE TABLE IF NOT EXISTS ?? ( 
        ?? INT AUTO_INCREMENT PRIMARY KEY, 
        ?? VARCHAR(32), 
        ?? VARCHAR(24), 
        ?? INT );]], 
  
    -- параметры, которые будут подставлены в запрос вместо знаков "??". 
    -- если юзать "?" вместо "??", то все строки будут экранированы и с кавычками 
    "testTable", -- заменяет первый знак "??" 
    "id", -- заменяет второй знак "??" 
    "name", -- заменяет третий знак "??" 
    "password", -- заменяет четвертый знак "??" 
    "money" -- заменяет пятый знак "??" 
)
Код:
-- добавляем одну запись 
dbExec ( 
    sqlLink, -- ссылка на коннект с базой 
  
    -- запрос 
    [[INSERT INTO testTable ( name, password, money ) 
          VALUES ( ?, ?, ? );]], 
  
    -- параметры, которые будут подставлены в запрос вместо знаков "?" 
    "MX_Master", 
    "1245", 
    1500 
)

Сделаем запрос, результат которого нам пригодится ( dbQuery, dbPoll, dbFree )
Будем юзать колбэк функцию, которая должна сама выполнится когда результат запроса будет готов.

Код:
-- делаем выборку 
dbQuery ( 
    -- это одноразовая функция, которая вызовется, когда выполнится запрос 
    function ( queryHandle ) -- queryHandle это уникальный ИД результата запроса 
        -- получим результат запроса 
        local resultTable, num, err = dbPoll( queryHandle, 0 ) 
  
        -- проверим результат 
        if resultTable then 
            outputChatBox('Запрос выполнен:') 
  
            for rowNum, rowData in ipairs(resultTable) do 
                outputChatBox( '  запись '..rowNum..': '..rowData['id']..', '..rowData['name']..', '..rowData['password']..''..rowData['money']) 
            end 
        elseif resultTable == nil then 
            outputChatBox('Запрос еще не выполнен.') 
            dbFree(queryHandle) -- очистим память от результата 
        elseif resultTable == false then 
            -- num в данном случае код ошибки, а err это описание ошибки 
            outputChatBox('Ошибка в запросе, код '..num..': '..err) 
        end 
    end, 
  
    sqlLink, -- ссылка на коннект с базой 
  
    -- запрос 
    "SELECT * FROM testTable;" 
)

Если все правильно, то результат будет примерно такой:

Запрос выполнен:  запись 1: 1, MX_Master, 1245, 1500

Закроем соединение ( destroyElement)

Код:
destroyElement( sqlLink )

SQLite

Для SQLite многое аналогично MySQL, но открывать БД нужно слегка иначе.
Вместо хоста нужно указывать путь к файлу БД. Если путь начинается с ":/" (например ":/public.db"), то файл БД будет открыт/создан в общей папке сервера для SQLite БДшек.
Если путь начинается с ":ИМЯ_РЕСУРСА/" (например ":play/test.db"), то файл БД будет открыт/создан в папке указанного ресурса.
В остальных случаях файл БД будет открыт/создан в папке текущего ресурса, в котором выполняется скрипт.
Заметка: если файл БД не существует, то он будет создан.

Открываем файл БД
( dbConnect )

Код:
-- создаем глобальную переменную для хранения ссылки на коннект 
sqlLink = dbConnect ( 
    "sqlite", -- тип базы данных 
    "test.db" -- путь к файлу БД 
)

Выполняем запросы, результаты которых нам не нужны ( dbExec )
Тексты запросов:

Код:
CREATE TABLE IF NOT EXISTS testTable (  id INTEGER AUTOINCREMENT PRIMARY KEY,  name TEXT,  password TEXT,  money INTEGER); 
INSERT INTO testTable ( name, password, money )  VALUES ( 'MX_Master', '1245', 1500 );
Код:
-- создаем таблицу 
dbExec ( 
    sqlLink, -- ссылка на коннект с базой 
  
    -- запрос 
    -- [[ и ]] это просто кавычки (в языке LUA) для многострочных строк  
    [[CREATE TABLE IF NOT EXISTS testTable ( 
        id INTEGER AUTOINCREMENT PRIMARY KEY, 
        name TEXT, 
        password TEXT, 
        money INTEGER );]] 
)
Код:
-- добавляем одну запись 
dbExec ( 
    sqlLink, -- ссылка на коннект с базой 
  
    -- запрос 
    [[INSERT INTO testTable ( name, password, money ) 
          VALUES ( 'MX_Master', '1245', 1500 );]] 
)

Чтобы не повторяться в этот раз сделаем запрос и обойдемся без колбэк функции ( dbQuery, dbPoll, dbFree )

Код:
local queryHandle = dbQuery( 
    sqlLink, -- ссылка на коннект с базой 
  
    -- запрос 
    "SELECT * FROM testTable;" 
) 
  
-- ждем результата (сервер в это время простаивает) 
local resultTable, num, err = dbPoll ( queryHandle, -1 ) 
  
-- проверим результат 
if resultTable then 
    outputChatBox('Запрос выполнен:') 
     
    for rowNum, rowData in ipairs(resultTable) do 
        outputChatBox( '  запись '..rowNum..': '..rowData['id']..', '..rowData['name']..', '..rowData['password']..''..rowData['money']) 
    end 
elseif resultTable == nil then 
    outputChatBox('Запрос еще не выполнен.') 
    dbFree(queryHandle) -- очистим память от результата 
elseif resultTable == false then 
    -- num в данном случае код ошибки, а err это описание ошибки 
    outputChatBox('Ошибка в запросе, код '..num..': '..err) 
end

Если все правильно, то результат будет примерно такой:

Запрос выполнен:  запись 1: 1, MX_Master, 1245, 1500

Закроем соединение ( destroyElement)

Код:
destroyElement( sqlLink )

Автор урока: MX_Master

Теги: MySQL,SQLite,Встроенные функции