Skip to content

Instantly share code, notes, and snippets.

@androksi
Last active February 21, 2023 16:32
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save androksi/656da62c0c8240bf02746cb742d7b112 to your computer and use it in GitHub Desktop.
Save androksi/656da62c0c8240bf02746cb742d7b112 to your computer and use it in GitHub Desktop.

Tutorial de MySQL

Sim, é o famoso banco de dados. Neste tutorial, eu vou abordar o uso do MySQL focado no MTA. Mas é claro que você pode estudar e expandir para outras áreas sem problema algum.

O que é um banco de dados?

É onde seus dados roubados ficam guardados — brincadeira. Resumidamente, é onde os dados ficam guardados. Tá, mas... que dados são esses? Eles podem ser qualquer coisa, desde textos, imagens, áudios, IDs, nome de usuário, senhas, tabelas JSON, números, data de criação e por aí vai.

Com esses dados que estão guardados nós podemos formar uma informação.

Como faço para começar a guardar dados?

É muito simples! Tudo o que você precisa fazer é instalar um servidor MySQL na sua torradeira, mais conhecido como seu computador. Também, para simplificar a visualização dos dados, nós precisaremos de um programa para isso.

Instalando o XAMPP

Você deve instalar esse programa no seu computador, ele será responsável por gerir toda a conexão MySQL.

Link para baixar: https://www.apachefriends.org/pt_br/index.html

Instalando o Beekeeper Studio

Particularmente eu amo esse programa, então irei usá-lo nesse tutorial. Existem outras soluções como phpMyAdmin e MySQL Workbench. Mas, sinceramente, o Beekeeper Studio funciona muito bem — sem contar que ele é feito em JavaScript, usando Electron, isto é, super leve.

Link para baixar: https://github.com/beekeeper-studio/beekeeper-studio/releases

Nota: o download é feito através do GitHub pois essa é a versão gratuita e de código aberta feita pela comunidade. Existe a versão paga, mas convenhamos: ninguém merece. Lembre-se de baixar a versão e instalador correto. Ele tem este nome: Beekeeper-Studio-Setup-3.8.9.exe

Configurando os programas baixados

Eles não precisam de uma configuração prévia. É simplesmente instalar, abrir e começar a usar. De qualquer forma, se isso ainda não é claro, não tem problema, vamos passo a passo.

Iniciando o servidor MySQL

Uma vez que você instalou o XAMPP, abra-o. Pode ser que ele não crie um atalho na área de trabalho, mas você pode apertar o botão do Windows e pesquisar por XAMPP. Recomendo que abra como administrador.

Com ele aberto, veremos esta tela:

XAMPP Aberto

Não se preocupe se aquele "X" vermelho estiver em todos no seu. Quando eu instalo, prefiro deixar só o necessário. De qualquer forma, não é nada que irá atrapalhar o andamento do tutorial.

Agora nós já podemos iniciar o servidor MySQL, clicando no botão "Start". Ele ficará assim:

Botão "Start" XAMPP

Pronto! Nosso servidor está instalado e rodando.

Iniciando o Beekeeper Studio

Por favor, abra o programa. Com ele aberto, nós veremos uma tela deste jeito:

Tela do Beekeeper Studio

Não tem muito segredo. Vamos nos conectar ao servidor MySQL, dessa forma iremos ver tudo o que acontece em nosso banco de dados.

Clique em Select a connection type

Estabelecer nova conexão MySQL

Selecione a opção MySQL. Nós daremos de cara com alguns campos para preencher. Não se preocupe. É bem fácil!

Campos para preencher na nova conexão do MySQL

No campo Host, iremos colocar localhost. No campo User, iremos colocar root.

Pronto! Com esses dois campos preenchidos, clique no botão "Connect". Se tudo estiver correto, esta tela irá aparecer:

Tela de conexão bem sucedida

Daqui, já podemos gerenciar os bancos de dados e tabelas. Eu vou facilitar algumas coisas, pois pode ser a primeira vez de alguém entrando em contato com essa interface.

Aqui fica o local onde você irá selecionar o banco de dados para visualizar as tabelas, registros e outros.

Local dos bancos de dados

Uma vez que você clica ali, será listado todos os banco de dados criados. Existem alguns que vêm como padrão, criados pelo próprio XAMPP.

Temos também a área onde iremos digitar alguns comandos.

Área de comandos

Por enquanto, é apenas isso que você deve saber. Vamos começar!

Criando seu primeiro banco de dados

Existem algumas formas de criar um banco de dados, irei mostrar a forma que eu recomendo. É super simples e fácil.

Naquele campo onde usaremos para digitar comandos, iremos digitar o seguinte:

CREATE DATABASE `db_test` CHARACTER SET `utf8` COLLATE `utf8_general_ci`;

Oh, meu deus! O que é isso? Nossa! Mas o que é tudo isso? Me ajuda, me ajuda, por favor!

Relaxe. Não é nada demais. O nosso primeiro comando, então, é o CREATE. Geralmente ele é usado para criar banco de dados e tabelas.

CHARACTER SET serve para definirmos qual será a codificação de todos os dados dentro das tabelas. Recomendo sempre usar utf8, pois engloba todos os caracteres, sem possibilidades de causar um bug.

COLLATE também serve para definir a codificação, mas existem várias, você pode pesquisar a fim de estudar. Usaremos utf8_general_ci.

Abrindo a lista de bancos de dados, ele deve estar ali.

Lista de bancos de dados

Selecione-o. É importante SEMPRE ter o seu banco de dados selecionado. Caso isso não aconteça, os comandos digitados não irão funcionar.

Criando sua primeira tabela

Agora que criamos o banco de dados e estamos com ele selecionado, vamos criar uma tabela para armazenar alguns dados.

Apague o comando anterior e digite este:

CREATE TABLE IF NOT EXISTS `products` (
  `id` INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
  `name` VARCHAR(128) NOT NULL,
  `price` INT NOT NULL
);

Calma! Não entre em pânico. Irei explicar algumas coisas sobre o comando acima.

Antes disso, você percebeu que eu usei crase (`) encapsulando o nome? Então, isso é de suma importância para os nomes que damos, informando ao servidor MySQL que aquilo NÃO É UM COMANDO, mas sim o nome de alguma coisa. Não usar aquilo pode ocasionar alguns erros.

Notasse que há "IF NOT EXISTS", ou seja, a tabela só será criado caso ela não exista. É recomendável que use dessa maneira para evitar que os dados sejam apagados.

Dando continuidade. Quando temos uma tabela, nela existem duas coisas: colunas e entradas.

Colunas - são identificadores. Simples assim. Se nós quisermos o nome de um produto, iremos buscar pela coluna name, nesse caso.

Entradas - onde os dados ficarão salvos. Cada entrada no banco de dados é diferente, podendo conter outros nomes. Por exemplo, inseri um dado na tabela e, na coluna name coloquei PlayStation 4; quando eu for inserir novamente, posso colocar Samsung Galaxy S23. Teoricamente, nossa tabela agora tem dois produtos.

Em toda tabela que você criar, SEMPRE adicione a chave id daquela forma. Citarei aqui novamente:

`id` INT NOT NULL PRIMARY KEY AUTO_INCREMENT,

Toda tabela deve ter esse campo, ele que irá ser referência para uma outra tabela ou em criações de chaves estrangeiras. Não iremos abordar esse tema neste tutorial. De qualquer forma, crie!

Tipos

Existem alguns tipos de dados, sendo eles:

VARCHAR
INT
JSON
TEXT
BIGINT
TINYINT
BOOLEAN
TIMESTAMP
BLOB

Usaremos apenas alguns, mas vale o estudo em relação aos outros tipos.

NOT NULL

Esse comando irá dizer para a tabela que não irá aceitar uma inserção sem um valor.

AUTO_INCREMENT

Esse comando irá dizer para a tabela que o ID será adicionado de forma automática assim que uma nova entrada for criada.

Continuando...

Enfim, caso você tenha criado corretamente, a tabela irá aparecer ali no canto. Ficará desta forma:

Tabela de produtos criada

Como inserir dados?

Para isso, usaremos um outro comando, que é o INSERT. Ele é bem simples também. Apague o comando anterior. Copie, cole e execute este:

INSERT INTO `products` (`name`, `price`) VALUES ('Computador Super Gamer', 15999);

Mesmo você não visualizando, se tudo estiver correto, nós temos agora uma entrada no banco de dados — e não é calvice. Brincadeira.

Primeiramente, vamos focar em entender como esse comando funciona. Começando pelo:

INSERT INTO - pode ser traduzido para "INSIRA DENTRO DE". Após digitar isso, nós precisamos indicar em qual tabela os dados serão inseridos. Em nosso exemplo, queremos que insira os dados na tabela "products".

Depois disso, nós temos que abrir parênteses () e definir as colunas. Aqui vamos inserir um nome e um preço.

VALUES - é onde ficará os valores, de acordo com o nome das colunas. Por exemplo, nós indicamos que iremos inserir os seguintes dados: nome e preço (name, price) — sendo assim, o primeiro dado a vir dentro de VALUES deve ser o nome do produto. Respectivamente, o preço.

O jeito que iremos inserir nos exemplos futuros de MTA será diferente. Por enquanto, vamos focar como as coisas estão no momento.

Lembre-se de usar crase (`) para indicar que estamos falando sobre o nome da coluna. Perceba que não tem crase (`) nos valores que estamos inserindo, pois eles são, como o nome diz, valores que ficarão armazenados.

Como ler os dados inseridos?

Hum... começando a ficar um pouquinho complexo. Mas você vai entender fácil.

Usaremos agora o comando SELECT. Digamos que nós queremos obter todos os dados da tabela, de todas as colunas. O comando para isso é:

SELECT * FROM `products`;

Observação: Já que chegamos aqui, vou aproveitar pra falar uma coisa: sempre que for executar um novo comando, apague o anterior. É sim possível ter múltiplos comandos naquela área, mas pelo tutorial, faça dessa forma.

Com o comando executado, se tudo estiver correto, você verá os dados que inserimos anteriormente:

Dados inseridos

Vamos adicionar mais um produto. Você fará isso sozinho. Depois de adicionado, execute novamente o comando. O seu estará assim:

Dados inseridos 2

Não liga para o ID 3 ali, eu errei uma coisa aqui e tive que deletar a outra entrada. Não se preocupe. O seu deve estar 1 e 2.

Certo. Agora você deve estar se perguntando: tá, mas como eu faria para obter os dados de uma entrada específica?

O comando segue sendo o mesmo, mas agora nós iremos especificar qual nós queremos. Use o seguinte comando:

SELECT * FROM `products` WHERE `id` = 1;

Se tudo estiver correto, deve retornar apenas aquela entrada que tem o ID de número 1:

Somente o ID 1

WHERE - é como se fosse um if que usamos na programação. Nós também podemos passar mais coisas além disso. Vejamos:

SELECT * FROM `products` WHERE `price` >= 5000;

O comando acima irá buscar somente pelos produtos que têm o preço maior ou igual a 5 mil reais.

Suponhamos que temos uma coluna com o nome de brand (que é marca de alguma coisa, em Inglês)

Nós podemos buscar somente produtos daquela marca e que tenha o preço maior ou igual que, por exemplo, 2 mil reais. Ficando assim:

SELECT * FROM `products` WHERE `price` >= 2000 AND `brand` = 'Samsung';

Nota: O comando acima não é passível de ser executado, mas como exercício, você pode criar a tabela novamente com essa coluna.

Como atualizar dados?

Também é algo simples. Usaremos o comando UPDATE. Dê uma olhada no comando abaixo:

UPDATE `products` SET `price` = 12500 WHERE `id` = 1;

O que o comando está querendo dar a entender é o seguinte: atualize o banco de dados products, alterando as seguintes colunas se alguma coisa for especificada.

Uma observação extremamente importante: Jamais deixe de usar o comando WHERE juntamente com UPDATE. Caso contrário, todos os dados serão substituídos e, dessa forma, perdidos. Sempre que for atualizar alguma coisa, lembre-se que essa coisa será atualizada para somente uma entrada.

Tente pensar da seguinte forma: se o preço do Computador Super Gamer alterou, então eu preciso especificar que o preço DELE mudou. Os outros produtos continuarão com o mesmo preço, a menos que eles também tenham o preço reduzido ou aumentado. Mas, novamente, especificamente cada um deles, em um comando diferente.

Nota: Também podemos usar o comando AND, caso seja necessário. Há cenários em que precisaremos, mas não aconteceu aqui, pois temos uma tabela simples.

Como remover entradas?

Para remover entradas, nós usamos o comando DELETE. Ele é parecido com o comando UPDATE, sendo necessário SEMPRE o uso do WHERE para especificar qual entrada deve ser excluída.

Usaremos o seguinte comando para deletar o nosso Computador, que tem o ID 1:

DELETE FROM `products` WHERE `id` = 1;

Após executar o comando e fazendo uma busca, você irá perceber que não tem mais. Assim está o meu:

Sem o ID 1

Como remover tudo de uma só vez?

Para isso, nós usamos o comando TRUNCATE. Ele remove todas as entradas, ou seja, limpa completamente a tabela especificada. Segue o exemplo:

TRUNCATE `products`;

Faça uma busca e verá que não há mais nenhum dado.

Resumo

Trabalhar com banco de dados de forma simples é bem fácil, com o tempo, praticando, você consegue criar comandos mais complexos.

Lembre-se:

Lembre-se

Usando o que aprendemos dentro do MTA

Para usarmos um banco de dados dentro do MTA, temos duas opções:

  • MySQL (Conexão, salvo na nuvem)
  • SQLite (Arquivo, salvo em disco, localmente)

Independente do modo que você irá usar, é quase sempre a mesma coisa. Quase sempre pois cada banco de dados pode ter um motor (engine) diferente. Não é uma grande diferença, porém alguns comandos podem ser diferentes.

Neste tutorial, usaremos MySQL. Mas... tenho uma surpresa no final!

Como conectar ao banco de dados

Precisamos da função dbConnect e também especificar de qual modo usaremos, junto com as informações de conexão, como: host (IP/DNS), usuário, senha (caso haja) e o nome do banco de dados.

Agora, crie uma pasta dentro de resources, lá do seu servidor MTA. Eu vou colocar como dbtut.

Feito isso, crie um arquivo meta.xml com o seguinte conteúdo, apenas para carregar nosso resource:

<meta>
    <script src="database.lua" type="server" />

    <export function="getConnection" type="server" />
</meta>

Agora, iremos criar também o arquivo database.lua, com o seguinte conteúdo:

local connectionInfo = {
    db_name = "db_test", -- Mesmo nome do banco de dados que criamos.
    host = "localhost",
    username = "root",
    password = '' -- Aqui deixaremos vazio, já que o nosso banco de dados não possui um senha.
}

local databaseConnection -- Variável onde a conexão ficará armazenada

function getConnection() -- Função que iremos exportar para retornar a conexão, sendo assim poderemos usar fora daqui.
    return databaseConnection
end

addEventHandler("onResourceStart", resourceRoot,
    function()
        databaseConnection = dbConnect("mysql", "dbname=" .. connectionInfo.db_name .. ";host=" .. connectionInfo.host, connectionInfo.username, connectionInfo.password)

        -- Checando se a conexão foi estabelecida.
        if databaseConnection then
            print("Conexão com o banco de dados estabelecida!")
        else
            print("Infelizmente a conexão não pôde ser estabelecida.")
        end
    end
)

Inicie o resource em seu servidor. Se tudo estiver correto, poderemos continuar com o tutorial.

Agora que nós temos o resource rodando e com o banco de dados iniciado. Criaremos um outro resource e trabalharemos lá.

Crie uma pasta com outro nome, eu vou deixar como tut_markers, só para fins de estudo.

Use este meta.xml:

<meta>
    <script src="script.lua" type="server" />
</meta>

Crie um arquivo com o nome script.lua e vamos continuar.

Agora, dentro do arquivo script.lua, vamos adicionar um evento para quando o resource iniciar ele então criar a nossa tabela.

local markers = {}
local lastId

addEventHandler("onResourceStart", resourceRoot,
    function()
        local db = exports.dbtut:getConnection() -- Iremos obter a conexão.

        if not db then -- Caso não haja a conexão, iremos informar através de um `print` que o banco de dados está off-line.
            return print("Banco de dados off-line. Impossível continuar.")
        end

        -- Se tudo estiver correto, vamos criar a tabela. Nós usamos a função `dbExec` (https://wiki.multitheftauto.com/wiki/DbExec)
        dbExec(db, [[
            CREATE TABLE IF NOT EXISTS `markers` (
                `id` INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
                `position` JSON NOT NULL,
                `color` JSON NOT NULL,
                `type` VARCHAR(16) DEFAULT 'cylinder',
                `size` INT DEFAULT 1,
                `creator` VARCHAR(32) DEFAULT 'server',
                `created_at` BIGINT NOT NULL
            );
        ]])

        -- Há duas maneiras de usar a função `dbQuery`
        -- Irei usá-la diretamente, sem callbacks

        -- Aqui nós vamos buscar todos os markers que estão salvos
        -- No banco de dados e então criaremos todos eles

        local queryHandler = dbQuery(db, "SELECT * FROM `markers`")
        local data = dbPoll(queryHandler, -1)

        -- A função `dbQuery` apenas retorna um "handler"
        -- Que nós temos que organizar com a função `dbPoll`
        -- Essa função (dbPoll) irá retornar uma tabela parecida com esta:

        --[[
            local data = {
                { id = 1, position = { posX, posY, posZ }, color = { r, g, b, a }, type = type, size = size, creator = creator, created_at = created_at },
                { id = 2, position = { posX, posY, posZ }, color = { r, g, b, a }, type = type, size = size, creator = creator, created_at = created_at },
                { id = 3, position = { posX, posY, posZ }, color = { r, g, b, a }, type = type, size = size, creator = creator, created_at = created_at },
            }
        ]]--

        lastId = 0

        if #data == 0 then -- Se não tiver nada ainda, então iremos parar por aqui
            return false
        end

        -- Se tiver entradas, iremos criar
        for k = 1, #data do
            local row = data[k]

            -- Lembra que salvamos a posição e cor no banco de dados
            -- Como JSON? Então, agora temos que converter novamente
            -- Para a forma que o MTA reconhece
            -- Usaremos a função `fromJSON` para isso

            local position = fromJSON(row.position)
            local color = fromJSON(row.color)

            local markerType = row.type
            local markerSize = row.size

            local creatorName = row.creator
            local createdAt = row.created_at

            local marker = createMarker(position[1], position[2], position[3], markerType, markerSize, color[1], color[2], color[3], color[4])

            markers[marker] = {
                id = row.id,
                position = position,
                creator_name = creatorName,
                created_at = createdAt
            }
        end

        lastId = data[#data].id
    end
)

Inicie o resource em seu servidor. Se tudo estiver certo, você terá uma nova tabela adicionada ao seu banco de dados.

Perceba que eu usei o comando DEFAULT. Isso quer dizer que, caso eu não queira definir no INSERT INTO, ele usará aquele valor como padrão.

Vamos começar a interagir com essa tabela!

Criando comandos de interação com o banco de dados

Eu optei por separar cada comando, dessa forma ficará mais fácil o entendimento para aqueles que não são muito experientes com isso ainda.

Criando um marker

addCommandHandler("create-marker",
    function(player, command, markerType, markerSize)
        local db = exports.dbtut:getConnection() -- Novamente obtendo a conexão.

        if not db then -- Novamente checando.
            return print("O banco de dados está off-line.")
        end

        -- Devemos nos perguntar uma coisa.
        -- Quais dados são obrigatórios?
        -- Nesse caso, somente a posição e a cor.
        -- Porém a cor nós iremos definir uma padrão pelo código mesmo.

        local posX, posY, posZ = getElementPosition(player)
        posZ = posZ - 1 -- Só pra criar o marker no chão

        local color = { 255, 255, 255, 255 }

        -- Sim, nós definimos um valor padrão (DEFAULT)
        -- No banco de dados, mas vamos aplicar aqui também
        -- Só para fins de estudo
        markerType = markerType or "cylinder"
        markerSize = tonumber(markerSize) or 1

        local creatorName = getPlayerName(player)
        local createdAt = getRealTime().timestamp

        -- Usaremos essa função (dbExec) para inserir coisas no banco de dados.
        -- Existe a função "dbQuery" mas só usamos ela quando se trata de um SELECT.

        -- Perceba que usaremos a função "toJSON"
        -- Isto é, estaremos convertendo a tabela Lua para JSON
        -- Pois o banco de dados não aceita uma tabela Lua

        dbExec(db, "INSERT INTO `markers` (`position`, `color`, `type`, `size`, `creator`, `created_at`) VALUES (?, ?, ?, ?, ?, ?)", toJSON({ posX, posY, posZ }), toJSON(color), markerType, markerSize, creatorName, createdAt)

        local marker = createMarker(posX, posY, posZ, markerType, markerSize, unpack(color))

        lastId = lastId + 1

        markers[marker] = {
            id = lastId,
            position = { posX, posY, posZ },
            creator_name = creatorName,
            created_at = createdAt
        }

        print("O marker foi criado!")
    end
)

-- Como usar o comando:
-- /create-marker cylinder 2
-- ou
-- /create-marker corona 1
-- ou
-- /create-marker corona 5

-- Enfim, a sintaxe é: /create-marker <tipo> <tamanho>

Eita! O código é grande. Eu vou explicar a parte onde os dados estão sendo inseridos, afinal é o que importa. Todo o resto é conceito de programação, que não se encaixa neste tutorial. Mas estude bem e tente entender, pois pensei na melhor maneira, seja em questões de otimização ou facilidades.

Bom, você pode ter percebido que, pelo menos o começo do nosso INSERT INTO é a mesma coisa, mas muda uma coisinha.

Você jamais irá passar o valor diretamente lá dentro de VALUES. Nós adicionamos interrogações (?) em vez disso e, então, no outro parâmetro da função dbExec, passamos os argumentos, respectivamente. Não se esqueça disso: é sempre na ordem em que você colocou os nomes antes.

Nesse caso, eu passei position, color, type, size, creator, created_at. Sendo assim, eu sou obrigado a passar os argumentos dessa forma. Primeiro sendo a posição, depois a cor, depois o tipo, o tamanho e continua...

O total de interrogações (?) depende exatamente disso, de quantas colunas você passou. Existem 6 colunas em nosso exemplo.

Mostrando as informações do marker mais próximo

Começaremos criando uma função para que possamos obter o marker mais próximo do player que executou o comando.

function getNearestMarker(playerRef)
    local matches = {}
    local px, py, pz = getElementPosition(playerRef)

    for marker, data in pairs(markers) do
        local mx, my, mz = unpack(data.position)
        local distance = getDistanceBetweenPoints3D(px, py, pz, mx, my, mz)

        if distance <= 2 then
            matches[#matches + 1] = marker
        end
    end

    if #matches == 0 or #matches > 1 then
        return false
    end

    return matches[1]
end

Com a função criada, agora vamos criar um comando para ver as informações.

addCommandHandler("show-marker",
    function(player)
        local marker = getNearestMarker(player)

        if not marker then
            return false
        end

        local data = markers[marker]

        local markerId = data.id
        local creatorName = data.creator
        local stringDate = os.date("%d/%m/%Y", data.created_at)

        outputChatBox("-> ID: " .. markerId, player, 255, 255, 255, true)

        outputChatBox("-> Quem criou: " .. creatorName, player, 255, 255, 255, true)

        outputChatBox("-> Quando foi criado: " .. stringDate, player, 255, 255, 255, true)
    end
)

-- Como usar o comando:
-- /show-marker, perto de um marker

Observação: O uso de tabelas é de extrema importância. Com elas nós podemos visualizar, neste exemplo, os markers sem precisar buscar no banco de dados. Consultas são pesadas e devem ser feitas o mínimo possível. Crie um cache, como eu fiz e sempre que iniciar os resources, armazene os markers numa tabela. Você verá o quão bom é usar quando precisa editar alguma coisa do marker, seja a cor ou o tipo.

Alterando a cor do marker mais próximo

Como já temos a função de obter o marker mais próximo, vamos direto ao código!

addCommandHandler("edit-marker-color",
    function(player, command, red, green, blue, alpha)
        local db = exports.dbtut:getConnection()

        if not db then
            return false
        end

        local marker = getNearestMarker(player)

        if not marker then
            return false
        end

        local data = markers[marker]
        local markerId = data.id

        -- Nós precisamos do ID aqui para editar SOMENTE
        -- O marker que queremos

        -- Vamos obter a cor atual do marker
        -- Para adicionar um "fallback" caso o usuário
        -- Passe somente uma parte da cor
        local mR, mG, mB, mA = getMarkerColor(marker)

        -- Verificando se as cores estão corretas
        red = tonumber(red) or mR
        green = tonumber(green) or mG
        blue = tonumber(blue) or mB
        alpha = tonumber(alpha) or mA

        -- Alteramos a cor do marker então
        setMarkerColor(marker, red, green, blue, alpha)

        -- Agora o mais importante...
        -- Lembra que eu disse que tabelas são importantes? Pois então
        -- Nós já temos o ID (markerId)
        -- Basta atualizar a cor no banco de dados

        dbExec(db, "UPDATE `markers` SET `color` = ? WHERE `id` = ?", toJSON({ red, green, blue, alpha }), markerId)

        print("Você alterou a cor do marker de ID " .. markerId)
    end
)

-- Como usar o comando:
-- /edit-marker-color 255 89 0 255, perto de um marker
-- /edit-marker-color <r> <g> <b> <a>

Você deve ter percebido que eu usei interrogação (?) aqui também. Sim, é de extrema importância usar, pois como no comando INSERT INTO, lá em VALUES, caso esteja sendo passado diretamente, irá ocorrer o famoso SQL Injection. Jogadores de má índole poderão quebrar totalmente seu banco de dados.

Preste bem atenção e lembre-se novamente: está tudo numa ordem! Vamos por partes.

UPDATE `markers` SET `color` = ? WHERE `id` = ?

Basicamente é isso: eu estou querendo mudar a cor, mas somente se o ID for igual àquele que passarmos. Se falarmos em voz alta e lermos o código, fica mais fácil. Preste bem atenção.

"O que eu quero fazer?" 🤔

dbExec(db, "UPDATE `markers` SET")

"Eu quero alterar a cor" 🎨

dbExec(db, "UPDATE `markers` SET `color` = ?", toJSON({ red, green, blue, alpha }))

"Mas somente se for desse ID aqui ó, código" ❗

dbExec(db, "UPDATE `markers` SET `color` = ? WHERE `id` = ?", toJSON({ red, green, blue, alpha }), markerId)

Pronto. Eles estão em ordem. Agora a cor será alterada, se for daquele ID.

Ah, e lembrando, você pode passar mais coisas além da cor. No exemplo só quero mesmo alterar a cor. Porém, se precisássemos mudar a cor e o tipo ao mesmo tempo, ficaria desta forma:

local markerType = "corona"

dbExec(db, "UPDATE `markers` SET `color` = ?, `type` = ? WHERE `id` = ?", toJSON({ red, green, blue, alpha }), markerType, markerId)

Nós separamos por vírgula. E novamente, perceba a ordem. Jamais se esqueça disso e preste muito atenção sempre que for mexer nisso.

Deletando o marker mais próximo

Hora de deletar o nosso querido marker. Vamos ao código... porém, antes de começar, criaremos uma função para obter o total de itens dentro de uma tabela.

function table.length(array)
    local count = 0
    for _ in pairs(array) do
        count = count + 1
    end
    return count
end
addCommandHandler("delete-marker",
    function(player)
        local db = exports.dbtut:getConnection()

        if not db then
            return false
        end

        local marker = getNearestMarker(player)

        if not marker then
            return false
        end

        local data = markers[marker]
        local markerId = data.id

        -- Nós precisamos do ID aqui para deletar SOMENTE
        -- O marker que queremos

        markers[marker] = nil
        destroyElement(marker)

        dbExec(db, "DELETE FROM `markers` WHERE `id` = ?", markerId)

        -- Lembra que criamos uma função para pegar o total de items
        -- na tabela? Então, iremos usá-la para limpar a tabela
        -- do banco de dados. Dessa forma, os IDs do AUTO_INCREMENT
        -- serão resetados, ocasionando nenhum bug

        if table.length(markers) == 0 then -- Caso não tenha mais nenhum marker criado (obviamente não terá nem no banco de dados)
            dbExec(db, "TRUNCATE `markers`")
            lastId = 0 -- Também voltamos o contador do último ID para 0
        end

        print("Você deletou o marker de ID " .. markerId)
    end
)

-- Como usar o comando:
-- /delete-marker, perto de um marker

Muito obrigado por ler até aqui ♥

O tutorial termina por aqui e espero que eu possa ter passado um pouco de conhecimento para a comunidade. Isso estava previsto para ser postado ano passado, em Janeiro de 2022, porém o meu tempo ficou curto e não consegui. Escrevi este tutorial novamente, tudo do zero para vocês e elaborei mais coisas.

Ainda existem muitas coisas a serem vistas em relação aos bancos de dados. No momento, o básico está neste tutorial. Eu garanto que vocês são capazes de aproveitar muita coisa daqui. Leiam e releiam caso necessário.

Qualquer dúvida em relação ao código pode me chamar no privado do Discord, responderei assim que tiver disponível.

Estudem, aprendam e não parem de seguir o que vocês gostam!

Gratidão,

androksi.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment