Syntax
Oftast när man skriver kod i SQL brukar det bara vara korta kommandon som avslutas med ett semikolon. Detta betyder att SQL är designat på ett sätt som skiljer sig från de flesta traditionella programmeringsspråk. Exempelvis gör SQL ingen skillnad på gemener och versaler. Det betyder att man kan skriva variabeln username
som userName
, USERNAME
, uSeRnaME
, eller vilken kombination av vilka små och stora bokstäver som helst. Det kommer tolkas likadant som username
i alla fall.
SQL bryr sig inte heller om hur mycket whitespace (mellanslag, enterslag, tab, etc) som du använder dig av, så länge varje ord är separerat med minst ett whitespace. Nedanför har du tre exempel på ekvivalenta SQL-kommando. Texten som följer två bindestreck är en kommentar, ej kod.
-- Exempel 1
select username from users where age > 40;
-- Exempel 2
SELECT username
FROM users
WHERE age > 40;
-- Exempel 3
SeLeCT useRNAme
frOm USERS
WHEre agE >
40
;
Vi kommer att använda oss av stilen i exempel 2.
Exakt vad koden gör tar vi upp i senare kapitel, men för att göra koden så tydlig som möjligt kommer vi använda oss av ett par konventioner som underlättar läsandet av koden:
Vi använder stora bokstäver för SQL-nyckelord (exempelvis
SELECT
ellerFROM
).Vi använd små bokstäver för attribut och tabeller (exempelvis
username
,age
,users
ellertweets
).Vi bryter hellre upp kod i flera rader än att skriva alltför långa rader. Detta får man själv göra en bedömning av medan man skriver men en tumregel är att undvika rader som är över 80 karaktärer lång. Dock finns det undantag.
Det är viktigt att skriva kod som går att läsa. Skriv som om personen som måste läsa er kod har kort stubin och vet var ni bor.
Datatyper
Alla värden i en relationalsdatabas måste bestå av någon fundamental datatyp. Det finns många olika datatyper men man klarar sig långt på enbart ett få. Här är en kort lista av de vanligaste datatyperna som vi kommer använda oss av i resten av kursen.
INTEGER
: Ett heltal.REAL
: Ett decimaltal (exempelvis 0.1)CHAR(n)
: En n lång sträng av karaktärer, varken längre eller kortare. Man kan ha kortare strängar men de blir vadderade med struntvärden för att skapa en n lång sträng. Om man bara skriverCHAR
så är det ekvivalent somCHAR(1)
.TEXT
: En sträng av obestämd längd.VARCHAR(n)
: En sträng av karaktärer som är upp till n lång, men kan vara kortare. Att bara skrivaVARCHAR
är ekvivalent somTEXT
.BOOL
: Ett sant eller falskt värde.TIME
: En tidpunkt. Detta kan ha många olika format men vi kommer använda oss av 'hh:mm:ss', exempelvis '13:19:22'.DATE
: Ett datum. Detta kan ha många olika format men vi kommer använda oss av 'yyyy-mm-dd', exempelvis '2017-12-24'.TIMESTAMP
: BådeTIME
ochDATE
. Vi kommer använda oss av formatet 'yyyy-mm-dd hh:mm:ss', exempelvis '2012-01-08 08:13:37'.NULL
: Avsaknaden av data.
För den som är intresserad i fler datatyper finns de här.
Villkor
Beroende på vilka datatyper man hanterar för tillfället finns olika sorters villkor man kan testa. SQL stödjer de vanliga matematiska operatorerna för att jämföra olika datatyper:
<
: mindre än>
: större än<=
: mindre eller lika med>=
: större eller lika med=
: lika med<>
eller!=
: skiljt från (inte lika med)
Notera här en viktig skillnad från de flesta programmeringsspråk, nämligen att likhet testas med ett enkelt likhetstecken istället för dubbla. I SQL kan du inte tilldela värden med =
. Det kan också vara viktigt att komma ihåg att skiljt från (inte lika med) kan skrivas <>
, om du skulle läsa exempelkod någon annanstans.
För nummer jämförs, precis som i matematiken, talens storleksordning. För strängar och karaktärer jämförs de efter deras position i alfabetet (lexikografiskt ordning). TIME
, DATE
och DATETIME
jämförs utefter tid, så vi kan avgöra om en tid är före eller efter en annan.
-- Några exempel (detta är inte riktig SQL-kod).
200 > 100 -- Sant
'a' < 'b' -- Sant
'Hello' > 'Cello' -- Sant
'Cello' > 'Cell' -- Sant
'2018-01-05' > '2011-12-12' -- Sant. (Detta är DATE datatyper, inte strängar!)
'12:00:00' < '22:30:55' -- Sant. (Detta är TIME datatyper, inte strängar!)
Vi kan också testa flera villkor samtidigt genom att binda ihop dem med AND
eller OR
. Om vi vill att flera villkor ska vara uppfyllda använder vi AND
och om vi vill endast något av villkoren ska vara uppfyllt använder vi OR
. Vi kan också använda oss av NOT
för att omvandla True
till False
och vice versa.
5 = 5 AND '08:10:35' < '13:13:37' -- Sant.
5 = 5 OR '08:10:35' < '13:13:37' -- Sant.
5 != 5 AND '08:10:35' < '13:13:37' -- Falskt.
5 != 5 OR '08:10:35' < '13:13:37' -- Sant.
NOT 5 = 5 -- Falskt.
NOT 5 != 5 -- Sant.
Det kan vara svårt att se i de exempel ovan vad som är strängar och vad som är tidsdatatyper. Detta är för att tidsdatatyper representeras som en sträng, fast med ett specifikt format. När man skriver kod på riktigt jämför man aldrig konstanter på detta sätt, utan man jämför en variabel med en konstant. Eftersom man vet typen på variabeln kommer man även veta om konstanten behandlas som en sträng eller tidsdatatyp.
BETWEEN
Ett lite snyggare sätt att skriva villkor som tittar om ett tal x är inom ett spann [a, b] (exempelvis x >= a AND x <= b
), är att använda sig av BETWEEN
. Detta fungerar även för strängar och tidsdatatyper. Notera att ändpunkterna är inkluderade.
5 BETWEEN 3 AND 6 -- Sant.
7 BETWEEN 3 AND 6 -- Falskt.
'c' BETWEEN 'a' AND 'd' -- Sant.
5 BETWEEN 5 AND 6 -- Sant.
Vi kan även kontrollera det omvända, det vill säga om ett tal inte är inom ett spann, genom att skriva NOT
framför. Detta är då ekvivalent som x < a OR x > b
.
3 NOT BETWEEN 5 AND 8 -- Sant.
7 NOT BETWEEN 3 AND 6 -- Falskt.
'c' NOT BETWEEN 'a' AND 'd' -- Falskt.
Unknown
I många programmeringsspråk resulterar jämförelser till antingen sant eller falskt, men i SQL kan en jämförelse även resultera i UNKNOWN
. Detta händer om vi försöker jämföra något med ett NULL
värde. Även att jämföra NULL = NULL
kommer också resultera i UNKNOWN
. På grund av detta finns ett par uttryckt som vi kan använda för att få fram ett sant eller falskt värde från ett NULL
värde.
<expression> IS DISTINCT FROM <expression>
: Testar likhet (=
), men behandlarNULL
som ett eget tal.<expression> IS NOT DISTINCT FROM <expression>
: Testar skillnad (!=
), men behandlarNULL
som ett eget tal.<expression> IS NULL
: Testar om expression ärNULL
.<expression> IS NOT NULL
: Testar om expression inte ärNULL
.
<expression>
står i detta fall står för ett uttryck som kan antingen vara ett enda värde eller ett matematiskt uttryck som resulterar i ett värde.
5 IS DISTINCT FROM NULL -- Sant.
NULL IS DISTINCT FROM NULL -- Falskt.
'Hello' IS NOT DISTINCT FROM 'Hello' -- Sant.
10 IS DISTINCT FROM NULL -- Falskt.
Pattern matching
För strängar kan vi använda oss av pattern matching med hjälp av nyckelordet LIKE
. Med det kan vi använda oss av två specialtecken för att jämföra strängar utefter specifika mönster.
%
: Matcha alla sekvenser av noll eller flera tecken_
: Matcha precis ett tecken
'abc' LIKE 'ab_' -- Sant
'abx' LIKE 'ab_' -- Sant
'tbx' LIKE '_b_' -- Sant
'abc' LIKE 'abc_' -- Falskt
'abc' LIKE '%' -- Sant
'abc' LIKE 'a%' -- Sant
'abc' LIKE '%bc' -- Sant
'abc' LIKE 'abc%' -- Sant
'abc' LIKE '%x' -- Falskt
Exercise
Vad kommer följande uttryck resultera i?
TRUE
,FALSE
ellerUNKNOWN
?'Good morning' < 'Good night' '2011-02-08 22:00:20' > '2011-01-08 23:33:54' 1024 != NULL 'Good morning' LIKE 'Good _' 'NULL' IS DISTINCT FROM NULL 500 > 400 AND 400 > 500 'Hello' LIKE 'H_ll_' 'Extraordinary' LIKE '%x%' NULL IS NOT DISTINCT FROM 500
Solution
TRUE
TRUE
UNKNOWN
FALSE
TRUE
FALSE
TRUE
TRUE
FALSE
Exercise
Vilka datatyper bör du använda för dessa attribut?
ålder
födelsedag
förnamn
kod
(med siffror och bokstäver på 4 tecken).
är_student
(sant eller falskt).
Solution
INTEGER
DATE
VARCHAR(255)
(255 är slumpmässigt valt. Så länge talet är stort nog att täcka i princip alla fall är det okej)
CHAR(4)
BOOL