-
Notifications
You must be signed in to change notification settings - Fork 0
Models Active Record
The mysql_model_* natives are a higher-level way to read/write a single row
without writing SQL by hand. You describe a table once by binding Pawn
variables to columns; then find / insert / update / save / delete move
data between those variables and the database.
It's optional sugar over prepared statements — under the hood it builds safe, parameterized SQL for you.
- ✅ Reading/writing one row keyed by an id (a player's account, a house, a car).
- ❌ Not for multi-row
SELECTs, joins, or aggregates — usemysql_executefor those.
Bind each column to a Pawn variable. Pick a key column (usually the id).
enum E_ACCOUNT {
acc_id,
acc_name[24],
acc_money,
Float:acc_health
}
new g_Acc[MAX_PLAYERS][E_ACCOUNT];
new Model:g_AccModel[MAX_PLAYERS];
CreateAccountModel(playerid)
{
// mysql_model_create(table[], MySQL:handle)
new Model:m = mysql_model_create("accounts", g_DB);
// bind: variable FIRST, then the column name (strings also take the max length)
mysql_model_bind_int (m, g_Acc[playerid][acc_id], "id");
mysql_model_bind_string(m, g_Acc[playerid][acc_name], 24, "name");
mysql_model_bind_int (m, g_Acc[playerid][acc_money], "money");
mysql_model_bind_float (m, g_Acc[playerid][acc_health], "health");
mysql_model_set_key(m, "id"); // the primary key column
g_AccModel[playerid] = m;
}Bind the actual variables you use in your gamemode — a
findwrites the row's values straight into them, andsave/updatereads from them.
Set the key variable, then find:
g_Acc[playerid][acc_id] = 5; // who to load
mysql_model_find(g_AccModel[playerid], "OnAccFound", "d", playerid);
forward OnAccFound(playerid);
public OnAccFound(playerid)
{
// g_Acc[playerid][acc_money] etc. are now filled from the DB row
GivePlayerMoney(playerid, g_Acc[playerid][acc_money]);
return 1;
}Fill the bound variables, then insert. The new auto-increment id is written back
into your key variable:
g_Acc[playerid][acc_id] = 0; // 0/unset = new row
g_Acc[playerid][acc_name] = "Carol";
g_Acc[playerid][acc_money] = 0;
mysql_model_insert(g_AccModel[playerid], "OnAccInserted", "d", playerid);
forward OnAccInserted(playerid);
public OnAccInserted(playerid)
{
printf("new account id = %d", g_Acc[playerid][acc_id]); // filled in for you
return 1;
}-
mysql_model_update— UPDATE the row matching the key. -
mysql_model_save— INSERT if the key is unset, else UPDATE (upsert convenience).
g_Acc[playerid][acc_money] = GetPlayerMoney(playerid);
mysql_model_update(g_AccModel[playerid]); // fire-and-forget, or pass a callbackmysql_model_delete(g_AccModel[playerid]); // deletes the row with the bound keyFree the model when you're done with it (e.g. on disconnect):
mysql_model_destroy(g_AccModel[playerid]);Models are also cleaned up on disconnect/gamemode restart.
Every value is sent as a bound parameter, exactly like a prepared statement — so models are injection-safe too. They're just a friendlier API when you're moving one row in and out of Pawn variables.
Model:mysql_model_create(const table[], MySQL:handle = MYSQL_DEFAULT_HANDLE);
mysql_model_bind_int(Model:m, &variable, const column[]);
mysql_model_bind_float(Model:m, &Float:variable, const column[]);
mysql_model_bind_string(Model:m, variable[], variable_maxlen, const column[]);
mysql_model_set_key(Model:m, const column[]);
mysql_model_find/insert/update/save/delete(Model:m, const cb[]="", const fmt[]="", ...);
mysql_model_unbind(Model:m, const column[]);
mysql_model_clear(Model:m);
mysql_model_destroy(Model:m);See the Native reference for the full list.
Next: Cookbook · Performance
Understand
Use
- Installing MySQL
- Docker Compose
- Getting started
- Configuration
- SQL crash course
- Designing your tables
- Storing game data
- Dates & times
- First queries
- Async patterns
- Reading results
- Prepared statements
- Passwords & hashing
- Transactions
- Models (active-record)
- Tutorial: login system
- mysql-admin demo
Deeper
Reference