Tutorial SQLite
#1

Tutorial SQLite


Introducere
- Multi dintre voi credeti ca SQLite este foarte foarte greu de inteles, ei bine nu este asa, este chiar simplu! Am decis sa fac acest tutorial deoarece ma plictisesc si poate romanu' isi va da seama ce este mai rapid si in care system sa ai incredere.
In SQLite poti sa ai incredere 99.9% deoarece, aplicat cum trebuie, nu vei avea scurgeri de memorie sau lipsa de data.


Ce este SQLite ?
- SQLite este un fel de MySQL dar cu baza de date interna. Adica un fisier cu extensia .db. SQLite este bazat pe tabele si coloane, este foarte usor de folosit si are multe functii folositoare prin care poti face ceva mai bun decat cu metodele prin fisiere.
Denumirea de la SQL este Structured Query Language. In SQL totul este bazat pe stringuri cu functii cheie care duc la realizarea unei actiuni.
AI NEVOIE DE UN MANAGER DE BAZE DE DATE CA SA CITESTI INFORMATIA!
DESCARCA-L AICI
http://solidfiles.com/d/af325/download



Clauze de folosit:
  • Clauza CREATE TABLE IF NOT EXISTS creeaza tabelul daca nu exista, se foloseste deobicei in OnFilterScriptInit sau OnGameModeInit, sau unde vrei tu defapt.
  • Clauza FROM specifica din ce tabel sa ia anumita informatie.
  • Clauza WHERE specifica locatia unui element in tabel, de exemplu, noi vrem sa preluam data `kills` unde `nume` este 'Zh3r0'. Se foloseste ca punct de reper.
  • Clauza ORDER BY ordonoeaza o anumita coloana dupa titlu, dupa marine, crescator, decrescator.
  • Clauza SELECT seleteaza `stat`. Se poate folosi in combinatie cu FROM si cu WHERE . Gen, "SELECT * FROM `Tabel` WHERE `Name` = 'Zh3r0' ", ceea ce inseamna ca verifica daca randul unde numele este Zh3r0 exista.
  • Clauza AND se poate folosi pentru intarirea unei verificatii, gen "SELECT * FROM `Tabel` WHERE `Name`= 'Zh3r0' AND `Password` = 'blabla' ", verifica daca in `Nume` este Zh3r0 dar in acelasi timp `Password` sa aiba 'blabla'
  • Clauza UPDATE updateaza un rand din tabel.Daca randul nu exista, nici-o actiune nu v-a fi luata.
  • Clauza INSERT INTO insereaza in tabel un rand nou, chiar daca randul exista, v-a fi duplicat, de aceea trebuie sa te referi la clauza UPDATE cand vrei sa updatezi randul.
  • Clauza DELETE FROM sterge un rand din tabel, se foloseste impreuna cu clauza WHERE pentru a determina care rand v-a fi sters.
    - Exista mai multe clauze, dar eu am listat cele mai imporante si des folosite in SA-MP.

Cum sa:

Cum cream o baza de date?
Folosind functia db_open();.
Intai creeam o variabila cu tagul DB: deoarece vrem ca variabila sa fie recunoscuta ca asociat al SQL.
Scrie in topul scriptului

pawn Код:
new DB:Database;
Dute la callbackul OnFilterScriptInit() daca e FS sau OnGameModeInit() daca e GM
Adauga urmatorul cod:
pawn Код:
Database = db_open("Database.db");
Codul de mai sus v-a creea baza de date daca nu exista si o v-a deschide daca exista pentru a putea primi informatii, sau a da informatii.
Sub acel cod adauga asta:
pawn Код:
db_free_result(db_query(Database, "CREATE TABLE IF NOT EXISTS `Tabel` (`Nume`, `Bani`, `Ratio`)"));

Codul de mai sus, v-a creea tabelul `Tabel` in fisierul Database.db din scriptfiles daca nu exista.In acelasi timp v-a adauga 3 coloane, cele enumerate in ( ).
Succes! Ai creat o baza de date dar in acelasi timp ai adaugat si 3 coloane!

Ce inseamna db_query() si db_free_result()?
pawn Код:
db_query()
Cu aceasta functie se poate scrie dar si citi in acelasi timp, depinde de ce ai scris in acel string, si ce clauza ai folosit.

pawn Код:
db_free_result()
Trebuie sa te asigur ca de fiecare data, cand citesti, sau scri intr-o baza de date, sa eliberezi rezultatele, altfel s-ar puea sa intampini buguri sau o scurgere de memorie, ceea ce cred ca nu ai vrea sa se intample!


Cum scriu intr-o baza de date?

Folosind functia db_query().
Ca exemplu sa luam OnFilterScriptInit() si sa lucram acolo.

Nu trebuie sa deschidem baza de date cu functia db_open() deoarece ea a fost deschisa la initierea fiserului.
Hai sa scriem ceva in acele 3 coloane in tabelul numit Tabel.
pawn Код:
//Cream un string numit Query cu care v-om putea dauga date, gen Numele jucatorului, Scoru, killurile etc.
new Query[129];

//Formata stringul cu numele si toate cele ca dupaia sa folosim db_query() pentru a le scrie.
format(Query, sizeof(Query), "INSERT INTO `Tabel` (`Nume`, `Bani`, `Ratio`) VALUES('%s', '%d', '%f')", ("Zh3r0"), 500, Float:555 / Float:34);

//Acum sa scriem in baza de date ce am scris mai sus, bine nu chiar, codu de sus v-a fi transformat intr-o comanda pe care bazele de date le inteleg si le transforma in ceva psihic si le proceseaza si iese un rand nou.
db_query(Database, Query);

//Daca vrei sa fi sigur ca eliberezi orice ramasita de informatie, fa astfel.
db_free_result( db_query(Database, Query) );//In acelasi timp eliberam informatia care nu este necesara si actionam.
Puteti deschide acum fisierul Database.db din folderul scriptfiles din folderul cu server, deshideti fisierul cu programul pus la dispozitie mai sus la Introducere.
Cand deschideti baza de date ar trebui sa aveti asa ceva




Cum citesc dintr-o baza de date?
Acum hai sa facem o comanda prin consola ca sa evitem intrarea pe server si toate cele.
Adauga functia asta undeva in script, daca exista deja, doar ia ce e inauntru si baga acolo.
pawn Код:
public OnRconCommand(cmd[])
{
    if(!strcmp(cmd, "/start", .length = strlen("/start")))
    {
     
    }
    return 1;
}
Acum daca scri in consola /start nu se v-a intampla nimic deoarece este GOL!
Hai sa-l umplem cu codul pentru citire!
pawn Код:
if(!strcmp(cmd, "/start", .length = strlen("/start")))
{
     //Cream un string numit Query in care vom formata codul pentru preluare de informatie.
     new Query[256];

     //Creeam o variabila in care stocam rezultatul primit din db_query().
     new DBResult:Rezultat;

     //Formatam stringul Query cu datele necesare in preluarea informatiei.
     //In acest format verificam daca in tabelul `Tabel` exista un rand care contine la coloana `Nume` cuvantul Zh3r0.
     format(Query, sizeof(Query), "SELECT * FROM `Tabel` WHERE `Nume` = 'Zh3r0'");

    //Cu acest cod v-om citi ce am cerut mai sus, am scris Rezultat = pentru a stoca informatia primita in db_query pentru a verifica daca ce am scris mai sus este valid.
     Rezultat = db_query(Database, Query);

     //Acum, folosim functia db_num_rows pentru a verifica daca am primit o informatie valida sau nu, daca Zh3r0 exista in Tabel in coloana `Nume`.
     //Intai verificam daca este adevarat, daca intradevar, Zh3r0 exista in Tabel la coloana `Nume`.
     if(db_num_rows(Rezultat))
     {
           //Dam de stire ca a rezultat corect, v-a printa in consola ce am scris mai jos.
           print("Rezultatul a fost corect, Zh3r0 exista un Tabel in coloana `Nume`");
   
           //Cream un string in care stocam informatia primita din baza de date.
           new Field[30];
   
           //Cream variabilele unde vom stoca informatia.
           new Bani, Float:Ratio;

           //Acum sa preluam datele din coloana `Bani` si `Ratio` de la `Nume` egal cu Zh3r0.
           db_get_field_assoc(Rezultat, #Bani, Field, 30);

           //Strngul Field a primit acum informatia de la `Bani` unde `Nume` = 'Zh3r0'
           //O stocam intr-o variabila, poate sa fie si variabila facuta de tine, gen pInfo[playerid][Bani]
           Bani = strval(Field);//strval deoarece informatia este un string si trebuie sa devina integer.(EX: 100)
 
           //Sa prelam ratia din `Tabel` unde `Nume` = 'Zh3r0'
           db_get_field_assoc(Rezultat, #Ratio, Field, 30);

           //floatstr deoarece informatia din Field este un string si trebuie transformata intr-un float (EX: 4.7)
           Ratio = floatstr(Field);

           //Acum sa printam informatia primita!
           printf(#Bani: %d","# Ratio: %.4f, Bani, Ratio);
}
//Am preluat din `Tabel` unde `Nume` = 'Zh3r0' cu success, acum eliberam informatiile in exces!
db_free_result(Rezultat);

Acum in consola ar trebui sa apara:
Bani: 500, Ratio: 16.3235


Cum sterg o linie din tabel?

Simplu! Folosind clauza DELETE FROM.

Exemplu de stergere:
pawn Код:
db_query(Database, "DELETE FROM `Tabel` WHERE `Nume` = 'Zh3r0'");
V-a sterge toata linia unde gaseste la coloana `Nume` un string 'Zh3r0'.

Informatii utile!
  • De ce la coloane am folosit ` ` ? Deoarece, cand adaugam o coloana fara ` ` s-ar putea ca sa avem scurgeri de memorie, folosind aceste doua apaostroafe ajuta la acuratete.
  • De ce cand scriam sau citeam ceva am folosit ' ' ? La fel ca mai sus, ca informatia sa fie preciza!
  • De ce am folosit ("Zh3r0") ? Este doar un exemplu, acela poate deveni gen Name(playerid) sau pName, adica o variabila care contine numele jucatorului.
Descarca un simplu Login/Register script facut cu SQL.
DOWNLOAD AICI!

Odata descarcat, intri in joc si vei da /register <parola>.
Parola trebuie sa fie de min 5 caractere si max 24.
Odata creat contu dute in sriptfiles si deschide fisierul numit Conturi.db cu programul mentionat mai sus.
Inauntru trebuie sa aiba:


Dar cu datele tale!


### Daca aveti intrebari lasati aici si va ajut.
Reply
#2

bun.
merci, chiar daca nu-l folosesc
e bun pentru cei interesati
Reply
#3

Super Zh3ro xD
Foarte folositor,chiar acum aveam nevoie de un tutorial dinasta,mersi
Reply
#4

Super Zh3ro , mersi
Reply
#5

da cam usor )


Bravo Zh3r0
Reply
#6

1. Functia db_free_result se foloseste doar pentru clauza SELECT.
2. Uita-te mai atent la callback-ul OnPlayerDisconnect. La fel ca si 3.
3.
Quote:
Originally Posted by Zh3r0
Посмотреть сообщение
pawn Код:
db_free_result(db_query(Database, "CREATE TABLE IF NOT EXISTS `Tabel` (`Nume`, `Bani`, `Ratio`)"));
Codul de mai sus, v-a creea tabelul `Tabel` in fisierul Database.db din scriptfiles daca nu exista.In acelasi timp v-a adauga 3 coloane, cele enumerate in ( ).
Succes! Ai creat o baza de date dar in acelasi timp ai adaugat si 3 coloane!
Codul de mai sus nu are niciun sens. Chiar daca ai folosit db_free_result pentru acel query, nu va elibera nicio informatie pentru ca nu are de unde.

4. In primul exemplu, comanda /start. Nu eliberezi datele "in exces". Eliberezi toate informatiile luate de SELECT.

5. Cand creezi o baza de date, fiecare tabel trebuie sa aiba un ID (primary key) pentru o cautare mai eficienta. In exemplul tau, tu selectezi toata informatia dintr-un rand sa vezi daca exista (SELECT *), si nu-i prea bine daca vrei sa fi cat mai eficient posibil.

6. Cand creezi o baza de date ^, atribuie fiecarei coloane tipul de data potrivit. Nume TEXT, Bani NUMERIC, Ratio TEXT.

Daca faci un tutorial, nu te complica. Foloseste variabile, nu le pune direct cum ai facut in codul de mai sus, pentru ca complici treaba si nici tu nu mai intelegi ce faci.
Reply
#7

Quote:
Originally Posted by [NoV]LaZ
Посмотреть сообщение
1. Functia db_free_result se foloseste doar pentru clauza SELECT.
2. Uita-te mai atent la callback-ul OnPlayerDisconnect. La fel ca si 3.
3.
Codul de mai sus nu are niciun sens. Chiar daca ai folosit db_free_result pentru acel query, nu va elibera nicio informatie pentru ca nu are de unde.

4. In primul exemplu, comanda /start. Nu eliberezi datele "in exces". Eliberezi toate informatiile luate de SELECT.

5. Cand creezi o baza de date, fiecare tabel trebuie sa aiba un ID (primary key) pentru o cautare mai eficienta. In exemplul tau, tu selectezi toata informatia dintr-un rand sa vezi daca exista (SELECT *), si nu-i prea bine daca vrei sa fi cat mai eficient posibil.

6. Cand creezi o baza de date ^, atribuie fiecarei coloane tipul de data potrivit. Nume TEXT, Bani NUMERIC, Ratio TEXT.

Daca faci un tutorial, nu te complica. Foloseste variabile, nu le pune direct cum ai facut in codul de mai sus, pentru ca complici treaba si nici tu nu mai intelegi ce faci.
  1. Inteleg, e bine de stiut si de aflat lucruri noi, acum stiu, nu se v-a mai repeta.
  2. Rezolvat!
  3. Am inteles, doar la clauza SELECT. Faza era ca eu cand am invatat SQLite m-am luat dupa un script, si asa avea si el.
  4. Okey, inteleg, nu data in exces si informatia insine
  5. Imi arati te rog un exemplu de INCREMENT PRIMARY KEY sau PRIMARY KEY, depinde care e bun si ce fac.
  6. Am inteles! Mersi ca mi-ai spus, la 0Admin nu aveam asa ceva.
Pai eu doar am aratat un exemplu, scriptul care l-am pus la dispozitie e "Adevaratul" lucru.

Acum, daca te rog, poti sa-mi raspunzi la ce am zis mai sus? Ca vreau sa imbunatatesc!
Reply
#8

Pentru auto increment se foloseste coloana INTEGER PRIMARY KEY AUTOINCREMENT, nu stiu daca SA-MP suporta asa ceva, iar pentru primary key coloana INTEGER PRIMARY KEY; ii confirmat ca functioneaza.
Acum ca ai un primary key, query-ul tau ar trebui sa arate cam asa cand selectezi ceva.
Код:
SELECT `coloanaprimarykey` FROM `tabel` WHERE `coloana` = 'ceva';
Ai selectat mai putine date si mai rapid datorita acelei coloane speciale, deci mai putin de procesat .
Reply
#9

http://www.devdaily.com/android/sqli...ty-primary-key

Samp suporta ceea ce suporta si SQLite. https://sampwiki.blast.hk/wiki/Changelog#Version_0.3b (Upgraded sqlite version to 3.7.0.1)

Mare atentie la securitatea datelor ! Pentru a preveni sql injection, datele care pot fi introduse de catre clienti, trebuie sa verificate sa nu contina caractere nepermise.

Exemplu de injection, daca stii structura tabelului:
Sa presupunem ca avem o comanda care afiseaza ora cand a fost conectat un anumit jucator pe server, spre ex:
/seen Zh3r0

query-ul trimis ar fi unul de tipul urmator:
Код:
SELECT conectare FROM `Tabel` WHERE `Nume` = 'Zh3r0'
O persoana rau intentionata insa, ar putea incerca urmatorul lucru:

Код:
/seen %';DROP TABLE `Tabel`--
Astfel, query-ul trimis catre server va deveni:
pawn Код:
SELECT conectare FROM `Tabel` WHERE `Nume` = '%';DROP TABLE `Tabel`--'
Ne trezim cu 2 query-uri trimse, unul care afiseaza toate potrivirile, apoi practic al 2-lea sterge toata structura+continutul tabelului cu numele `Tabel`

http://www.sqlite.org/lang_expr.html
Код:
If the optional ESCAPE clause is present, then the expression following the ESCAPE keyword must evaluate to a string consisting of a single character. This character may be used in the LIKE pattern to include literal percent or underscore characters. The escape character followed by a percent symbol (%), underscore (_), or a second instance of the escape character itself matches a literal percent symbol, underscore, or a single escape character, respectively.
Reply
#10

Sa presupun ca acuma, in legatura cu securitate si siguranta, totul este OK nu?
pawn Код:
CREATE TABLE IF NOT EXISTS `Users` (`ID` INTEGER PRIMARY KEY,`IP` TEXT,`Nume` TEXT,`Parola` TEXT,`Bani` NUMERIC,`Scor` NUMERIC)"

Si presupun ca asa merge de acum? Fara SELECT * FROM
pawn Код:
SELECT `ID` FROM `Users` WHERE `Nume` = '%s'

EDIT: Am vazut ca ai dat edit, eu sincer nu inteleg mare lucru din situ-l lor oficial.
O idee cum as putea scapa de aia? De vreo problema cu securitatea...


EDIT2: `ID` trebuie sa stocheze vreo valoare? Sau trebuie sa fie null?
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)