Visar inlägg med etikett mysql. Visa alla inlägg
Visar inlägg med etikett mysql. Visa alla inlägg

02 mars, 2011

MySQL: InnoDB Foreign keys och Cascade

Förord
Hej på er! Nu ska jag förklara lite mer om databasen MySQL och en av databasmotorerna InnoDB. Jag upptäckte igår vad detta innebär och då började jag komma ihåg att jag hade läst om detta förut i en bra bok om just MySQL databashantering. Boken heter "MySQL handboken : [den snabba vägen till grunderna i MySQL]" och passar utmärkt till den som vill lära sig MySQL och gå in lite mer på djupet.

När jag läste boken förstod jag inte så mycket om foreign keys, som på svenska heter "främmande nycklar", men det förstår jag bättre nu. Därför har jag tänkt att visa ett exempel på när det kan vara mycket användbart.

Mycket bra läsning på engelska finns i en artikel publicerad på InnoDB.com [2]

Introduktion
Vad är MySQL?
Okej, som de flesta vet så är MySQL en typ av databas där man kan lagra information på ett strukturerat sätt. Och för er som inte vet, så vet ni nu vad MySQL är för något.,

SQL = Structured Query Language

Men vad kan MySQL användas till?
MySQL använder s.k. SQL-frågor för att skicka och hämta data från en databas. MySQL kan användas till att lagra information strukturerat om t.ex kunder som har bokat klipptider hos en frisör, eller produkter och artiklar som man vill sälja via en hemsida. När någon sedan har lagt en beställning kan man koppla produkterna till en specifik beställning som i sin tur hör till en registrerad kund.

Ett vanligt exempel från gymnasiet är en databas med elever som kommer att börja på skolan nästkommande termin. Vi fick lära oss hur man designar en databas med tabeller som är relaterade till varandra och hur man endast kan tillåta unika personer i databasen baserat på unika personnummer.

Fint, men vad är InnoDB för något?
I MySQL används olika databasmotorer (engines) för att spara och hämta data på olika sätt. Ska datans integritet kontrolleras eller spelar det ingen roll? Ska tabeller relateras med varandra eller skötas med programmering? Det är uppgiften som en databasmotor har.

InnoDB är inte så vanlig bland nybörjare eftersom standardmotorn heter MyISAM och många vet inte eller bryr sig inte om att kontrollera vilken databasmotor man använder. Databasen funkar ju fortfarande på samma sätt, eller? Ja det är sant men InnoDB kan kontrollera data i databasens tabeller så att länkarna, relationerna och integriteten inte bryts om en ändring sker i databasen.

Huvudregeln säger att i en relationsdatabas (en databas med relationer vilket hörs på namnet) så måste relaterade nycklar ha en korrekt länkning - nyckel1 med ID 4 i tabell A måste vara samma som nyckel1 med ID 4 i tabell B. Med InnoDB kan man kontrollera att ID-numret måste vara samma i båda tabellerna som är relaterade med varandra genom användning av främmande nycklar.

Om du inte förstår så är det helt förståeligt. Det kan vara ett svårt koncept i början innan man lär sig. Jag kommer strax gå igenom skillnaderna mellan InnoDB och MyISAM (den vanligaste databasmotorn).


Först en kort beskrivning om primärnycklar och främmande nycklar
En primärnyckel måste vara unik i en tabell. Dubbletter och kopior får inte förekomma. Ett vanligt exempel på en primärnyckel är ett ID i en tabell som automatiskt räknar uppåt när nya rader med data läggs till. Om man ska ha ett personnummer i en databas så passar personnumret utmärkt som en primärnyckel eftersom det ska vara unikt. Detta är bra så att man inte råkar fylla i ett som redan finns.


När ska man använda InnoDB och MyISAM?
Kortfattat
Om du har en t.ex en hemsida med en databas som innehåller en tabell som kommer att uppdateras och ändras kontinuerligt och väldigt ofta, då passar InnoDB. Speciellt om du har flera tabeller som är relaterade till varandra. Då kan InnoDB säga till när det blir fel och hjälpa till med uppdatering i andra tabeller. InnoDB är långsammare när det gäller SELECT och ändringar.

MyISAM ska man helst använda om det sällan sker INSERT, UPDATE och DELETE i tabellerna. Alltså om det sker mycket SELECT. MyISAM är snabbast men är också enklast att arbeta med.


Det bästa scenariot är...
Om man kan köra två databaser som master och slave med replikering. Då kan en av dem innehålla tabeller med InnoDB som håller koll på all integritet, och den andra har kopior av alla tabeller från den första fast med MyISAM istället för InnoDB. När data ska hämtas så anropas den andra med MyISAM. När data ska läggas till, uppdateras eller tas bort så anropas den första. Då får man det bästa av två världar - nja två olika tekniker i alla fall.


Nu ett exempel med InnoDB

Exempel 1
Beskrivning: Vi kommer ha en tabell där vi lagrar information om kategorier för produkter som säljs på en hemsida. Observera att detta exempel inte kommer fungera med MyISAM.

Skapa först en databas. Skapa sedan nedanstående tabeller.

CREATE TABLE tbl_products(
product_id INT UNSIGNED NOT NULL,
product_name VARCHAR(20),
PRIMARY KEY(product_id)
) ENGINE=InnoDB;
Detta är tabellen med produkter som sedan ska kopplas till kategorier.


CREATE TABLE tbl_categories(
category_id INT UNSIGNED NOT NULL,
category_name VARCHAR(20),
PRIMARY KEY(category_id)
) ENGINE=InnoDB;
Detta är tabellen med kategorier. Tabellerna ovanför beskriver inte hur de är relaterade med varandra. För det behöver vi ännu en tabell.

CREATE TABLE tbl_categories_products(
category_id INT UNSIGNED NOT NULL,
product_id INT UNSIGNED NOT NULL,
PRIMARY KEY(product_id, category_id),
FOREIGN KEY (category_id) REFERENCES tbl_categories(category_id),
FOREIGN KEY (product_id) REFERENCES tbl_products(product_id)
) ENGINE=InnoDB;


Nu kan vi se på bilden här nedanför hur relationen mellan tabellerna ser ut.

(Bild 1) Relation mellan tabeller produkter och kategorier

Lägga till lite data till tabellerna. Här lägger vi till några produkter:
INSERT INTO tbl_products(product_id, product_name)
VALUES
(1, 'MP3 spelare'),
(2, 'iPod'),
(3, 'iPad'),
(4, 'Dell Dimension 1111 PC'),
(5, 'PHP och MySQL Handboken'),
(6, 'Bäverdalen'),
(7, 'Samsung Galaxy Tab')


Lägg till några kategorier för produkterna:
INSERT INTO tbl_categories(category_id, category_name)
VALUES
(1, 'Musikspelare'),
(2, 'Läsplattor'),
(3, 'PC'),
(4, 'Böcker')


Skapa relationer mellan kategorier och produkter:
INSERT INTO tbl_categories_products(category_id, product_id)
VALUES
(1, 1),
(1, 2),
(2, 3),
(3, 4),
(4, 5),
(4, 6),
(2, 7)


Försök att lista ut själv hur relationen är uppbyggd. Första kolumnen är vilken kategori som den andra kolumnen tillhör. T.ex "PHP och MySQL Handboken" tillhör kategori nr 4 vilket är "Böcker".

Resultat
Nu måste utvecklaren och alla mjukvaror som tänker använda tabellerna tänka på att kontrollera integriteten själva genom att uppdatera alla tabeller som ändras för varje SQL-fråga till databasen. ID numren måste stämma överens annars får man ett felmeddelande av databasen. Så om jag nu skulle råka fylla i data (en post) i tabellen tbl_categories_products med följande SQL-fråga, så skulle jag få ett felmeddelande eftersom kategori ID-numret inte finns i tabellen tbl_categories.

INSERT INTO tbl_categories_products(category_id, product_id) VALUES (8, 2)



Exempel för MyISAM
Tyvärr har jag inte några exempel för tabeller som har MyISAM men jag vet att det fungerar genom att skapa sk Triggers. Läs gärna referensen [1] för att läsa mer.


Vad händer om man vill ändra ett ID-nummer i tabellen för kategorier?
Då blir det fel. Man måste ändra i båda tabellerna samtidigt har jag för mig. Men det problemet kan vi lösa i kommande text och exempel.


Cascade för "delete" och "update"
Med nyckelordet "Cascade" kan man tillåta att InnoDB själv ska ha kontroll över alla tabellerna automatiskt. Säg nu att jag vill byta ut ID-numret för kategorin "Läsplattor" till ID 17, då kan jag uppdatera numret för category_id i tabellen tbl_categories och ändringen sker även automatiskt i tabellen tbl_categories_products eftersom den är relaterad till category_id och måste vara likadan. Ändras en tabell så måste den andra tabellen också ändras.

Detsamma gäller när en rad tas bort. Om jag känner för att ta bort hela kategorin "Böcker" (ID nr 4) så kommer raden/raderna i tabellen tbl_categories_products med category_id = 4 att också tas bort.

Hur gör man då detta... man kan använda Cascade när man skapar en främmande nyckel. Nu kommer jag visa med ett exempel hur man gör. Man kan använda CREATE TABLE och ALTER TABLE för att ändra i efterhand. Jag kommer visa hur man gör via CREATE TABLE.

CREATE TABLE tbl_categories_products(
category_id INT UNSIGNED NOT NULL,
product_id INT UNSIGNED NOT NULL,
PRIMARY KEY(product_id, category_id),
FOREIGN KEY (category_id) REFERENCES tbl_categories(category_id) ON UPDATE CASCADE ON DELETE CASCADE,
FOREIGN KEY (product_id) REFERENCES tbl_products(product_id) ON UPDATE CASCADE ON DELETE CASCADE
) ENGINE=InnoDB;


Detta betyder nu att tabellen övervakar de främmande nycklarna i de främmande tabellerna tbl_categories och tbl_products.

Om du nu testar att köra följande SQL-fråga så kan du se att två tabeller uppdateras. Den ena som du valde och den andra som har en relation med den du valde.

UPDATE tbl_categories SET category_id = 14 WHERE category_id = 2

Kontrollera tabellerna

SELECT * FROM tbl_categories
SELECT * FROM tbl_products
SELECT * FROM tbl_categories_products (har ändrat sitt category_id som var 2 automatiskt till 14)

Det borde se ut ungefär så här nu i tabellen tbl_categories:
+-------------+---------------+
| category_id | category_name |
+-------------+---------------+
| 1 | Musikspelare |
+-------------+---------------+
| 14 | Läsplattor |
+-------------+---------------+
| 3 | PC |
+-------------+---------------+
| 4 | Böcker |
+-------------+---------------+

tbl_categories_products:
+-------------+------------+
| category_id | product_id |
+-------------+------------+
| 1 | 1 |
+-------------+------------+
| 1 | 2 |
+-------------+------------+
| 14 | 3 |
+-------------+------------+
| 3 | 4 |
+-------------+------------+
| 4 | 5 |
+-------------+------------+
| 4 | 6 |
+-------------+------------+
| 14 | 7 |
+-------------+------------+


Slutsats
Slutsatsen med detta testet är att jag nu kommer överväga att använda InnoDB för mer kritiska applikationer där det sker många ändringar i databasen. Om jag kör detta system på en hemsida kommer jag att köra cachelagring av all data så behöver data bara hämtas en gång med SELECT från databasen och resten sparas i textfiler.

Det kommer också bli svårare att designa sin databas så jag får planera bättre i framtiden exakt vilka tabeller jag vill använda och hur man eventuellt kan uppdatera databasen i framtiden för att minska problem och fel så mycket som möjligt.

Nu behöver jag bara uppdatera en tabell och behöver inte tänka på vilka andra tabeller som är indirekt relaterade till tabellen genom "osynliga" relationer. Med detta menar jag att jag alltid innan har skrivit applikationer som själva måste hålla reda på att ändra i t.ex tabellen tbl_categories_products så fort jag uppdaterar ett kategori ID eller tar bort en kategori.

Ett bra scenario är kommentarer som är kopplade till ett blogginlägg. Tar man bort blogginlägget så ska alla tillhörande kommentarer tas bort automatiskt utan att jag som programmerare behöver tänkta på att skriva kod som måste utföra det manuellt. Nu sköts allt i databasen och koden blir mer abstract och enklare att underhålla.

Slutord
Det var allt för den här gången. Jag hoppas att artikeln har varit till någon nytta för er.

Mvh
Waschman


Referenser
[1] http://dev.mysql.com/tech-resources/articles/mysql-enforcing-foreign-keys.html
[2] http://blogs.innodb.com/wp/2010/09/mysql-5-5-innodb-as-default-storage-engine/

24 mars, 2010

PHP/MySQL: Konvertera från datetime till sekunder från epoch

English translation:MySQL and PHP Convert datetime to seconds

Undrar du hur man kan omvandla data från en kolumn i MySQL med datetime som datatyp till antalet sekunder från "epoch" (1970-01-01)? Det undrade jag och nu tänker jag dela med mig av lösningen.

Jag gillar att programmera med PHP och utveckla dynamiska hemsidor tillsammans med MySQL som backbone. Just nu för en liten stund sedan letade jag efter en lösning för att omvandla datetime till sekunder för att enklare formatera datum med PHP funktionen date().

Notis:
Jag vet att det finns utmärkta lösningar inbyggda i MySQL men i koden jag använder nu går det inte att lösa på det sättet. Det datum som returneras från databasen är alltid i formatet yy-mm-dd tt:mm:ss

<?php
echo strtotime('2010-03-24 12:26:00') .'<br/>';
echo strtotime('2010-03-24 12:27:00') .'<br/>';

// Resultat
// 1269458760
// 1269458820

// Verifiera att det fungerar
echo date('Y-m-d H:i:s', strtotime('2010-03-24 12:27:00') ) .'<br/>';

// Resultat
// 2010-03-24 12:27:00

// Ett annat format
echo date('l F j, Y, G:i', strtotime('2010-03-24 12:27:00'));

// Resultat
// Wednesday March 24, 2010, 12:27
?>

Men för er som verkligen vill lösa det på MySQL-viset kommer här ett exempel:

// Skriver ut 1269458820
SELECT UNIX_TIMESTAMP('2010-03-24 12:27:00')

Ganska enkelt eller hur? Vill ni veta mer om funktionen strtotime() [1] i PHP så hittar ni information i den grymma dokumentationen på www.php.net [2]

Lycka till med programmeringen

Referenser
[1] www.php.net/manual/en/function.strtotime.php
[2] www.php.net

22 april, 2009

Ubuntu/PHP/Apache: Sätta upp webbserver i Linux Ubuntu

Detta är mest ett tips för mig själv för att jag inte skall glömma bort var jag fann denna fantastiska guide [1]. Guiden går igenom om hur man sätter upp Apache, PHP, MySQL i ett Ubuntu system. Jag fann guiden via Netbeans och jag tror även att det går att använda Netbeans IDE på Ubuntu men är inte riktigt säker.

Om det går så har man en bra PHP-editor tillgodo eftersom Netbeans har det stödet inbyggt i senare versioner.

Framtiden
Inom kort kommer jag dokumentera exakt hur man installerar en webbserver med mod_rewrite, gd2 och en MySQL-databas i Ubuntu.

Källor
[1] Configuring the PHP development environment in Linux Ubuntu

02 mars, 2008

Nätverk/Server: Sätta upp egen server #2

Förord
Den 13 Juli 2006 publicerade jag en artikel om hur man sätter upp en egen server på sin Windows XP dator. Då talade jag bara Apache 2.2 och PHP 5.1.4. Nu är det dags för en uppdatering som är extremt

förenklad jämfört med min förra artikel. Istället kommer jag nu skriva om senaste Apache, MySQL och PHP. Jag kommer fortfarande gå igenom hur man gör för Windows XP men i en senare artikel kommer jag kanske

gå igenom hur man sätter upp en linux server - som drar otroligt mindre resurser än en Windows "box".

Introduktion
I denna artikeln tänker jag gå igenom hur man sätter upp en webbserver (Apache 2.2.8), en databasserver (MySQL 5.0.51a x86) och skriptspråket PHP 5.2.5 på Windows XP. Vi konfigurerar allt manuellt.

Att tänka på
Man behöver inte konfigurera allt manuellt eftersom det redan finns färdiga "paket" att ladda ner. Ett sådant paket är XAMPP som även finns tillgängligt för Linux, Windows,

Mac OS X och Solaris. XAMPP hittar ni hos
Apache Friends - XAMPP. Men det är ju

så mycket roligare att göra det själv plus att man då har mer kontroll över programmen och filerna. Det är enligt mitt tycke förstås.


Observera att jag inte tänker gå igenom säkerhet eller optimering för flera användare etc. Det får ni själva Googla efter.

Ladda ner programvaran
Apache 2.2.8 kan ni ladda ner här (utan SSL stöd) - x86
PHP 5.2.5 kan ni ladda ner här (klicka på den spegel-länk/mirror ni vill använda)
MySQL 5 (x86) kan ni ladda ner här

Följ mina instruktioner här nedanför för bilderna:

Installera Apache 2.2.8



















Installera MySQL 5













Konfigurera MySQL 5 (grunder och en root-användare)



















Här väljer vi ett lösenord för "root" kontot - det är det konto som har full kontroll över databasen. Vi väljer även att man ska kunna komma åt servern från en fjärrdator.


Påbörja konfigurationen med de inställningar vi har ställt in hittills.




Installera PHP 5.2.5

(Klicka på bilden för att förstora) Filen här ovan kan ni packa upp med vilket program som helst som klarar att öppna ZIP-formatet. Packa upp paketet till sökvägen C:\php5_2_5 som ni ser i nästa bild.


(Klicka på bilden för att förstora)

Konfigurera PHP 5.2.5 och MySQL 5 för ihopkoppling

Kopiera filen här ovanför för nästa steg

Klista in libmySQL.dll i katalogen C:\Windows



För er som inte förstår figuren kan jag tala om att man ska kopiera filen php.ini-recommended till samma katalog fast med namnet php.ini istället.

Den nya filen konfigurerar vi här nedanför.


Visa felmeddelanden som PHP skickar till oss


Sätt katalogen för alla tillägg


Aktivera tilläggen: php_mysql.dll, php_mysqli.dll och php_pdo_mysql.dll

Spara och så är konfigurationen för PHP klar. Det finns mycket mer man kan göra men det vi har gjort hittills räcker gott och väl. Om det är någon som har ett förslag på ändringar får ni gärna skicka en kommentar till artikeln.


Konfigurera Apache 2.2.8
Nu ska vi konfigurera Apache, vilket är mjukvaran för vår webbserver. Dess konfiguration finns lagrad i en fil vid namn "httpd.conf" som man hittar med följande sökväg: C:\Apache2.2\conf\httpd.conf".


Här ovan använder vi en PHP-modul istället för CGI-versionen (php-cgi.exe). Det är säkrare och ger bättre prestanda har jag för mig, samt att det är rekommenderat av nästan alla tekniker.


Ändra sökvägen till katalogen där vi kan lägga alla våra webbsidor



Här får ni välja vilket av följande två rödmarkerade alternativ ni vill konfigurera.

Följande tillåter endast anslutningar från din dator till webbservern


Tillåt anslutningar från alla destinationer för åtkomst till webbservern



DirectoryIndex här ovanför bestämmer i vilken ordning som filerna ska kontrolleras om en katalog innehåller en index-fil. I detta fallet vill vi att en fil som heter "index.php" ska köras även om det redan finns en fil som heter "index.html". Denna fil körs automatiskt när vi besöker en katalog på servern (i sökvägen för katalogen "www") där en sådan fil existerar.

Spara och konfigurationen för webbservern ska vara färdig. Men först innan vi fortsätter måste vi starta om webbservern. Detta kan göras via Apaches egna kontrollpanel som ligger längst ner till höger vi klockan. Ikonen är en rund vit cirkel med en grön pil. Högerklicka på den och välj "Open Apache Monitor". Väl där markerar ni "Apache2.2" i listan och klickar på knappen "Restart" till höger.
Man kan också starta om webbservern via startmenyn > Alla program > Apache HTTP Server 2.2 > Control Apache Server > Restart
Nu återstår bara att testa om det fungerar.

Det slutliga testet

Katalogen "www" här ovan måste ni själva skapa.


Skapa två filer som vi kommer använda i följande steg för att testa och verifiera installationen.




Ett helt vanligt textdokument som vi kommer åt via http://localhost/test.txt


Ett simpelt test-skript i PHP som visar information om installationen.

Resultatet för PHP-installationen

(Klicka på bilden för att förstora)
Via den sida som nu visas av PHP kan man avläsa viktiga inställningar och systemsökvägar samt diverse miljövariabler. Säkerhetsrisk: Om ni använder er webbserver för produktion så att den är tillgänglig ute på Internet så bör ni ta bort denna fil, eller låsa åtkomsten med ett lösenord. Detta för att den kan innehålla känslig information som ej bör läsas av ovälkomna gäster.

Här kan ni observera att MySQL och MySQLi är rätt konfigurerat

(Klicka på bilden för att förstora)
Tillägg: MySQLi är en förbättrad (Improved) version av MySQL och ger även utvecklaren tillgång till något som kallas för "Prepared statements". Det är en teknik som försvårar en intrångsteknik som kallas "SQL Injection". Detta är bara en liten del av alla förbättringar som MySQLi erbjuder.

Ett litet testskript i PHP för att verkligen testa att MySQL fungerar som det ska (åtminstone att funktionerna existerar och finns tillgängliga.



Jippi!!!


Slutord
Så där! Äntligen var det färdigt. Nu hoppas jag att det inte är några där ute som får problem med en manuell installation av en webbserver tillsammans med MySQL och PHP.

Observera att jag inte har implementerat någon säkerhet och för MySQL finns ännu bara ett "root" konto för total åtkomst. Ni ska helst skapa ett extra användarkonto i MySQL med kommandoradsverktyget som medföljer för att göra åtkomsten till databasen lite säkrare.

Viktig information: Denna installation bör ej användas för produktion - den är endast till för utveckling och test av system.

Lycka till!

Välkomna till bloggen

Välkomna ska ni vara kära besökare. Jag skriver om IT för att det är kul och för att jag vill dela med mig av information och kunskap. Jag försöker hålla bloggen så kategoriserad som möjligt för att ni enklare ska hitta intressanta länkar och artiklar.