FÖ 4: Databaskursen 1. SQL DDL (Data Definition Language) 2. Skapa tabell 3. Lägga till PK 4. Data Dictionary Views 5. Namn på constraints 6. Lägga till FK 7. Lägga till en kolumn 8. Objektet sekvens 9. Tabellen Dual 10. Ta bort objekt 11. Datatyper 12. Inbyggda funktioner 1 Pär Douhan, pdo@du.se
SQL DDL Förkortningen DDL står för Data Definition Language Används när vi ska skapa, förändra eller ta bort dtb databasobjekt. bjkt Några exempel på databasobjekt är: tabell, procedur, funktion, trigger och sekvens. Objekt 1. Skapa objekt: create 2. Förändra objekt: alter 3. Ta bort objekt: drop 2
Skapa en tabell STUDENT # studnr * fnamn * enamn o mobil STUDENT studnr fnamn enamn mobil create table student( studnr varchar2(10), fnamn varchar2(50) not null, enamn varchar2(50) not null, mobil varchar2(15)); table STUDENT created. 3
Lägga till en PK STUDENT # studnr * fnamn * enamn o mobil Nu ska vi lägga till en primärnyckel kl (PK) till tabellen student. t Vi ser i modellen att kolumnen studnr är markerad med # och ska alltså vara tabellens primärnyckel. Vi kan göra detta direkt när vi skapar tabellen, men jag föredrar att göra det efteråt. Vi använder alter för att göra detta: alter table student add primary key(studnr); table STUDENT alterd. Undrar vilket namn vår PK fick? Vi kan ta reda på det genom att söka i Data Dictionary. 4
Data Dictionary Data Dictionary En databas innehåller alltid en beskrivning av lagrad information. Denna brukar kallas för Data Dictionary. Ibland även för metadatabasen. I Oracle finns det flera olika data dictionary views. Dessa ligger i ett tablespace som heter system. 5
Data Dictionary Views Data t dictionary diti views, även kända somcatalog tl views, låter oss övervaka databasens tillstånd i realtid: Data 1. Vyerna USER, ALL, och DBA, innehåller Dictionary information om schemaobjekt som är tillgängliga på olika behörighetsnivåer 2. De s.k. V$ vyerna innehåller information om databasens prestanda. Vi kan tex t.ex. se hur mycket minne databasens olika sessioner konsumerar etc. Via dessa vyer kan vi söka fram metadata om alla objekt och olika tillstånd i databasen. Vi hittar alla vyer och mycket mer på ss64: http://ss64.com 6
Söka i Data Dictionary STUDENT # studnr * fnamn * enamn o mobil desc user_ constraints; Name Null Type OWNER VARCHAR2(128) CONSTRAINT_NAME VARCHAR2(128) CONSTRAINT_TYPE VARCHAR2(1) TABLE_NAME VARCHAR2(128) SEARCH_CONDITION LONG() SEARCH_CONDITION_VC VARCHAR2(4000) R_OWNER VARCHAR2(128) R_CONSTRAINT_NAME VARCHAR2(128) DELETE_RULE VARCHAR2(9) STATUS VARCHAR2(8) DEFERRABLE VARCHAR2(14) DEFERRED VARCHAR2(9) VALIDATED VARCHAR2(13) GENERATED VARCHAR2(14) BAD VARCHAR2(3) RELY VARCHAR2(4) LAST_CHANGE DATE INDEX_OWNER VARCHAR2(128) INDEX_NAME VARCHAR2(128) INVALID VARCHAR2(7) VIEW_RELATED VARCHAR2(14) ORIGIN_CON_ID NUMBER 7
Söka i Data Dictionary STUDENT # studnr * fnamn * enamn o mobil select constraint_name,constraint_type from user_constraints where table_name = 'STUDENT'; -- OBS! Stora bokstäver CONSTRAINT_NAME CONSTRAINT_TYPE ------------------------------- --------------- SYS_C0010189 P SYS_C0010187 C SYS_C0010188 C CONSTRAINT_TYPE (from 12c docs) C Check constraint on a table P Primary key U Unique key R Referential integrity V With check option, on a view O With read only, on a view Namnet på vår PK är alltså: SYS_C0010189 8
Namn på constraints t STUDENT # studnr * fnamn * enamn o mobil STUDENT studnr fnamn enamn mobil 1 erik andersson 0733359556 SYS_C0010189 är inget bra namn på en constraint. insert into student(studnr,fnamn,enamn,mobil) values('1','carina','eriksson','0733358559'); Error starting at line : 1 in command - insert into student(studnr,fnamn,enamn,mobil) values('1','carina','eriksson','0733358559') Error report - SQL Error: ORA-00001: brott mot unik begränsning (TEST.SYS_C0010189) Detta namn säger oss ingenting! 00001. 00000 - "unique constraint (%s.%s) violated" 9
Byta namn på constraints t STUDENT # studnr * fnamn * enamn o mobil alter table student rename constraint SYS_C0010189 to student_studnr_pk; table STUDENT altered. Det är alltid bra att ge sina constraints bra namn. Det finns olika namngivningskonventioner. i Här är en som jag använder: tabell_kolumn_typ Typ Primary Key Foreign Key Check Unique Förkortning pk fk ck uq 10
Namn på constraints t STUDENT # studnr * fnamn * enamn o mobil STUDENT studnr fnamn enamn mobil 1 erik andersson 0733359556 Vi testar igen för att se skillnaden: insert into student(studnr,fnamn,enamn,mobil) values('1','carina','eriksson','0733358559'); Error starting at line : 1 in command - insert into student(studnr,fnamn,enamn,mobil) values('1','carina','eriksson','0733358559') Error report - SQL Error: ORA-00001: brott mot unik begränsning (TEST.STUDENT_STUDNR_PK) 00001. 00000 - "unique constraint (%s.%s) violated" 11
Ta bort en constraint t STUDENT # studnr * fnamn * enamn o mobil Om vi vill ta bort en constraint kan vi göra det med drop. Vi behöver bara känna till namnet: alter table student drop constraint student_studnr_pk; Nu är PK borttagen. Om vi vill kan vi lägga till fler constraints på samma gång. Vi lägger till PK igen och en unique constraint på kolumnen mobil: alter table student add constraint student_studnr_pk primary key(studnr) add constraint student_mobil_uq unique(mobil); 12
Lägga till en FK PERSON # persnr * fnamn * enamn o mobil ÄGARBYTE FORDON # id (#) persnr # regnr * färg (#) regnr * märke * datum * modell create table ägarbyte( id number(9), persnr varchar2(11), regnr varchar2(6), datum date default sysdate not null); alter table ägarbyte add constraint ägarbyte_radnr_pk primary key(id) add constraint ägarbyte_persnr_fk foreign key(persnr) references person(persnr) add constraint ägarbyte_regnr_fk foreign key(regnr) references fordon(regnr); 13
Lägga till en kolumn STUDENT # studnr * persnr * fnamn * enamn o mobil alter table student add persnr number(10); Oj, det blev visst fel datatyp på kolumnen. Vi vill ha varchar2(11) istället så att vi kan lagra personnummer som en teckensträng på formen 'YYMMDD-NNNN'. Vi kan ändra datatyp på kolumnen med följande SQL- sats: alter table student modify persnr varchar2(11); 14
Objektet t sekvens ÄGARBYTE # id (#) persnr (#) regnr * datum 112568, 112569... Det kan bli problem att generera nya unika id-värden för tabellen Ägarbyte om vi överlåter detta till människor. Bättre att låta en sekvens fixa detta! En sekvens är ett databasobjekt som vi kan se som en svart låda. Varje gång vi anropar funktionen nextval på sekvensobjektet så kommer vi att få ett nytt unikt nummer. Jämför med en nummerlappsmaskin på t.ex. apoteket. 15
Objektet t sekvens ÄGARBYTE # id (#) persnr (#) regnr * datum 112568, 112569... Vi skapar enkelt en sekvens enligt Vi kan testa t att den fungerar: följande kod: create sequence seq_ägarbyte start with 1 increment by 1; select seq_ägarbyte.nextval from dual; NEXTVAL 1 16
Hur använder vi en sekvens ÄGARBYTE id persnr regnr datum 1 940610-7140 ABC567 1994-11-2511 Vi anropar sekvensen när vi ska lägga till data i en tabell. Detta gör vi med SQL DML: insert into ägarbyte(id,persnr,regnr,datum) values(seq_ägarbyte.nextval,'940610-7145','abc567',sysdate); OBS! Det går inte att koppla ihop sekvensen med tabellen vid skapandet av tabellen. 17
Tabellen Dual Det finns en tabell definierad i Oracle data dictionary med namnet Dual. Tabellen finns där så att utvecklare som vill köra frågor eller testa funktioner, garanteras ett känt resultat. DUAL * dummy select * from dual; DUMMY ----- X Det finns alltid bara en rad i tabellen Dual. Om vi gör select på en konstant, t. ex. en 'textsträng' ' eller ett uttryck från någon tabell, så kommer resultatet att returneras en gång för varje rad som tabellen innehåller. I fallet med tabellen Dual, så kommer vi alltid att få ett resultat tillbaka. 18
Tabellen Dual -exempel select 'Kalle Andersson' from dual; 'KALLEANDERSSON' ---------------- Kalle Andersson SYSDATE select sysdate ---------------- from dual; 2019-05-10 SYSDATE + 10 select sysdate + 10 ---------------- from dual; 2019-05-2005 select 1 + 2 + 3 from dual; 1+2+3 ---------------- 6 19
Ta bort objekt För att ta bort skapade objekt använder vi oss av: drop objekt_name; PERSON # persnr * fnamn * enamn * telefon o mobil ÄGARBYTE FORDON # id (#) persnr # regnr * färg (#) regnr * märke * datum * modell Om vi skall ta bort ovanstående tabeller, så måste detta ske i en viss ordning: 1. drop table ägarbyte; 2. drop table person; drop table fordon; Vi kan inte ta bort person eller fordon först. Då detta medför brott mot referensintegriteten. Vi skulle ha FK-värden i ägarbyte som saknade referenser. 20
Datatyper t -enkla datatyper t "I have a very simple rule: Put dates in dates, numbers in numbers, and strings in strings. Never use a datatype to store something other than what it was designed for, and use the most specific type possible. " (Tom Kyte, Oracle) Varchar2 när vi vill lagra text. Kom ihåg att sätta enkelfnuttar ' runt texten i 'en textsträng'. Vi kan sätta maxlängd genom att lägga till stränglängden, varchar2(25) har en maxlängd av 25 tecken. Number när är vi behöver bhö lagra siffror: 345, 3, 67.3, 314 3.14. Vi sätter inte enkelfnuttar ' runt siffror. number(3) innebär max 3 siffror, t. ex. 999. number(5,2) innebär total längd av 5 siffror inklusive 2 decimaler, t. ex. 145.25 Date när vi skall lagra tidpunkter. Skilj på hur det lagras i databasen och hur det presenteras. Om vi lagrar sysdate, så har vi år, dag, timme, minut, sekund, ja ända ner på tusendels sekund. Vi kan presentera det som '2024-01-25' eller '01-JAN-2024' genom att ange en viss formatmask. Vi sätter enkelfnuttar ' runt datum '2016-12-24'. 21
Konverteringsfunktioner Olika inbyggda funktioner som sköter konvertering av datatyper. to_char, to_date, to_number etc. Vi kan konvertera ett datum, t. ex. sysdate till en teckensträng på önskat format 2027-10-01:14:15:58. 01:14:15:58 Vi testar med en bekant SQL-sats: select to_char(sysdate,'yyyy-mm-dd:hh24:mi:ss') as nu from dual; NU ------------------- 2015-03-12:13:15:49 22
Jämför inte äpplen med päron Ibland kan vi behöva konvertera en 'teckensträng' till ett datum eller ett datum till en 'teckensträng'. Vi vill kanske kontrollera om det finns några rader i kundtabellen med ett regdatum som är lika med '2019-05-25'. where regdatum = '2019-05-25'; datum sträng Furthermore, only compare dates to dates, strings to strings, and numbers to numbers. When dates and numbers are stored in strings, or stored using inappropriate lengths, your system suffers: 1. När man stoppar in data i databasen förlorar man möjligheten att kontrollera att datum är riktiga datum, att siffror är riktiga siffror 2. Databasen förlorar prestanda 3. Dataintegriteten och därmed datkvaliteten sjunker 4. Hela systemet lider! 23
Jämför äpplen med äpplen Vi måste se till att det är samma datatyp på bägge sidor om likhetsoperatorn = where to_char(regdatum,'yyyy-mm-dd') = '2019-05-25'; sträng sträng Om vi vill kontrollera hur många som registrerade sig under 2019: where to_char(regdatum, 'YYYY') = '2019'; Om vi vill kontrollera hur många som registrerade sig under Augusti 2019: where to_char(regdatum,'yyyy-mm') = '2019-08'; 24
Konsekvenser av felaktiga datatyper t Om vi lagrar ett datum som nummer eller en sträng så kan detta få svåra konsekvenser! Vad hindrar mig från att mata in 20170296? Den 96:e Februari finns väl inte. Jo i vår databas finns det datumet. Detta är ett exempel på låg dataintegritet. Vd Vad hindrar mig från få att mata in 2017-E2-A6? 2017-E2-A6,, vilken dag är det? Om vi hade satt datum som date hade detta inte varit möjligt. Systemet hade stoppat oss från att mata in vår skräpdata i databasen. "Put dates in dates, numbers in numbers, and strings in strings." 25
Operationer på datatypen t date date + number = date date - number = date date - date = number antalet tlt dagar mellan två tå datum dt select to_date('jan-01-2026','mon-dd-yyyy') + 10 as återdatum from dual; ÅTERDATUM ---------------- 2026-01-11 select sysdate - to_date('1993-02-23','yyyy-mm-dd') from dual; sysdate - to_date('1993-02-23','yyyy-mm-dd') -------------------------------------------- 8052,74644 26
Avrunda decimaler Vi kan använda funktionen round() för att avrunda till önskvärt antal decimaler: select round(sysdate - to_date('1993-02-23','yyyy-mm-dd'),0) as antal_dagar from dual; ANTAL_DAGAR ------------ 8053 Här kan du läsa mer om Oracle built in functions: http://www.techonthenet.com/oracle/functions/ 27