Knight docs
EN ID
GitHub

Database & Storage

SQLite and MySQL from a gamemode, sync and async.

SQLite

knight
system::start() {
    let db = sqlite_open("data/accounts.db");
    sqlite_exec(db, "CREATE TABLE IF NOT EXISTS accounts (name TEXT PRIMARY KEY, score INTEGER)");
};

player::command("/save", int score) {
    let db = sqlite_open("data/accounts.db");
    sqlite_exec(db, "INSERT OR REPLACE INTO accounts VALUES (?, ?)", PlayerName(playerid), score);
};

player::command("/load") {
    let db = sqlite_open("data/accounts.db");
    let idx = sqlite_query(db, "SELECT score FROM accounts WHERE name = ?", PlayerName(playerid));
    if (idx != null) {
        SendClientMessage(playerid, "score = {cache_get_value_name_int(idx, 0, "score")}");
    }
};

Async queries

For slow queries, use the async variant and a named callback. It runs off the tick loop.

knight
function onScore(result, err) {
    if (err == "") {
        Log("rows = " + str(cache_get_row_count(result)));
    }
}

player::command("/load") {
    let db = sqlite_open("data/accounts.db");
    sqlite_query_async(db, "onScore", "SELECT score FROM accounts");
};

Passwords

knight
let hash = hash_password(password);
if (verify_password(input, hash)) {
    SendClientMessage(playerid, "Logged in.");
}
Warning
Always use ? placeholders for user input. Never build SQL by concatenating strings.

Which database?

BackendBest forDetails
SQLiteSingle server, small/medium dataSQLite guide
MySQLExternal database, multiple servers, large dataMySQL guide