Skip to content
Slides & Docs
Main Navigation
Home
Resources
Software Dev
Web Dev
Return to top
On this page
DFU 03, Advanced Queries
Slideshow
# DFU 03 ## Advanced Queries ---- ### Notice - Eksemplerne i denne præsentation er lavet med PostgreSQL da I bad om PostgreSQL - der vil være forskelle ift. MSSQL og MySQL - forskellene er dog små <!------------------------------ --- Subqueries -------------------------------> --- ## Subqueries ---- ### Hvad er subqueries? - En forespørgsel **inde i en anden** forespørgsel** <!-- .element: class="fragment" --> - Returnerer data, som bruges af den "ydre" forespørgsel <!-- .element: class="fragment" --> - Kan stå i `SELECT`, `FROM`, `WHERE`, `HAVING` m.fl. <!-- .element: class="fragment" --> ---- ### Hvorfor bruge subqueries? - Bryd komplekse problemer op i mindre bidder <!-- .element: class="fragment" --> - Genbrug logik uden views <!-- .element: class="fragment" --> - Dynmiske filterværdier <!-- .element: class="fragment" --> ---- ### Ulemper ved subqueries - Kan være sværere at læse og forstå <!-- .element: class="fragment" --> - Potentielt dårligere ydeevne end joins <!-- .element: class="fragment" --> ---- ### Typer af subqueries - **Scalar** (enkelt værdi): Returnerer et enkelt værdi (én række, én kolonne) <!-- .element: class="fragment" --> - **Row**: Returnerer en enkelt række (én række, flere kolonner) <!-- .element: class="fragment" --> - **Table**: Returnerer flere rækker og kolonner (flere rækker, flere kolonner) <!-- .element: class="fragment" --> - **Correlated**: Refererer til kolonner i den ydre forespørgsel <!-- .element: class="fragment" --> ---- ### Eksempel: Scalar Subuqery ```sql [2] SELECT name, (SELECT COUNT(*) FROM courses WHERE programId = programs.id) AS courseCount FROM programs; ``` - Indlejret query giver én værdi <!-- .element: class="fragment" --> - Bruges i SELECT til at tilføje beregnet kolonne <!-- .element: class="fragment" --> ---- ### Eksempel Row Subuqery ```sql [] SELECT s.* FROM "Students" s WHERE (s.id, s."programId") = (SELECT e."studentId", e."programId" FROM "Exams" e ORDER BY e.grade DESC LIMIT 1); ``` - Match på **flere kolonner** med row value comparison <!-- .element: class="fragment" --> - Finder den **student** hvis `id`, `programId` matcher `studentId`, `programId` fra subquery <!-- .element: class="fragment" --> ---- ### Eksempel Table Subuqery ```sql [] SELECT name FROM programs WHERE id IN ( SELECT programId FROM courses WHERE level = 'AP' ); ``` - Subquery returnerer en tabel med id'er <!-- .element: class="fragment" --> - Bruges i WHERE til at filtrere programmer med AP-kurser <!-- .element: class="fragment" --> ---- ### Eksempel Correlated Subuqery ```sql [] SELECT p.name, (SELECT COUNT(*) FROM courses c WHERE c."programId" = p.id) AS courseCount FROM programs p; ``` - Subquery refererer til ydre query (`p.id`) <!-- .element: class="fragment" --> - Beregner antal kurser for hvert program <!-- .element: class="fragment" --> ---- ### Subqueries vs. Joins - Subqueries kan være mere intuitive for visse problemer <!-- .element: class="fragment" --> - Joins kan være mere effektive for store datasæt <!-- .element: class="fragment" --> - Valg afhænger af kontekst og præference <!-- .element: class="fragment" --> ---- ## Opgaver [https://ucl.kjc.dk/dfu/dfu-03-exercises-subqueries.html](https://ucl.kjc.dk/dfu/dfu-03-exercises-subqueries.html) <!------------------------------ --- Views -------------------------------> --- ## Views ---- ### Hvad er et view? - Logiske "virtuelle tabeller" <!-- .element: class="fragment" --> - Gemmer en SELECT-forespørgsel under et navn <!-- .element: class="fragment" --> - Bruges som en tabel i queries <!-- .element: class="fragment" --> ---- ### Views behavior - Opdateres dynamisk med underliggende data <!-- .element: class="fragment" --> - Oprettelse af et view er DDL (Data Definition Language) <!-- .element: class="fragment" --> - Selecte fra et view er DQL (Data Query Language) <!-- .element: class="fragment" --> - Performance: view er bare en "gemt query" <!-- .element: class="fragment" --> ---- ### Hvorfor bruge views? - Gør komplekse queries simple <!-- .element: class="fragment" --> - Genbrug af logik på tværs af systemet <!-- .element: class="fragment" --> - Sikkerd: skjul følsomme kolonner <!-- .element: class="fragment" --> - Konsistens: ét sted at ændre logikken <!-- .element: class="fragment" --> ---- ### Ulemper ved Views - Kan påvirke ydeevnen, især med komplekse forespørgsler <!-- .element: class="fragment" --> - Kan gøre debugging sværere <!-- .element: class="fragment" --> ---- ### Typer af Views - **Simple Views**: Basere på en enkelt tabel, uden aggregeringer eller joins <!-- .element: class="fragment" --> - **Complex Views**: Involverer flere tabeller, aggregeringer, joins eller subqueries <!-- .element: class="fragment" --> ---- ### Oprettelse af Views ```sql [] CREATE OR REPLACE VIEW view_name AS SELECT column1, column2, ... FROM table_name WHERE condition; ``` - `CREATE OR REPLACE VIEW`: Opretter eller opdaterer et view <!-- .element: class="fragment" --> - `OR REPLACE`: Valgfrit, erstatter eksisterende view <!-- .element: class="fragment" --> ---- ### Brug af Views ```sql [] SELECT * FROM view_name WHERE condition; ``` - Bruges som en almindelig tabel i SQL-forespørgsler <!-- .element: class="fragment" --> - Bemærk at conditionals er tilladt både i view-definitionen og i forespørgslen <!-- .element: class="fragment" --> ---- ### Sletning af Views ```sql [] DROP VIEW IF EXISTS view_name; ``` - `IF EXISTS`: Valgfrit, undgår fejl hvis viewet ikke findes ---- ### Views vs. ORM e.g. Entity Framework - Views kan bruges sammen med ORM-værktøjer som Entity Framework <!-- .element: class="fragment" --> - ORM kan mappe views til entiteter ligesom tabeller <!-- .element: class="fragment" --> - Fordel: Genbrug af komplekse forespørgsler uden at skulle skrive SQL i applikationskoden <!-- .element: class="fragment" --> - Ulempe: Mindre fleksibilitet sammenlignet med direkte SQL-forespørgsler <!-- .element: class="fragment" --> ---- ## Opgaver [https://ucl.kjc.dk/dfu/dfu-03-exercises-views.html](https://ucl.kjc.dk/dfu/dfu-03-exercises-views.html) <!------------------------------ --- Functions -------------------------------> --- ## Functions ---- ### Indbyggede funktioner - SQL har mange indbyggede funktioner <!-- .element: class="fragment" --> - F.eks. `COUNT()`, `SUM()`, `AVG()`, `UPPER()`, `LOWER()`, `NOW()` <!-- .element: class="fragment" --> - Bruges i `SELECT`, `WHERE`, `HAVING`, `ORDER BY` m.fl. <!-- .element: class="fragment" --> ---- ### Hvad er en custom functions? - Konceptuelt det samme som i programmering <!-- .element: class="fragment" --> - En `function` er en gemt "procedure", der returnerer en værdi <!-- .element: class="fragment" --> - Kan tage inputparametre <!-- .element: class="fragment" --> - Kan bruges i SQL som indbyggede funktioner <!-- .element: class="fragment" --> ---- ### Hvorfor bruge custom functions? - Genbrug af kompleks logik <!-- .element: class="fragment" --> - Forbedret læsbarhed af SQL-forespørgsler <!-- .element: class="fragment" --> - Centraliseret vedligeholdelse af logik <!-- .element: class="fragment" --> ---- ### Udfordringer ved custom functions - Kan påvirke ydeevnen, især hvis de kaldes mange gange <!-- .element: class="fragment" --> - Man kan have en tendens til at flytte logik fra applikationen til databasen <!-- .element: class="fragment" --> - Ikke gennemsigtigt hvilke functions der findes <!-- .element: class="fragment" --> ---- ### Eksempel: Oprettelse af en simpel function ```sql [] CREATE FUNCTION add(integer, integer) RETURNS integer AS 'select $1 + $2;' LANGUAGE SQL RETURNS NULL ON NULL INPUT; ``` ---- ### Brug af en function ```sql [] SELECT add(2, 3) AS sum; ``` ---- ### Eksempler på use cases - Beregninger, f.eks. momsberegning <!-- .element: class="fragment" --> - Datomanipulation, f.eks. formatering af strenge <!-- .element: class="fragment" --> - Datavalidering, f.eks. tjekke gyldighed af data <!-- .element: class="fragment" --> Det er selvfølgelig et valg om man ønsker denne logik i databasen eller i applikationen <!-- .element: class="fragment" --> ---- ## Opgaver [https://ucl.kjc.dk/dfu/dfu-03-exercises-functions.html](/dfu/dfu-03-exercises-functions.html) --- ## Stored procedures <!-- with PostgreSQL --> ---- ### Hvad er en stored procedure? - En gemt procedure i databasen <!-- .element: class="fragment" --> - Kan udføre komplekse operationer <!-- .element: class="fragment" --> - Kan returnere resultater eller status <!-- .element: class="fragment" --> ---- ### Hvorfor bruge stored procedures? - Centraliseret logik i databasen <!-- .element: class="fragment" --> - Forbedret ydeevne ved at reducere netværkstrafik <!-- .element: class="fragment" --> - Sikkerhed: begræns adgang til data via procedurer <!-- .element: class="fragment" --> ---- ### Udfordringer ved stored procedures - Kan gøre debugging sværere, da logikken er i databasen <!-- .element: class="fragment" --> - Kan føre til "vendor lock-in" pga. database-specifik syntaks <!-- .element: class="fragment" --> - Vedligeholdelse kan blive kompleks med mange procedurer <!-- .element: class="fragment" --> ---- ### Forskellen mellem `functions` og `stored procedures` - **Functions** returnerer en værdi og kan bruges i SQL-forespørgsler <!-- .element: class="fragment" --> - **Stored Procedures** kan udføre handlinger og returnere status <!-- .element: class="fragment" --> - **Stored Procedures** et "fully self-contained" <!-- .element: class="fragment" --> ---- ### Oprettelse af en simpel stored procedure ```sql [] CREATE OR REPLACE PROCEDURE log_student_enrollment(student_id INT, course_id INT) LANGUAGE plpgsql AS $$ BEGIN INSERT INTO enrollments ("studentId", "courseId", "enrollmentDate") VALUES (student_id, course_id, NOW()); END; $$; ``` - `CREATE OR REPLACE PROCEDURE`: Opretter eller opdaterer en procedure <!-- .element: class="fragment" --> - `LANGUAGE plpgsql`: Angiver sproget (PostgreSQL's PL/pgSQL) <!-- .element: class="fragment" --> - `AS $$` ... `$$;`: Definerer procedurekroppen / afgrænsning <!-- .element: class="fragment" --> ---- ### Kald af en stored procedure ```sql [] CALL log_student_enrollment(1, 101); ``` ---- ### Eksempler på use cases - Data manipulation, f.eks. indsættelse eller opdatering af flere tabeller <!-- .element: class="fragment" --> - Kompleks forretningslogik, f.eks. validering og Beregninger <!-- .element: class="fragment" --> - Batch processer, f.eks. periodiske Opgaver <!-- .element: class="fragment" --> ---- ## Opgaver [https://ucl.kjc.dk/dfu/dfu-03-exercises-sp.html](/dfu/dfu-03-exercises-sp.html) --- ## Transactions ---- ### Hvad er en transaction? - En **transaction** er en serie af SQL operationer, der udføres som en enkelt enhed <!-- .element: class="fragment" --> - Enten gennemføres alle operationer, eller ingen af dem <!-- .element: class="fragment" --> ---- ### Hvorfor Transactions? - Bevarer **dataintegritet** <!-- .element: class="fragment" --> - Sikrer **konsistens** i databasen <!-- .element: class="fragment" --> - Gør ændringer **atomiske** (alt eller intet) <!-- .element: class="fragment" --> ---- ### ACID-principperne - **Atomicity**: Hele transactionen gennemføres eller ingen del af den <!-- .element: class="fragment" --> - **Consistency**: Databasen forbliver i en gyldig tilstand før og efter transactionen <!-- .element: class="fragment" --> - **Isolation**: Transaktioner er isolerede fra hinanden, så samtidige transaktioner ikke påvirker hinanden <!-- .element: class="fragment" --> - **Durability**: Når en transaction er gennemført, er ændringerne permanente, selv ved systemfejl <!-- .element: class="fragment" --> ---- ### Grundlæggende syntax ```sql [] BEGIN; -- Start transaction -- SQL operationer her -> UPDATE accounts SET balance = balance - 100 WHERE id = 1; UPDATE accounts SET balance = balance + 100 WHERE id = 2; -- <- SQL operationer her COMMIT; -- Gem ændringer -- ROLLBACK; -- Fortryd ændringer (bruges ved fejl) ``` ---- ### Eksempel ```sql [] BEGIN; UPDATE accounts SET balance = balance - 100 WHERE id = 1; UPDATE accounts SET balance = balance + 100 WHERE id = 2; IF (/* fejl opstår */) THEN ROLLBACK; -- Fortryd ændringer ELSE COMMIT; -- Gem ændringer END IF; ``` ---- ### Transactions i Stored Procedures ```sql [] CREATE PROCEDURE proc2() LANGUAGE plpgsql AS $$ BEGIN FOR idx IN 1..100 LOOP INSERT INTO my_tbl(col_num) VALUES(idx); IF idx % 10 = 0 THEN A COMMIT; B ELSE ROLLBACK; C END IF; END LOOP; END $$; ``` ---- ### Best Practices - Brug transactions til operationer, der involverer flere trin <!-- .element: class="fragment" --> - Hold transactions så korte som muligt for at minimere table locks <!-- .element: class="fragment" --> ---- ### Opgaver [https://ucl.kjc.dk/dfu/dfu-03-exercises-transactions.html](/dfu/dfu-03-exercises-transactions.html)
Toggle fullwidth
sql
sql
sql
sql
sql
sql
sql
sql
sql
sql
sql
sql
sql
sql