Avdeling for informatikk og e-læring, Høgskolen i Sør-Trøndelag Leksjon :MySQL - funksjoner Kjell Toft Hansen - revidert for MySQL av Tore Mallaug 27.02.2013 Lærestoffet er utviklet for faget Databaser 2 1. Funksjoner I denne leksjonen skal se på hvordan vi bruker innebygde og brukerdefinerte funksjoner. Innhold 1.1. INNLEDNING... 1 1.2. INNEBYGDE FUNKSJONER... 1 1.2.1. Numeriske funksjoner... 2 1.2.2. Tekstfunksjoner... 2 1.2.3. Datofunksjoner... 4 1.2.4. Konverteringsfunksjoner... 4 1.2.5. Funksjonen CASE... 4 1.3. BRUKERDEFINERTE FUNKSJONER... 5 1.3.1. Syntaks og eksempel... 5 1.3.2. Tips til struktur... 6 1.3.3. Deterministisk funksjon... 7 1.4. LITTERATUR SOM ER BRUKT... 7 1.1. Innledning En funksjon i SQL er en grunnleggende SQL-komponent som applikasjoner kan bruke gjennom SQL-spørringer. ANSI/ISO standarden for SQL definerer mange grunnleggende innebygde SQL funksjoner som en del av språket. Relasjonsdatabasesystemer som MySQL tilbyr også egne tilleggsfunksjoner. Disse innebygde funksjonene kan være et alternativ til programkode i (tjener-)applikasjoner. 1.2. Innebygde funksjoner I en klient/tjener-arkitektur 1 vil et spørsmål være hvilke applikasjoner (tjenere og klienter) som skal ta seg av prosesseringen hvilke funksjonalitet i det totale info.systemet, eller hvilke maskiner som skal prosessere funksjonene om du vil. Tradisjonelt vil SQL-spørringer kjøres på databasetjeneren. Jo mer som kan utføres i SQL, jo mindre datatrafikk (slipper å sende 1 Kap.9 i Databaser-boka for en generell oversikt over mulige klient/tjener-løsninger for databaser.
MySQL - funksjoner side 2 av 7 unødvendig data fra databasetjeneren) og prosessering trengs ute på andre tjenere (f.eks. webtjenere) og klienter (applikasjoner). Vi skal under se på noen gode eksempler på funksjoner som kan være nyttige i spørringer. 1.2.1. Numeriske funksjoner Numeriske funksjoner er redskap for manipulering av matematiske uttrykk og returnerer numeriske verdier. Noen av de mest vanlige funksjoner er COUNT, AVG, SUM, MAX og MIN. Under har vi et eksempel hvor vi bruker den numeriske funksjonen ROUND. Den runder av en numerisk verdi og fjerner desimaler. SELECT delnr, pris, ROUND(pris) avrundet_pris FROM prisinfo ORDER BY pris; Spørringens resultattabell blir: DELNR PRIS AVRUNDET_PRIS 51173,35 0 51173,44 0 51173,57 1 1909,85 1 202 1,5 2 202 1,5 2 201 1,6 2 202 1,76 2 201 1,9 2 201 2,6 3 1909 3 3 202 6,5 7 51200 7,35 7 1 120 120 1 219,99 220 4 550 550 4 899 899 3 1050 1050 3 1199 1199 3 1299 1299 1.2.2. Tekstfunksjoner Tekstfunksjoner opererer på tekstverdier som skal legges inn i tabellene og på spørringer. Avhengig av hvilken type funksjon, så vil vi få forskjellig typer resultatverdier. Her følger et eksempel på bruken av funksjonen UPPER, som returnerer store bokstaver. SELECT UPPER(beskrivelse) stor_bokstav FROM delinfo; Resultattabellen av spørringen blir da: ST OR_BOKST AV
MySQL - funksjoner side 3 av 7 BINDERS KONTORSTOL LINJALSETT PULT SKRIVEBORD SKRIVEUNDERLAG SVARTE KULEPENNER GULE KULEPENNER Funksjonen CONCAT trekker sammen tekst fra ulike kolonner. Funksjonen IFNULL (NVL i Oracle) gir oss muligheten til å få ut en kommentar hvor verdien i tabellen har NULL verdi IFNULL er et eksempel på en sammenligningsfunksjon, dvs. funksjoner som sammenligner 2 eller flere verdier. En annen slik funksjon er SUBSTR - se senere. Eksemplet som følger viser bruken av begge funksjonene. SELECT UPPER (CONCAT(CONCAT(adresse,' '),levby)) adresse, UPPER(IFNULL(fylke,'fylke mangler')) fylke FROM levinfo; Det er også funksjoner som manipulerer en delstreng. Funksjonen TRIM fjerner uønskete tegn fra en tekststreng. I eksempelet under ønsker vi å fjerne endingen «er» fra beskrivelsen til en del med del nummer 202. SELECT delnr, TRIM(TRAILING 'er' FROM beskrivelse) beskrivelse FROM delinfo WHERE delnr = 202; Resultattabellen av spørringen blir: DELNR BESKRIVELSE 202 Gule kulepenn En annen tekststrengfunksjon er SUBSTR. Den kutter kolonnebredden i resultattabellen. I tabellen Delinfo har vi satt av plass til 30 tegn i kolonnen beskrivelse. Den lengste tekststrengen som er lagt inn er på 15 tegn. Mao så vil resultattabellen sette av plass til 15 tomme tegn hvis vi ikke bruker SUBSTR. SELECT delnr, SUBSTR(beskrivelse, 1, 15) beskrivelse FROM delinfo; Resultattabellen blir: DELNR 51173 Binders BESKRIVELSE 1 Kontorstol 51200 Linjalsett 3 Pult 4 Skrivebord 1909 Skriveunderlag 201 Svarte kulepenn 202 Gule kulepenner 8 rows returned
MySQL - funksjoner side 4 av 7 1.2.3. Datofunksjoner Datofunksjoner brukes ved uttrykk som behandler tid. Under følger et eksempel på bruken av funksjonene CURDATE (alternativt CURRENT_DATE) og LAST_DATE. CURDATE gir dagens dato og LAST_DATE gir siste dag i den måneden. SELECT CURDATE()dagens_dato, LAST_DAY(CURDATE()) siste_dato, LAST_DAY(CURDATE())- CURDATE() dager_igjen; Resultattabellen etter kjøring av spørringen blir: DAGENS_DATO SIST E_DATO DAGER_IGJEN 2012-09-05 2012-09-30 25 I resultattabellen over er datoformatet standard amerikansk med årstallet først. Det er mulig å skrive ut datoer som en streng ved å bruke funksjonen DATE_FORMAT sammen med "specifiers". PS! DATE_FORMAT konverterer datoformatet til en tekststreng. F.eks. SELECT DATE_FORMAT(CURDATE(),'%d.%m.%y') dagens_dato; DAGENS_DATO 05.09.12 Følgende spørring kan brukes f.eks. til å opprette et utsnitt (eng. view) som kan hjelpe programutviklere til å finne riktig start- og siste dag i en spesifikk måned: SELECT DATE_FORMAT(DATE_ADD(CURDATE(),INTERVAL -1 MONTH),'%Y-%m-01') første_dag_siste_måned, LAST_DAY(DATE_ADD(CURDATE(),INTERVAL -1 MONTH)) siste_dag_siste_måned, DATE_FORMAT(CURDATE(),'%Y-%m-01') første_dag_i_inneværende_måned, LAST_DAY(CURDATE()) siste_dag_i_inneværende_måned; Når vi kjører spørringen får vi følgende resultattabell: FØRSTE_DAG_SISTE_ MÅNED SIST E_DAG_SISTE_ MÅNED FØRSTE_DAG_I_INNEVÆRENDE _MÅNED 2012-08-01 2012-08-31 2012-09-01 2012-09-30 SIST E_DAG_I_INNEVÆRENDE _MÅNED 1.2.4. Konverteringsfunksjoner DATE_FORMAT for å konvertere en date til en streng er vist tidligere. I eksempelet under konverterer vi numeriske verdier til tekstverdier ved bruk av CAST. SELECT pris, CAST(pris AS CHAR(10)) tekststreng FROM prisinfo ORDER BY pris; Vi forenkler litt her å sier at verdien i en pris ikke trenger mer enn 10 tegn. 1.2.5. Funksjonen CASE CASE er et eksempel på en sammenligningsfunksjon. CASE er et nyttig redskap når vi har behov for å gruppere data. Syntaksen ser ut som følger:
MySQL - funksjoner side 5 av 7 case when betingelse 1 then uttrykk 1 when betingelse 2 then uttrykk 2 [else] uttrykk 2a end La oss se på et eksempel. Vi ønsker å skrive ut antall leverandører gruppert på postnummer mellom 0 og 2999 og mellom 3000 og 9999. SELECT SUM(CASE WHEN postnr between 0 and 2999 then 1 else 0 end) as "0 til 2999", SUM(CASE WHEN postnr between 3000 and 9999 then 1 else 0 end) as "3000 til 9999" FROM levinfo; Resultattabellen etter spørringen er utført, blir som følger: 0 til 2999 1 5 3000 til 9999 Funksjonen SUM blir brukt for hver gruppering av data. CASE blir deretter plassert på innsiden av summeringsfunksjonen. Hvis et postnr tilfredsstiller betingelsen i WHENsetningen, så blir verdien 1 lagt til. Hvis postnummeret ikke tilfredsstiller betingelsen, så blir verdien 0 lagt til. 1.3. Brukerdefinerte funksjoner MySQL gir også muligheten til å opprette såkalte brukerdefinerte funksjoner. Slike funksjoner er svært lik lagrete prosedyrer i syntaks og struktur, bortsett fra at en funksjon må returnere en verdi. En funksjon kan ha ingen eller flere parametere og en setning som returnerer en verdi. Datatypen til returverdien må deklareres i funksjonens hode. En funksjon brukes ikke alene, men i sammenheng med en SELECT-setning, blokk, prosedyre eller trigger. Brukerdefinerte funksjoner kan i prinsippet brukes på samme måte som innebygde aggregat-funksjoner som SUM(), AVD(), COUNT() m.fl. Dvs. de kan brukes inne i SELECT-setninger. Men ytelsen til prosesseringen av egendefinerte funksjoner inne i MySQL er ikke vurdert i denne leksjonen (dette bør vurderes hvis en har en veldig stor database). Funksjonene kan også brukes i lagrede prosedyrer (dette er ikke vist i "MySQLutgaven" av denne leksjonen. Se evt. "Oracle-utgaven"). 1.3.1. Syntaks og eksempel Syntaksen til en brukerdefinert funksjon ser slik ut: CREATE FUNCTION <funksjonsnavn> (parameterliste) RETURNS datatype [LANGUAGE SQL] [ {DETERMINISTIC NOT DETERMINISTIC} ] [ {CONTAINS SQL NO SQL MODIFIES SQL DATA READS SQL DATA} ] [ SQL SECURITY {DEFINER INVOKER} ] [ COMMENT comment ] BEGIN hovedprogram RETURN (returverdi); END;
MySQL - funksjoner side 6 av 7 Kommandoer som står i klammeparentes [ ] er frivillige. Legg merke til forskjellen på RETURNS (definerer datatypen til verdien som returneres fra funksjonen) og RETURN (returnerer en verdi (variabel) med samme datatype som RETURNS definerer). La oss lage en funksjon som finner hvor mange deler som er lagt inn i tabellen delinfo: delimiter // CREATE FUNCTION hvor_mange_deler() RETURNS INT READS SQL DATA BEGIN DECLARE antall INT; SELECT count(*) INTO antall FROM delinfo; RETURN(antall); END // delimiter ; Funksjonens navn ble lagret lokalt. For å teste om funksjonen fungerer, skriver vi spørringen: SELECT hvor_mange_deler(); Resultattabellen av spørringen blir: HVOR_MANGE_DELER 8 En enklere måte å skrive funksjonen (uten BEGIN..END) kan være: CREATE FUNCTION hvor_mange_deler() RETURNS INT READS SQL DATA RETURN (SELECT count(*) FROM delinfo); For å slette funksjonen fra databasen i MySQL kan denne kommandoen brukes: DROP FUNCTION hvor_mange_deler; 1.3.2. Tips til struktur Følgende liste representerer anbefalinger med hensyn til funksjonsstrukturen: Bruk helst ikke OUT eller IN OUT i funksjonens parameterliste. Alle data som skal returneres må deklareres i funksjonens RETURN-setning. Lag bare én RETURN-setning i den delen av funksjonen som skal kjøres, og den skal komme helt til slutt. Hvis funksjonen skal returnere flere verdier, så bruk en sammensatt datatype (eng. record, object, collection) eller bruk OUT eller IN OUT i argumentet.
MySQL - funksjoner side 7 av 7 1.3.3. Deterministisk funksjon En deterministisk funksjon er en funksjon som alltid returnerer samme svar forutsatt samme innverdier. Et veldig basis eksempel: CREATE FUNCTION hello (s CHAR(20)) RETURNS CHAR(50) DETERMINISTIC RETURN CONCAT('Hello, ',s,'!'); 1.4. Litteratur som er brukt MySQL - Fourth Edition av Paul DuBois. Using MySql Stored Functions. URL: http://www.toadworld.com/twpipelinemarch2008/pipemarch08mysql/tabid/308/default.aspx