В данной статье я постараюсь рассказать основы работы с модулем sqlx(mysql)
Данная статья рассчитана исключительно для новичков и тем, кто уже работал с mysql не найдут здесь ничего нового.
Для начала создадим чистый sma файл в данным содержанием
- Код: Выделить всё
#include <amxmodx>
#include <amxmisc>
#include <sqlx>
#define PLUGIN_NAME "[TUT]Mysql"
#define PLUGIN_VERSION "0.1"
#define PLUGIN_AUTHOR "BaJIeHoK(amx-x.ru)"
public plugin_init()
{
register_plugin(PLUGIN_NAME, PLUGIN_VERSION, PLUGIN_AUTHOR)
}
Как видите сразу подключили модуль sqlx.
Для быстрого изменение данных подключение к mysql мы создадим дефайны
- Код: Выделить всё
#define SQLX_HOSTNAME "127.0.0.1"
#define SQLX_USERNAME "root"
#define SQLX_PASSWORD ""
#define SQLX_DBNAME "tut_mysql"
Расшифровка( если вдруг кто не понял )
SQLX_HOSTNAME //Хост базы данных mysql
SQLX_USERNAME //Имя пользователя базы данных
SQLX_PASSWORD //Пароль базы данных
SQLX_DBNAME //Собственно сама база данных
И так мы подготовили всё - сейчас будем создавать код самого подключение к базе.
Размещать мы его будем в функции plugin_precache() для большей надежности, потому что данная функция вызывается раньше всех.
Для начала нам требуется создать обработчики для подготовки данных к подключению и самого подключения.
- Код: Выделить всё
new Handle:SQLX_Tuple
new Handle:SQLX_Connection
SQLX_Tuple //Будет служить обработчиком подготовленных данных для подключение
SQLX_Connection //Будет служить обработчиком самого подключения к mysql
Теперь создаем саму функцию plugin_precache()
- Код: Выделить всё
public plugin_precache()
{
new szError[512] //Сюда будет записана ошибка подключение к базе
new iError //Сюда будет записан код ошибки
SQLX_Tuple = SQL_MakeDbTuple(SQLX_HOSTNAME, SQLX_USERNAME, SQLX_PASSWORD, SQLX_DBNAME) //Подготавливаем данные
SQLX_Connection = SQL_Connect(SQLX_Tuple, iError, szError, charsmax( szError )) //Совершаем коннект к базе
if(SQLX_Connection == Empty_Handle) //Если при подключении возникли ошибки
set_fail_state( szError ) //Завершаем работу плагина и выводим ошибку
SQL_FreeHandle( SQLX_Connection ) //В случаи успешного соединения - закрываем его
}
И так мы закончили со всей подготовкой. В конечном итоге у вас должно получится это
- Код: Выделить всё
#include <amxmodx>
#include <amxmisc>
#include <sqlx>
#define PLUGIN_NAME "[TUT]Mysql"
#define PLUGIN_VERSION "0.1"
#define PLUGIN_AUTHOR "BaJIeHoK(amx-x.ru)"
#define SQLX_HOSTNAME "127.0.0.1"
#define SQLX_USERNAME "root"
#define SQLX_PASSWORD ""
#define SQLX_DBNAME "tut_mysql"
new Handle:SQLX_Tuple
new Handle:SQLX_Connection
public plugin_init()
{
register_plugin(PLUGIN_NAME, PLUGIN_VERSION, PLUGIN_AUTHOR)
}
public plugin_precache()
{
new szError[512]
new iError
SQLX_Tuple = SQL_MakeDbTuple(SQLX_HOSTNAME, SQLX_USERNAME, SQLX_PASSWORD, SQLX_DBNAME)
SQLX_Connection = SQL_Connect(SQLX_Tuple, iError, szError, charsmax( szError ))
if(SQLX_Connection == Empty_Handle)
set_fail_state( szError )
SQL_FreeHandle( SQLX_Connection )
}
Теперь мы можем добавлять, получать, изменять данные. Чем сейчас и займемся
Для начала создадим 3 внешних команды
- Код: Выделить всё
register_clcmd("say /sqlx_create", "SQLXCreate") //Будем создавать запись
register_clcmd("say /sqlx_select", "SQLXSelect") //Будем получать запись
register_clcmd("say /sqlx_update", "SQLXUpdate") //Будем обновлять запись
Переходим к созданию функции SQLXCreate
Она будем служить добавлением данных в базу, а что конкретно добавлять - выбираете только вы. В качестве примера мы отправим в базу SteamID игрока и его времяпровождение на сервере
- Код: Выделить всё
public SQLXCreate(id)
{
new szSteamID[32] //Сюда запишем SteamID игрока
new szQuery[512] //Сюда запишем запрос к базе
new szID[1] //Сюда запишем id игрока
szID[0] = id //Записываем id игрока
get_user_authid(id, szSteamID, charsmax( szSteamID )) //Получаем SteamID игрока
formatex(szQuery, charsmax( szQuery ), "SELECT * FROM `test` WHERE (`test`.`steamid` = '%s')", szSteamID) //Составляем запрос
SQL_ThreadQuery(SQLX_Tuple, "SQLXQuery", szQuery, szID, sizeof szID) //Отправляем запрос на обработку
}
А теперь разберем всё то, что сделали
- Код: Выделить всё
formatex(szQuery, charsmax( szQuery ), "SELECT * FROM `test` WHERE (`test`.`steamid` = '%s')", szSteamID)
SELECT - оператор, позволяющий извлечь строки из таблицы
* - Это значит, что мы получим все ячейки из таблицы. Так же мы можем получать отдельные данные из таблицы например steamid, time ну и так далее. Всё зависит от того какие у вас будут ячейки
FROM - обозначает откуда будут браться данные
`test` - Сюда записывается таблица откуда будем брать данные( об этом будет рассказано подробнее ниже )
WHERE - оператор, позволяющий сделать выборку по получаемым данным. В данном случаи мы будем искать только наш steamid, чтобы не получать кучу левых данных
`test`.`steamid` = '%s')", szSteamID) - Первый параметр указывает таблицу, которую мы указывали после FROM, они всегда одинаковые. Второй параметр это ячейка, по которой идет выборка, которой мы передаем параметр нашего SteamID
- Код: Выделить всё
SQL_ThreadQuery(SQLX_Tuple, "SQLXQuery", szQuery, szID, sizeof szID)
SQLX_Tuple - Наш созданных ранее обработчик подготовленных данных
SQLXQuery - Функция, которая выполнится при совершении запроса
szID - Наши дополнительные данные, в нашем случаи там id игрока
sizeof szID - Длина данных
- Код: Выделить всё
formatex(szQuery, charsmax( szQuery ), "INSERT INTO `test`(`steamid`, `time`) VALUES ('%s','%d');",
szSteamID, get_user_time(iPlayer))
INSERT INTO - Оператор, позволяющий добавить данные в базу
`test` - Сюда записывается таблица куда будем записывать данные
(`steamid`, `time`) - В какие ячейки будут записаны данные
VALUES ('%s','%d');",szSteamID, get_user_time(iPlayer) - Что будет записано. В нашем случаи SteamID игрока и его время, проведенное на сервере на момент ввода команды
Теперь требуется создать функцию непосредственной обработки нашего запроса SQLXQuery
- Код: Выделить всё
public SQLXQuery(iState, Handle:hQuery, szError[], iError, szID[], iID)
{
new iPlayer = szID[0] //Получаем id игрока
switch( iState ) //Проверяем как прошел запрос
{
case TQUERY_CONNECT_FAILED: //Код ошибки - 2( ошибка соединения )
{
client_print(iPlayer, print_chat, "no connect database: %s", szError) //Выводим сообщение
return PLUGIN_HANDLED
}
case TQUERY_QUERY_FAILED: //Код ошибки -1(ошибка запроса)
{
client_print(iPlayer, print_chat, "query error: %s", szError) //Выводим сообщение
return PLUGIN_HANDLED
}
}
if(SQL_NumResults( hQuery ) < 1) //Если данных в базе нет
{
new szSteamID[32] //Сюда запишем SteamID
get_user_authid(iPlayer, szSteamID, charsmax( szSteamID )) //Получаем SteamID игрока
new szQuery[512] //Сюда запишем запрос к базе
formatex(szQuery, charsmax( szQuery ), "INSERT INTO `test`(`steamid`, `time`) VALUES ('%s','%d');", szSteamID, get_user_time(iPlayer)) //Составляем запрос
SQL_ThreadQuery(SQLX_Tuple, "SQLXQueryClose", szQuery) //Отправляем запрос и закроем соединение
}else{ //А если данные есть
client_print(iPlayer, print_chat, "you already database") //Выводим сообщение
return PLUGIN_HANDLED
}
return PLUGIN_HANDLED
}
Опять же разбираемся
Функция SQLXQuery возвращает 7 параметров
iState - Статус запроса( есть ли ошибки )
Handle:hQuery - Ответ
szError[] - Текст ошибки
iError - Код ошибки
szID[] - Дополнительные параметры( id игрока )
iID - Длина
А так же есть дополнительный параметр( который в принципе не нужен )
Float:f:QTime - вернет время, которое было затрачено на обработку запроса
Как видите появился ещё 1 функция обработки запроса SQLXQueryClose
В ней не будем никаких проверок - мы просто закроем соединение, чтобы оно не висело открытым
- Код: Выделить всё
public SQLXQueryClose(iState, Handle:hQuery, szError[], iError, szID[], iID)
{
SQL_FreeHandle( hQuery ) //Закрываем
return PLUGIN_HANDLED //Уходим нафиг =)
}
Хух, хоть мы и сделали только отправку данных, но мы сделали сразу всю работу и для других команд. Теперь осталось дело за малым
Создаем функцию SQLXSelect
Здесь всё очень просто - мы берем тот же код, что и в SQLX_Create с одним отличием - меняем исполняемую функцию SQLXQuery на SQLXQuerySelect
- Код: Выделить всё
public SQLXSelect(id)
{
new szSteamID[32] //Сюда запишем SteamID игрока
new szQuery[512] //Сюда запишем запрос к базе
new szID[1] //Сюда запишем id игрока
szID[0] = id //Записываем id игрока
get_user_authid(id, szSteamID, charsmax( szSteamID )) //Получаем SteamID игрока
formatex(szQuery, charsmax( szQuery ), "SELECT * FROM `test` WHERE (`test`.`steamid` = '%s')", szSteamID) //Составляем запрос
SQL_ThreadQuery(SQLX_Tuple, "SQLXQuerySelect", szQuery, szID, sizeof szID) //Отправляем запрос на обработку
}
Разумеется мы могли создавать и получать данные одной функцией SQLXQuery, но т.к статья демонстрирующая - сделаем так
Теперь создаем функцию SQLXQuerySelect и так же дублируем код из SQLXQuery.
Нам всего лишь нужно будем поменять местами кое-что
- Код: Выделить всё
public SQLXQuerySelect(iState, Handle:hQuery, szError[], iError, szID[], iID)
{
new iPlayer = szID[0] //Получаем id игрока
switch( iState ) //Проверяем как прошел запрос
{
case TQUERY_CONNECT_FAILED: //Код ошибки - 2( ошибка соединения )
{
client_print(iPlayer, print_chat, "no connect database: %s", szError) //Выводим сообщение
return PLUGIN_HANDLED
}
case TQUERY_QUERY_FAILED: //Код ошибки -1(ошибка запроса)
{
client_print(iPlayer, print_chat, "query error: %s", szError) //Выводим сообщение
return PLUGIN_HANDLED
}
}
if(SQL_NumResults( hQuery ) < 1) //Если данных в базе нет
{
client_print(iPlayer, print_chat, "no player database") //Выводим сообщение
return PLUGIN_HANDLED
}else{ //А если данные есть
client_print(iPlayer, print_chat, "Your pastime server: %d sec", SQL_ReadResult(hQuery, 2)) //Выводим сообщение
return PLUGIN_HANDLED
}
return PLUGIN_HANDLED
}
Как видите мы поменяли внутренности в проверке на наличие в базе данных. Ключевой функцией здесь служит
- Код: Выделить всё
SQL_ReadResult(hQuery, 2)
Первый параметр обозначает ответ от нашего запроса, а второй это ячейка, которую мы хотим вывести.
ЗАПОМНИТЕ!
Отсчет ведется от 0, то есть получается, что данных из ячейки time будут третьими, steamid - первыми, ну, а что же будет 0 спросите вы? Ответ будет дан в конце
Так же хочу отметить то, что таким способом можно получить только числовые данные. Чтобы получить текстовые данные, требуется делать так
К коду никакого отношение не имеет!!! Дано как пример на будующее
- Код: Выделить всё
new szData[32] //Сюда запишем текстовой ответ от базы
SQL_ReadResult(hQuery, 2, szData, charsmax( szData ))
Ну всё, осталось создать функцию SQLXUpdate
- Код: Выделить всё
public SQLXUpdate(id)
{
new szSteamID[32] //Сюда запишем SteamID игрока
new szQuery[512] //Сюда запишем запрос к базе
get_user_authid(id, szSteamID, charsmax( szSteamID )) //Получаем SteamID игрока
formatex(szQuery, charsmax( szQuery ), "UPDATE `test` SET `time` = '%i' WHERE `test`.`steamid` = '%s';", get_user_time(id), szSteamID) //Составляем запрос
SQL_ThreadQuery(SQLX_Tuple, "SQLXQueryClose", szQuery) //Отправляем запрос и закроем соединение
}
И раз уж рассказал про select и insert, то расскажу и про update
- Код: Выделить всё
formatex(szQuery, charsmax( szQuery ), "UPDATE `test` SET `time` = '%i' WHERE `test`.`steamid` = '%s';", get_user_time(id), szSteamID)
UPDATE - Оператор, позволяющий обновить данные из базы
`test` - Сюда записывается таблица в которой будет обновление
SET - команда, выставляющая опции к запросу
`time` = '%i' - это значит, что мы обновим ячейку time
Ну, а дальше я уже говорил
Функцию так же не обрабатываем, а просто закрываем соединение
Ну чтож - мы написали плагин, но и это ещё не всё. Нам требуется ещё создать базу данных и таблицу с ячейками.
У каждого может быть по разному - обычно хостеры дают создать базу данных прямо из панели, то тогда пропускаем 1 и 2 шаг, если база данных уже создана
Покажу наглядно
1. Заходим в phpmyadmin, видим нечто такое
2. Создаем базу, имя которой указано в SQLX_DBNAME и нажимаем создать
3. Выбираем нашу базу, тыкаем на кнопку SQL
4. Вводим туда код запроса
- Код: Выделить всё
CREATE TABLE `test` //Создаем таблицу test( Ответ откуда берется test )
(
`id` INT NOT NULL AUTO_INCREMENT, //Идентификатор запроса( Ответ что такое 0 )
`steamid` VARCHAR( 32 ) NOT NULL, //Ячейка SteamID
`time` VARCHAR( 32 ) NOT NULL, //Ячейка времени
PRIMARY KEY(`id`) //Присваиваем идентификатором запроса id
);
Разумеется комментарии из запроса нужно УБРАТЬ
Вот и всё. Идем на сервер и проверяем
Если кому лень всё читать или всё складывать в пазл
- Код: Выделить всё
#include <amxmodx>
#include <amxmisc>
#include <sqlx>
#define PLUGIN_NAME "[TUT]Mysql"
#define PLUGIN_VERSION "0.1"
#define PLUGIN_AUTHOR "BaJIeHoK(amx-x.ru)"
#define SQLX_HOSTNAME "127.0.0.1"
#define SQLX_USERNAME "root"
#define SQLX_PASSWORD ""
#define SQLX_DBNAME "tut_mysql"
new Handle:SQLX_Tuple
new Handle:SQLX_Connection
public plugin_init()
{
register_plugin(PLUGIN_NAME, PLUGIN_VERSION, PLUGIN_AUTHOR)
register_clcmd("say /sqlx_create", "SQLXCreate")
register_clcmd("say /sqlx_select", "SQLXSelect")
register_clcmd("say /sqlx_update", "SQLXUpdate")
}
public plugin_precache()
{
new szError[512]
new iError
SQLX_Tuple = SQL_MakeDbTuple(SQLX_HOSTNAME, SQLX_USERNAME, SQLX_PASSWORD, SQLX_DBNAME)
SQLX_Connection = SQL_Connect(SQLX_Tuple, iError, szError, charsmax( szError ))
if(SQLX_Connection == Empty_Handle)
set_fail_state( szError )
SQL_FreeHandle( SQLX_Connection )
}
public SQLXCreate(id)
{
new szSteamID[32]
new szQuery[512]
new szID[1]
szID[0] = id
get_user_authid(id, szSteamID, charsmax( szSteamID ))
formatex(szQuery, charsmax( szQuery ), "SELECT * FROM `test` WHERE (`test`.`steamid` = '%s')", szSteamID)
SQL_ThreadQuery(SQLX_Tuple, "SQLXQuery", szQuery, szID, sizeof szID)
}
public SQLXSelect(id)
{
new szSteamID[32]
new szQuery[512]
new szID[1]
szID[0] = id
get_user_authid(id, szSteamID, charsmax( szSteamID ))
formatex(szQuery, charsmax( szQuery ), "SELECT * FROM `test` WHERE (`test`.`steamid` = '%s')", szSteamID)
SQL_ThreadQuery(SQLX_Tuple, "SQLXQuerySelect", szQuery, szID, sizeof szID)
}
public SQLXUpdate(id)
{
new szSteamID[32]
new szQuery[512]
get_user_authid(id, szSteamID, charsmax( szSteamID ))
formatex(szQuery, charsmax( szQuery ), "UPDATE `test` SET `time` = '%i' WHERE `test`.`steamid` = '%s';", get_user_time(id), szSteamID)
SQL_ThreadQuery(SQLX_Tuple, "SQLXQueryClose", szQuery)
}
public SQLXQuery(iState, Handle:hQuery, szError[], iError, szID[], iID)
{
new iPlayer = szID[0]
switch( iState )
{
case TQUERY_CONNECT_FAILED:
{
client_print(iPlayer, print_chat, "no connect database: %s", szError)
}
case TQUERY_QUERY_FAILED:
{
client_print(iPlayer, print_chat, "query error: %s", szError)
}
}
if(SQL_NumResults( hQuery ) < 1)
{
new szSteamID[32]
get_user_authid(iPlayer, szSteamID, charsmax( szSteamID ))
new szQuery[512]
formatex(szQuery, charsmax( szQuery ), "INSERT INTO `test`(`steamid`, `time`) VALUES ('%s','%d');", szSteamID, get_user_time(iPlayer))
SQL_ThreadQuery(SQLX_Tuple, "SQLXQueryClose", szQuery)
}else{
client_print(iPlayer, print_chat, "you already database")
}
}
public SQLXQuerySelect(iState, Handle:hQuery, szError[], iError, szID[], iID)
{
new iPlayer = szID[0]
switch( iState )
{
case TQUERY_CONNECT_FAILED:
{
client_print(iPlayer, print_chat, "no connect database: %s", szError)
return PLUGIN_HANDLED
}
case TQUERY_QUERY_FAILED:
{
client_print(iPlayer, print_chat, "query error: %s", szError)
return PLUGIN_HANDLED
}
}
if(SQL_NumResults( hQuery ) < 1)
{
client_print(iPlayer, print_chat, "no player database")
return PLUGIN_HANDLED
}else{
client_print(iPlayer, print_chat, "Your pastime server: %d sec", SQL_ReadResult(hQuery, 2))
return PLUGIN_HANDLED
}
return PLUGIN_HANDLED
}
public SQLXQueryClose(iState, Handle:hQuery, szError[], iError, szID[], iID)
{
SQL_FreeHandle( hQuery )
return PLUGIN_HANDLED
}
Ну вот и всё.
Если будут вопросы - задавайте
Удачи =)