R1KO
fuck society
- Сообщения
- 9,457
- Реакции
- 7,786
- Команда форума
- #1
[SourcePawn] Урок 13 - Работа с базами данных (MySQL, SQLite)
<- К содержанию
Подробнее о SQL запросах
Основные типы при работе с базами данных
- Database - производный тип от Handle, который являет собой соединение с базой.
- Методы Database
- Connect - Подключается к базе данных.
PHP:void Connect(SQLConnectCallback callback, const char[] name="default", any data=0);
- SQLConnectCallback callback - Обратный вызов.
- char[] name - Имя секции для подключения в файле databases.cfg.
- any data - Данные для передачи в обратный вызов. По умолчанию = 0.
- *Примечание: Метод Connect имеет тип static. Следовательно вызываться должен не от экземпляра типа, а от имени типа.
PHP:Database g_hDatabase; // Глобальная переменная для соединения с базой public void OnPluginStart() { Database.Connect(ConnectCallBack, "sp_lessons"); // sp_lessons Имя секции в databases.cfg } public void ConnectCallBack (Database hDB, const char[] szError, any data) // Пришел результат соединения { if (hDB == null || szError[0]) // Соединение не удачное { SetFailState("Database failure: %s", szError); // Отключаем плагин return; } g_hDatabase = hDB; // Присваиваем глобальной переменной соединения значение текущего соединения CreateTables(); // Функция пока не реализована, но по имени, думаю, ясно что она делает }
- SetCharset - Устанавливает набор символов при работе с базой.
PHP:bool SetCharset(const char[] charset)
- char[] charset - Набор символов (Например: "utf8" или "latin1")
-
PHP:
g_hDatabase.SetCharset("utf8");
- Query - Выполняет запрос к базе.
PHP:void Query(SQLQueryCallback callback, const char[] query, any data, DBPriority prio)
- SQLQueryCallback callback - Обратный вызов.
- char[] query - Запрос
- any data - Данные для передачи в обратный вызов. По умолчанию = 0.
- DBPriority prio - Приоритет выполнения. По умолчанию = DBPrio_Normal.
-
PHP:
public void OnClientPostAdminCheck(int iClient) { if(IsFakeClient(iClient) == false) { char szQuery[256], szAuth[32]; GetClientAuthId(iClient, AuthId_Engine, szAuth, sizeof(szAuth), true); FormatEx(szQuery, sizeof(szQuery), "SELECT `id`, `points` FROM `table_players` WHERE `auth` = '%s';", szAuth); // Формируем запрос g_hDatabase.Query(SQL_Callback_SelectClient, szQuery, GetClientUserId(iClient)); } } public void SQL_Callback_SelectClient(Database hDatabase, DBResultSet results, const char[] sError, any iUserID) // Обратный вызов { if(sError[0]) // Если произошла ошибка { LogError("SQL_Callback_SelectClient: %s", sError); // Выводим в лог return; // Прекращаем выполнение ф-и } int iClient = GetClientOfUserId(iUserID); if(iClient) { // Игрок всё еще на сервере } }
- Execute - Отправляет транзакцию.
PHP:void Execute(Transaction txn, SQLTxnSuccess onSuccess, SQLTxnFailure onError, any data, DBPriority priority)
- Transaction txn - Экземпляр типа Transaction.
- SQLTxnSuccess onSuccess - Обратный вызов в случае успеха.
- SQLTxnFailure onError - Обратный вызов в случае неудачи.
- any data - Данные для передачи в обратный вызов. По умолчанию = 0.
- DBPriority priority - Приоритет выполнения. По умолчанию = DBPrio_Normal.
-
PHP:
void MyFunc() { Transaction hTxn = new Transaction(); hTxn.AddQuery("запрос 1;", 8); // Как данные передадим число 8 hTxn.AddQuery("запрос 2;", 20); // Как данные передадим число 20 // ... hTxn.AddQuery("запрос 52;"); g_hDatabase.Execute(hTxn, SQL_TxnCallback_Success, SQL_TxnCallback_Failure, 150); // Как данные передадим число 150 } public void SQL_TxnCallback_Success(Database hDatabase, any Data, int iNumQueries, DBResultSet[] results, any[] QueryData) { // SQL_TxnCallback_Success // Data = 150 // iNumQueries = кол-во запросов // DBResultSet[] results = массив результатов запросов // any[] QueryData = массив данных запросов } public void SQL_TxnCallback_Failure(Database hDatabase, any Data, int iNumQueries, const char[] szError, int iFailIndex, any[] QueryData) { // Один или больше запросов прошли неудачно LogError("SQL_TxnCallback_Failure: %s", szError); }
- Escape - Экранирует символы ' в строке.'
PHP:bool Escape(const char[] string, char[] buffer, int maxlength, int &written)
- char[] string - Исходная строка
- char[] buffer - Буфер, куда будет помещен результат (Размер должен быть 2*strlen(string)+1)
- int maxlength - Размер буфера
- int &written - Буфер, в который будет записано количество записанных байт. По умолчанию = 0.
-
PHP:
char szName[MAX_NAME_LENGTH]; GetClientName(iClient, szName, sizeof(szName)); int iLen = 2*strlen(szName)+1; char[] szEscapedName = new char[iLen ]; g_hDatabase.Escape(szName, szEscapedName, iLen );
- IsSameConnection - Проверяет совпадают ли соединения.
PHP:bool IsSameConnection(Database other)
- Database other - Соединение с базой данных
-
PHP:
Database g_hDatabase2 // Другое соединение if(g_hDatabase.IsSameConnection(g_hDatabase2)) { PrintToServer("Подключения ведут к одной базе данных!"); } else { PrintToServer("Это разные соединения"); }
- Connect - Подключается к базе данных.
- Свойства Database
- Driver - Возвращает драйвер подключения к базе данных (тип DBDriver).
- Методы Database
- DBDriver- драйвер базы данных.
- Методы DBDriver
- Find - Находит драйвер по имени.
PHP:DBDriver Find(const char[] name);
- char[] name - Строка идентификации драйвера ("mysql" или "sqlite")
- GetIdentifier - Получает имя драйвера.
PHP:void GetIdentifier(char[] ident, int maxlength)
- char[] ident - Буфер, куда будет помещена строка идентификации драйвера ("mysql" или "sqlite")
- int maxlength - Размер буфера
- GetProduct - Получает продукт драйвера.
PHP:void GetProduct(char[] product, int maxlength)
- char[] product - Буфер, куда будет помещен продукт ("MySQL" или "SQLite")
- int maxlength - Размер буфера
- Find - Находит драйвер по имени.
- Методы DBDriver
- DBStatement- представляет собой предварительно скомпилированный запрос SQL, который может выполняться несколько раз с различными параметрами.
- Методы DBStatement
- BindInt - Назначает параметр в подготовленном запросе для целого значения.
PHP:void BindInt(int param, int number, bool signed)
- int param - Индекс параметра (начинается с 0)
- int number - Число для назначения
- bool signed - true - знаковое число, false - беззнаковое
- BindFloat - Назначает параметр в подготовленном запросе для числа с плавающей точкой.
PHP:void BindFloat(int param, float value)
- int param - Индекс параметра (начинается с 0)
- float value - Число для назначения
- BindString - Назначает параметр в подготовленном запросе для строки.
PHP:void BindString(int param, const char[] value, bool copy)
- int param - Индекс параметра (начинается с 0)
- char[] value - Строка для назначения
- bool copy - Если true - будет использована копия переменной (если значение переменной изменится то в запросе оно останется тем же).
- BindInt - Назначает параметр в подготовленном запросе для целого значения.
- Методы DBStatement
- Transaction- транзакция (набор запросов, которые связанны между собой и либо выполняются все, либо ни один из них).
- Методы Transaction
- Transaction - Создает объект типа Transaction.
PHP:Transaction hTxn = new Transaction();
- AddQuery - Добавляет запрос в транзакцию. Возвращает индекс запроса в списке транзакции.
PHP:int AddQuery(const char[] query, any data)
- char[] query - Запрос.
- any data - Данные для передачи в обратный вызов. По умолчанию = 0.
-
PHP:
Transaction hTxn = new Transaction(); hTxn.AddQuery("UPDATE `table_players` SET `points` = 0;"); hTxn.AddQuery("UPDATE `table_players` SET `points` = 100 WHERE `id` = 5;", 5); // Как данные передадим цифру 5
- Transaction - Создает объект типа Transaction.
- Методы Transaction
- DBResultSet- набор результатов, возвращаемых из запроса.
- Методы DBResultSet
- FetchRow - Возвращает строку из текущего набора результатов. Это нужно выполнять перед извлечением результатов. Возвращает true в случае успеха.
PHP:if(hResult.FetchRow()) // Если условие выполнено - можно получать данные { // Здесь будем получать данные } // Если запрос должен вернуть не 1, а несколько строк то можно сделать так: while(hResult.FetchRow()) // Тело цикла будет выполнятся пока можно получать данные { // Здесь будем получать данные }
- FetchInt - Возвращает целочисленное значение из текущей строки. Если NULL - вернет 0.
PHP:int FetchInt(int field, DBResult &result)
- int field - Индекс поля (начинается с 0).
- DBResult &result - Буфер, для сохранения статуса, возвращаемого значения. По умолчанию = 0.
-
PHP:
// Помните запрос? // "SELECT `id`, `points` FROM `table_players` WHERE `auth` = '%s';" // Нумерация полей начинается с 0, следовательно: // id - 0 // points - 1 // Получаем значение поля id int ID = hResult.FetchInt(0); // Получаем значение поля points int iPoints = hResult.FetchInt(1);
- FetchFloat - Возвращает значение с плавающей точкой из текущей строки. Если NULL - вернет 0.0.
PHP:float FetchFloat(int field, DBResult &result)
- int field - Индекс поля (начинается с 0).
- DBResult &result - Буфер, для сохранения статуса, возвращаемого значения. По умолчанию = 0.
-
PHP:
// "SELECT (CAST(kills as float)/CAST(daths as float)) as kdr FROM `table_players` WHERE `id` = 6;" // Получим соотношение кол-ва убийств к кол-ву смертей float fKDR = hResult.FetchFloat(0);
- FetchString - Возвращает строковое значение из текущей строки. Если NULL - вернет "".
PHP:int FetchString(int field, char[] buffer, int maxlength, DBResult &result)
- int field - Индекс поля (начинается с 0).
- char[] buffer - Буфер, для записи строки.
- int maxlength - Размер буфера.
- DBResult &result - Буфер, для сохранения статуса, возвращаемого значения. По умолчанию = 0.
-
PHP:
// "SELECT `clan_tag` FROM `table_players` WHERE `id` = 8;" // Получим соотношение кол-ва убийств к кол-ву смертей char szClanTag[32]; hResult.FetchString(0, szClanTag, sizeof(szClanTag));
- FetchSize - Возвращает размер строки в текущей строке набора. Это нужно вызывать только для строк, чтобы определить какого размера необходимо создать буфер. Обратите внимание, что возвращаемое значение не включает в себя нулевой символ.
PHP:int FetchSize(int field)
- int field - Индекс поля (начинается с 0).
-
PHP:
// С использованием этого метода, предыдущий код можно написать так: int iSize = hResult.FetchSize(0)+1; char[] szClanTag = new char[iSize]; hResult.FetchString(0, szClanTag, iSize );
- IsFieldNull - Возвращает является ли поле NULL.
PHP:bool IsFieldNull(int field)
- int field - Индекс поля (начинается с 0).
-
PHP:
if(hResult.IsFieldNull(0)) { // поле `clan_tag` является NULL }
- FieldNumToName - Получает имя поля по его индексу.
PHP:void FieldNumToName(int field, char[] name, int maxlength)
- int field - Индекс поля (начинается с 0).
- char[] name - Буфер, для записи имени поля.
- int maxlength - Размер буфера.
-
PHP:
char szFieldName[32]; hResult.FieldNumToName(0, szFieldName, sizeof(szFieldName)); // szFieldName = "clan_tag"
- FieldNameToNum - Получает индекс поля по его имени.
PHP:bool FieldNameToNum(const char[] name, int &field)
- char[] name - Имя поля.
- int &field - Буфер, для записи индекса пол).
-
PHP:
int iField; if(FieldNameToNum("clan_tag", iField)) { // iField = 0 }
- FetchMoreResults - Переход к следующему набору результатов.
В некоторых реализациях SQL, несколько наборов результатов могут существовать на одном запросе. Это возможно в MySQL с помощью простых запросов при выполнении запроса CALL. Если дело обстоит именно так, то все наборы результатов должны быть обработаны до того как другой запрос был сделан.
PHP:bool FetchMoreResults()
- FetchRow - Возвращает строку из текущего набора результатов. Это нужно выполнять перед извлечением результатов. Возвращает true в случае успеха.
- Свойства DBResultSet
- HasResults - Возвращает, существует ли или нет набор результатов. Это возвращает true, даже если были возвращены 0 результаты, но false на запросах как UPDATE, INSERT или DELETE.
- RowCount - Возвращает количество строк в последнем наборе результатов.
- FieldCount - Возвращает количество полей в последнем наборе результатов.
- MoreRows - Возвращает, есть ли еще строки.
- AffectedRows - Возвращает, измененных/удаленных (затронутых) запросом строк.
- InsertId - Возвращает, последний id из INSERT запроса.
- Методы DBResultSet
- Transaction- представляет собой набор запросов SQL, который являются зависимыми друг от друга. Либо все должны быть выполнены успешно, либо не будет выполнен ни один.
- Методы Transaction
- Transaction - Создает новую транзакцию.
PHP:Transaction hTxn = new Transaction();
- AddQuery - Добавляет SQL запрос в транзакцию.
PHP:int AddQuery(const char[] query, any data)
- char query - SQL запрос
- any data - Данные для передачи
-
PHP:
hTxn.AddQuery("запрос 1;", 8); // Как данные передадим число 8
- Transaction - Создает новую транзакцию.
- Методы Transaction
В одном и том же соединении можно запускать как поточные, так и не-поточные запросы.
Однако без надлежащих мер предосторожности вы можете повредить сетевой поток (даже если он локальный), поврежденную память или иным образом вызвать сбой в драйвере SQL.
Чтобы решить эту проблему, SourceMod имеет блокировку базы данных.
Блокировка выполняется через SQL_LockDatabase и SQL_UnlockDatabase.
Всякий раз, когда выполняется какая-либо из следующих операций, не связанных с потоком в базе данных, абсолютно необходимо заключить всю операцию с блокировкой:
- Сопряжения SQL_Query (и SQL_FetchMoreResults)
- SQL_FastQuery
- SQL_PrepareQuery
- Сопряжения SQL_Bind и SQL_Execute
Пример:
PHP:
bool GetByAge_Query(Database hDdb, int iAge)
{
char szQuery[128];
FormatEx(szQuery, sizeof(szQuery), "SELECT `name` FROM `users` WHERE `age` = %d;", iAge)
// Блокируем все запросы в базу данных
SQL_LockDatabase(hDdb);
// Выполняем не-поточный запрос
DBResultSet hQuery = SQL_Query(hDdb, szQuery);
// Разблокируем базу.
SQL_UnlockDatabase(hDdb);
if (hQuery == INVALID_HANDLE)
{
return false;
}
// Выводим результаты запроса
delete hQuery;
return true;
}
SourceMod предварительно выбирает набор результатов, и, следовательно, сетевая очередь чиста.
Предупреждение:
Никогда не вызывайте SQL_LockDatabase прямо перед поточной операцией.
Вы заблокируете сервер и должны его прекратить / убить.
Всегда разблокируйте базу после блокировки.
Если ваш запрос возвращает несколько наборов результатов, например, вызов процедуры в MySQL, который возвращает результаты, вы должны заблокировать как запрос, так и всю операцию выборки.
SourceMod может только получить один результирующий набор за раз, и все результирующие наборы должны быть очищены до запуска нового запроса.
В качестве примера простой плагин статистики (приложил файлом)
Подкиньте идей о чем можно примеров написать и о каких ф-ях рассказать
Вложения
Последнее редактирование: