AXV09

mysql [poradnik]

Dec 8th, 2012
97
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 10.99 KB | None | 0 0
  1. Spis treści:
  2. 1). Wprowadzenie
  3. 2). Wymagania
  4. 3). Tworzenie tabel
  5. 4). Typy pól
  6. 5). Łączenie z bazą
  7. 6). Wysyłanie zapytania
  8. 7). Omówienie kilku funkcji dot. MySQL
  9. 8). Obsługa danymi:
  10. - stworzenie rekordu
  11. - pobranie rekordu
  12. - zapisanie danych
  13. 9). Rady, zakończenie
  14.  
  15.  
  16.  
  17. Wprowadzenie:
  18. MySQL to inaczej wolnodostępny system zarządzania bazą danych.
  19. Jest obsługiwany przez wiele systemów, dzięki czemu nie mamy problemu z utrzymaniem kompatybilności.
  20. Dodatkowo jest wydany wersji źródłowej, co umożliwia skompilowanie go dla dowolnej platformy systemowej.
  21. Istnieje kilka typów mechanizmów każdy z nich służy do innego zastosowania:
  22. - MyISAM - domyślny mechanizm (nie obsługuje transakcji ani kluczy obcych, umożlwia wyszukiwanie pełnotekstowe)
  23. - InnoDB - także domyślna opcja (obługuje transakcje, klucze obce oraz zakładanie blokad na poziomie wierszy)
  24. Jest jeszcze kilka typów, ale nimi się nie będziemy interesować, ponieważ zostały wycofane.
  25.  
  26. Wymagania:
  27. Co prawda MySQL nie potrzebuje dużych wymagań z takiego powodu iż sam w trakcie wykonywania procesów, stara się je sam optymalizować.
  28. To także dotyczy się tabel, baz danych...
  29. Z doświadczenia nauczyłem się, że w teorii bazy potrzebują dużo pamięci RAM i szybkie dyski, można też trafić na to, że procesory też są brane pod uwagę.
  30. Głównie MySQL opiera się na cache'ch, bo ponad 90% wykonywanych zapytań trafia właśnie tam.
  31. Konfiguracja dla osób, które chcą w przyszłości otworzyć firme oferująca bazy danych:
  32. - Procesor: sempron 3000+
  33. - Pamięć: 2 GM RAM
  34. - Dysk twardy (główny): 2x250 GB (RE, 16 MB cache) z RAID
  35. - Dysk twardy (poboczny): 1x400 GB (wolniejsze dyski, dla przeprowadzanych backup'ów)
  36. Druga konfiguracja "optymalna" dla użytkownika:
  37. - Procesor: 1000+
  38. - Pamięć: 256/512 MB RAM
  39. - Dysk twardy: 20 GB z (RE, 16 MB cache i RAID)
  40.  
  41. Tworzenie tabel:
  42. Jest to główny proces obsługi naszej bazy, wymaga utworzenia bazy i połączenia się, ale o łączeniu w następnym rozdziale.
  43. Możemy zacząć wprowadzać dane, najpierw jednak trzeba utworzyć tabele, robimy to według następującego schematu:
  44. [code]
  45. CREATE TABLE nazwa_tabeli (nazwa_pola1 typ_pola1 [atrybuty], nazwa_pola2 typ_pola2 [atrybuty], nazwa_pola3 typ_pola3 [atrybuty], PRIMARY KEY(nazwa_polaX))
  46. [/code]
  47. Przykład:
  48. [code]
  49. CREATE TABLE NBA (id int NOT NULL AUTO_INCREMENT, imie char(30), lata char(3), punkty char(3), mistrzostwa char(3), PRIMARY KEY(id))
  50. [/code]
  51. Każda tabela musi posiadać co najmniej jedno pole, dodatkowo co najmniej jedno pole, które będzie jednoznacznie identyfikuje wiersz w tabeli - tak zwany klucz główny.
  52. Jeśli jest masa danych, a Ty znasz klucz główny jednego z wierszy wtedy możesz bez problemu dostać się do tego wiersza.
  53. W naszym przypadku kluczem głównym jest pole pierwsze - id.
  54. Przeważnie nadaje jako klucz główny określa się pierwsez pole tabeli.
  55. Dodatkowo klucz główny posiada dwa atrybuty:
  56. pierwszy - NOT NULL - oznaczający, że wartość tego pola nigdy nie może być pusta;
  57. drugi - AUTO_INCREMENT* - oznaczający, że wartość pola będzie automatycznie zwiększania przez baze danych przy dodaniu rekordu;
  58.  
  59. * Atrybut AUTO_INCREMENT - możemy stosować tylko do pól typu całkowitoliczbowego.
  60.  
  61. Typy pól:
  62. Dostępnych jest wiele typów pól, najpopularniejsze poniżej:
  63. - CHAR(x) / VARCHAR(x) - ciąg znaków o maksymalnej dł. X, gdzie X nie może być większy od 255;
  64. - BLOB - binarny ciąg znaków o dł. ograniczonej przez pamięc Twojego serwera;
  65. - TINYINT(ilość znaków) - liczby z zakresu od -128 do 127 lub liczby dodatnie od 0 do 255;
  66. - SMALLINT(ilość znaków) - liczby z zakresu od -32768 do 32767 lub liczby dodatnie od 0 do 65535;
  67. - MEDIUMINT(ilość znaków) - liczby z zakresu od -8388608 do 8388607 lub liczby dodatnie od 0 do 16777215;
  68. - INTEGER / INT - liczba całkowita z przedziału -2147483647 do 2147483647 lub liczby dodatnie od 0 do 4294967295;
  69. - TEXT - tekstowy ciąg znaków o dł. ograniczonej przez pamięć Twojego serwera;
  70. - DATE - data w formacie określonym przez ustawienia serwera;
  71. - ENUM - enumeracja (wyliczenie). W kolumnie może się znaleźć jedna z podanych wartości;
  72. - YEAR - rok, jeśli zostanie podany zły, jego wartość zmieni się w 0000;
  73. - DECIMAL(x, y) - liczba dziesiętna, gdzie X oznacza maksymalną liczbe cyfr, a Y maksymalną liczbę cyfr po przecinku;
  74.  
  75. Łączenie z bazą:
  76. Za pomocą poniższego kodu połączymy się poprawnie z naszą bazą (plugin: MySQL StrickenKid):
  77. [code]
  78. #define SQL_HOST "localhost"
  79. #define SQL_USER "user"
  80. #define SQL_PASSWORD "password"
  81. #define SQL_DB "datebase"
  82.  
  83. new MySQL:sql_init;
  84. public OnFilterScriptInit()
  85. {
  86. sql_init = mysql_init(1);
  87. new sql_handle = mysql_connect(SQL_HOST, SQL_USER, SQL_PASSWORD, SQL_DB, sql_init, .auto_reconnect=1);
  88. if (sql_handle) // mysql_connect jeśli nastąpi poprawne połączenie z bazą zwróci nam wynik "true"
  89. {
  90. // jeśli warunek się wykona
  91. printf("Połączono z bazą danych, gratulacje!");
  92. } else {
  93. // jeśli warunek się nie wykona
  94. printf("Niepołączono z bazą danych!!!");
  95. SendRconCommand("exit"); // zamykamy serwer
  96. }
  97. return 1;
  98. }
  99.  
  100. public OnFilterScriptExit() return mysql_close(sql_init);
  101. [/code]
  102. I tak oto połączyliśmy się z naszą bazą!
  103.  
  104. Wysyłanie zapytania:
  105. W tym kroku nauczymy się wykonywać polecenia/zapytania, które wyślemy do naszej bazy.
  106. Dla przykładu pobierzemy z naszej przykładowej tabeli lata oraz punkty, którego wyszukamy za pomocą imienia.
  107. [code]
  108. new buffer[127], playerNick[MAX_PLAYER_NAME];
  109. GetPlayerName(playerid, playerNick, MAX_PLAYER_NAME);
  110. mysql_real_escape_string(playerNick, playerNick); // sprawdzamy, czy nie ma zadnych podejrzanych znakow, ktore moga naszej bazie zaszkodzic
  111. format(buffer, 127, "SELECT lata, punkty FROM NBA WHERE imie='%s'", playerNick);
  112. if (mysql_query(buffer)) mysql_ping(); // Ta linijka pozwoli nam podtrzymać nasze połączenie
  113. mysql_store_result(); // zapisujemy do pamięci
  114. if (mysql_num_rows() && mysql_fetch_row(playerNick, ""))
  115. {
  116. new lata, punkty;
  117. sscanf(playerNick, "dd", lata, punkty);
  118. format(buffer, 127, "Masz %d punktów i %d lat.", punkty, lata);
  119. SendClientMessage(playerid, -1, buffer);
  120. }
  121. mysql_free_result(); // czyścimy pamięć
  122. [/code]
  123. Jeśli nasz rekord będzie istniał otrzymamy wiadomość np.
  124. [code]
  125. Masz 14 punktów i 19 lat.
  126. [/code]
  127.  
  128. Omówienie kilku funkcji dot. MySQL:
  129. Ogólnie w MySQL posiadamy bardzo dużo funkcji, które przydają się nam w różnych problemach można znaleźć rozwiązenia dzięki nim.
  130. Podam tylko te związane z datą:
  131. [code]
  132. -------------------------------------------------
  133. | Funkcja | Przykład użycia | Opis |
  134. -------------------------------------------------
  135. HOUR() | HOUR(kolumna) | Zwraca samą godzine, ze wskazanej daty
  136. MINUTE() | MINUTE(kolumna) | Zwraca same minuty, ze wskazanej daty.
  137. SECOND() | SECOND(kolumna) | Zwraca same sekundy, ze wskazanej daty.
  138. DAYNAME() | DAYNAME(kolumna) | Zwraca nazwę dnia tygodnia.
  139. DAYOFMONTH() | DAYOFMONTH(kolumna) | Zwraca sam dzień miesiąca, ze wskazanej daty (wyrażone liczbą).
  140. MONTHNAME() | MONTHNAME(kolumna) | Zwraca nazwę miesiąca występującego we wskazanej dacie.
  141. MONTH() | MONTH(kolumna) | Zwraca sam miesiąc ze wskazanej daty (wyrażony liczbą).
  142. YEAR() | YEAR(kolumna) | Zwraca sam rok ze wskazanej daty.
  143. ADDDATE() | ADDDATE(kolumna INTERVAL x typ) | Dodaje do daty przechowywanej w kolumnie x jednostek i zwraca wynik
  144. SUBDATE() | SUBDATE(kolumna INTERVAL x typ) | Odejmuje od daty przechowywanej w kolumnie x jednostek i zwraca wynik.
  145. UNIX_TIMESTAMP()| UNIX_TIMESTAMP(data) | Zwraca liczbę sekund jaka upłynęła od początku tzw. epoki unixa lub od wskazanej daty.
  146. [/code]
  147.  
  148. Obsługa danymi:
  149. - stworzenie rekordu
  150. W życiu codziennej pracy MySQL, przyjdzie taka pora, że trzeba będzie stworzyć REKORD.
  151. A więc napiszmy taką, sugerując się wcześniejszą tabelą
  152. Przykład 1).
  153. [code]
  154. INSERT INTO NBA (imie, punkty, lata, mistrzostwa) VALUES ('Imie', '17', '2', '1');
  155. [/code]
  156. Przykład 2).
  157. [code]
  158. INSERT INTO NBA SET imie='Imie', punkty='17', , lata='2', mistrzostwa='1';
  159. [/code]
  160. Przykład 3).
  161. [code]
  162. INSERT INTO NBA ('Imie', '17', '2', '1');
  163. [/code]
  164. Jak widzimy, można zrobić to na wiele sposobów.
  165.  
  166. - pobranie rekordu
  167. Ten krok pozwoli się nam przyjrzeć jak powinno wygladać poprawne pobranie rekordu.
  168. Stwórzmy sobie funkcje, która wyśle zapytanie, czy dane konto o nicku np. 'Jaś' istnieje...
  169. [code]
  170. public OnPlayerConnect(playerid)
  171. {
  172. if (SprawdzCzyKontoIstnieje(playerid))
  173. {
  174. SendClientMessage(playerid, -1, "Twoje konto istnieje w bazie danych!");
  175. } else {
  176. SendClientMessage(playerid, -1, "Twoje konto nie istnieje w bazie danych!");
  177. }
  178. return true;
  179. }
  180.  
  181. SprawdzCzyKontoIstnieje(graczid)
  182. {
  183. new buffer[127], nick[24], bool: istnieje = false;
  184. GetPlayerName(graczid, nick, MAX_PLAYER_NAME);
  185. mysql_real_escape_string(nick, nick);
  186. format(buffer, 127, "SELECT 1 FROM NBA WHERE imie='%s'", nick);
  187. if (mysql_query(buffer)) mysql_ping();
  188. mysql_store_result();
  189. if (mysql_nom_rows()) istnieje=true;
  190. mysql_free_result();
  191. return istnieje; // jeśli znalazlo konto otrzymamy wynik true, jesli nie, to false
  192. }
  193. [/code]
  194. Proste, prawda?
  195.  
  196. - zapisanie danych
  197. Przyszła pora na zapisanie/zaaktualizowanie danych gracza
  198. Użyjemy SEPARATORA "UPDATE":
  199. [code]
  200. enum p_info { bool: logged, imie[24], punkty, lata, mistrzostwa };
  201. new pInfo[MAX_PLAYERS][p_info];
  202.  
  203. public OnPlayerDisconnect(playerid, reason)
  204. {
  205. if (pInfo[playerid][logged]) // Sprawdzamy czy zalogowany jest
  206. {
  207. new buffer[127];
  208. GetPlayerName(playerid, pInfo[playerid][imie], MAX_PLAYER_NAME);
  209. pInfo[playerid][punkty] = GetPlayerScore(playerid);
  210. format(buffer, 127, "UPDATE NBA SET punkty='%d', lata='%d', mistrzostwa='%d' WHERE imie='%s'", pInfo[playerid][punkty], pInfo[playerid][lata], pInfo[playerid][mistrzostwa], pInfo[playerid][imie]);
  211. mysql_query(buffer);
  212. }
  213. return true;
  214. }
  215. [/code]
  216. I tak oto, zapisaliśmy dane gracza, gdy opuścił serwer.
  217.  
  218. Zakończenie:
  219. W końcu nadszedł koniec tego skromnego poradnika.
  220. Należy pamiętać o SQL Injection, można się przed tym zabezpieczyć stosująć w formatach tj. '%s', '%d', '%f';
  221. P.S: Gdy będe miał jeszcze czas, to poprawie co nieco.
  222. Podałem możliwe przykłady stosując do tego PAWN, aby było prościej zrozumieć znaczenie...
  223. Życzę sukcesów z pozdrowieniami, AXV.
  224.  
  225. (C) 2012, AXV
Advertisement
Add Comment
Please, Sign In to add comment