Знаете что-нибудь о 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,Встроенные функции