wiki.phpfreakz.nl
Aanmelden Artikel Overleg Bewerk Geschiedenis Go to the site toolbox

Overzichtelijk SQL

Inhoud

Inleiding

Dit artikel is een toevoeging op Overzichtelijk programmeren. Net als overzichtelijke PHP code schrijven, is het duidelijk houden van een SQL-Query een belangrijk iets. Hoe vaak is het niet voorkomen dat je een database foutmelding krijgt, en het probleem een ontbrekende komma of haakje was?

Het maakt voor de verwerkingssnelheid helemaal niet uit of alle SQL op één regel staat of wordt verdeeld over meerdere regels, dus schrijf de query duidelijk op, dat maakt jouw leven een stuk makkelijker en je applicatie wordt er niet trager door.

De basisregels

  • Gebruik hoofdletters voor alle SQL keywords, zoals SELECT , DELETE, FROM, WHERE, LIMIT etc.
  • Gebruik voor tabel- en kolomnamen altijd dezelfde soort letters, alleen kleine letters of alleen hoofdletters, maar nooit door elkaar.
  • Spring in na elk SQL keyword, en terug voor elk nieuw keyword.
  • Som lijsten parameters op in aparte regels met de komma aan het begin van de regel in plaats van erachter. De reden is dat je in de praktijk tijdens het debuggen vaak het laatste item van de lijst af wilt halen. Als de komma achter elk item staat dan moet je ook de komma van het vorige item weghalen. Door de komma voor elk item te zetten kun je de hele regel uitcommentarieeren zonder een komma weg te hoeven halen.

Met een komma erachter:

SELECT 
  fiets,
  auto -- ,
-- vliegtuig
FROM
  voertuigen;


met een komma ervoor:

SELECT 
  fiets
  , auto
-- , vliegtuig
FROM
  voertuigen;

Een bijkomend voordeel is dat alle komma's onder elkaar komen te staan waardoor je goed kunt zien of je er nog een mist.

  • Subqueries spring je zover mogelijk net zover in als het statement waar ze in vallen:
  1. SELECT
  2. veld
  3. , veld2
  4. , veld3
  5. FROM
  6. tabel
  7. WHERE
  8. gebruiker = 'piet'
  9. AND
  10. geheim IN (
  11. SELECT
  12. geheimid
  13. FROM
  14. geheimentabel
  15. WHERE
  16. magie='groot'
  17. )

Voorbeeld

Stel je hebt deze query:

SELECT veld, veld2, veld3 FROM tabel WHERE gebruiker='piet'

De correcte opmaak wordt dan:

  1. SELECT
  2. veld
  3. , veld2
  4. , veld3
  5. FROM
  6. tabel
  7. WHERE
  8. gebruiker = 'piet'

Het voordeel van deze schrijfwijze wordt bijzonder snel duidelijk als de query wat langer wordt:

  1. SELECT dayofcourse > courseduration, dayofcourse > (courseduration+14) FROM ( SELECT SUM(duration) AS courseduration, courseid FROM m3_psy_timeframes GROUP BY courseid) AS courseinfo INNER JOIN ( SELECT SQL_NO_CACHE users.uid, subscriptions.courseid, (DATEDIFF(NOW() , startdate) - totalpauze) AS dayofcourse ... <knip want dit valt toch buiten beeld>

Dat is niet meer te volgen. Een nette indeling houdt het overzichtelijk:

  1. SELECT
  2. dayofcourse > courseduration
  3. dayofcourse > (courseduration+14)
  4. FROM
  5. (
  6. SELECT
  7. SUM(duration) AS courseduration
  8. , courseid
  9. FROM
  10. m3_psy_timeframes
  11. GROUP BY
  12. courseid
  13. ) AS courseinfo
  14. INNER JOIN
  15. (
  16. SELECT SQL_NO_CACHE
  17. users.uid
  18. , subscriptions.courseid
  19. , (DATEDIFF(NOW() , startdate) - totalpauze) AS dayofcourse
  20. FROM
  21. m3_users AS users
  22. INNER JOIN
  23. m3_psy_course_subscriptions AS subscriptions
  24. ON
  25. subscriptions.userid = users.uid
  26. INNER JOIN
  27. (
  28. SELECT
  29. uid
  30. , subscriptions.courseid
  31. , COALESCE(SUM(DATEDIFF(pauzes.enddate , pauzes.startdate)),0) AS totalpauze
  32. FROM
  33. m3_users AS users
  34. INNER JOIN
  35. m3_psy_course_subscriptions AS subscriptions
  36. ON
  37. subscriptions.userid = users.uid
  38. LEFT JOIN
  39. m3_psy_course_pauses AS pauzes
  40. ON
  41. pauzes.userid=users.uid
  42. GROUP BY
  43. users.uid
  44. , subscriptions.courseid
  45. ) AS adata
  46. ON
  47. adata.uid=users.uid
  48. AND
  49. adata.courseid=subscriptions.courseid
  50. )AS bdata
  51. ON
  52. bdata.courseid = courseinfo.courseid


Regelnummers

Zou er een fout in je query staan, dan wordt daarin doorgaans ook een regelnummer gegeven. Dit regelnummer verwijst naar de regel in de query. Als een query maar uit 1 regel bestaat, krijg je dan dus altijd de verwijzing "op regel 1". Spreiden van je query over meerdere regels zal dan het zoeken van de fout versnellen.

Backticks ( ` )

Backticks zijn een MySQL handigheidje om aan te geven dat de tekst tussen de backticks niet mag worden gelezen als een SQL keyword, ookal is het dat wel. Vooral PHPMyAdmin past deze dingen te pas en te onpas toe.

Dit levert allerlei spannende bugs op omdat die backticks gegarandeerd een keer vergeten worden. Stel dat je een tabel hebt met een kolom genaamd delete en die wil je opvragen met een SELECT query, dan doe je:

  1. SELECT
  2. `delete`
  3. FROM
  4. tabelnaam

Maar als je de backticks vergeet dan krijgt delete ineens de betekenis van een DELETE query en dan selecteer je niet meer de waarde van de delete kolom, maar de uitkomst van de query DELETE FROM tabelnaam:

  1. SELECT
  2. DELETE
  3. FROM
  4. tabelnaam

Dat levert één record op met daarin één kolom genaamd delete en daarin de waarde true. Later merk je dan dat je tabel nu leeg is.

Gebruik dus nooit backticks. Geef je tabellen en kolommen een naam die niet gelijk is aan een SQL keyword. Voor elke database kun je in de handleiding een lijst met gereserveeerde woorden vinden die je niet mag gebruiken.

Noot: de meeste databases hebben een soortgelijke functionaliteit, in PostgreSQL werkt het met dubbelquotes. Echter MySQL is de enige die het actief aanraadt als een soort preventieve bugfix.

Selecteer enkel die velden die je nodig hebt

Het is natuurlijk heel makkelijk om gewoon alle velden te selecteren met '*'. Maar heb je deze wel allemaal nodig?

De database verwerkt de gegevens, maar je gebruik ze niet. Dat is verspilling van resources en helemaal nergens voor nodig.

Selecteer altijd ALLEEN de velden die je ook echt daadwerkelijk gebruikt. Zelfs als je alle velden gebruikt kan het handig zijn, deze gewoon allemaal te selecteren bij hun naam. Zodat je weet welke velden er allemaal zijn, en niet steeds in de database (of als je het helemaal goed hebt gedaan, documentatie) moet duiken om ze terug te vinden.

Bovendien krijg je dan ook een waarschuwing "column X not found" als je een kolom in een tabel verwacht die er helemaal niet is.

Aliassen

Een alias is wat de naam zegt; een andere naam voor hetzelfde. In SQL kun je aliassen gebruiken voor kolommen, tabellen en queries.

Aliassen voor overzichtelijkheid

Een alias kan een compleet andere tekst zijn dan hetgeen hij naar verwijst. Een lange of cryptische naam kan worden ge-aliast naar een naam die beter uitlegt wat er in staat.


Vuistregels

Het is zeer verleidelijk om de tabel 'users' af te korten tot 'u'. Maar als je ook een tabel 'userprofiles' hebt dan moet je daar iets anders voor gebruiken en dat wordt meestal 'up'. Als je daarna een tabel 'userprivileges' krijgt dan kan 'up' ook niet meer en ga je over naar 'upv' of iets anders cryptisch.

Het doel van de alias wordt dan zuiver en alleen "zo kort mogelijk zijn" en doet niet meer waarvoor je hem gebruikt: eenvoudig de juiste tabel aanwijzen.

Gebruik daarom liever een alias die de naam van de tabel vereenvoudigt. Kort dingen op een natuurlijke manier af, b.v. door de eerste lettergreep te gebruiken. userprofiles kan userprof worden, dat is duidelijk en toch korter.


Een voorbeeld van hoe het niet moet:

SELECT 
   x.id
   , x.naam
   , y.beroep
FROM 
   tabelmetlangenaamvanuser AS x
 , tabelmetberoepen AS y

Maar liever:

SELECT 
   user.id
   , user.naam
   , job.beroep
FROM 
   tabelmetlangenaamvanuser AS user
   , tabelmetberoepen AS job

Onderhoudbaarheid

Door een alias te gebruiken wordt de naam van en tabel of expressie op één plek ingesteld en in de rest alleen gebruikt. Mocht er een noodzaak zijn om de data waar de alias naar verwijst te veranderen, b.v. omdat het een andere tabel wordt, dan hoeft dat alleen te worden veranderd op de plek waar de alias wordt toegewezen.

Hoe werkt een alias

Een alias kan op twee manieren worden ingezet; als andere naam voor de dingen die je selecteert, of als een andere naam voor de dingen waar je uit selecteert.

Aliassen zijn ook praktisch noodzakelijk als je een berekening selecteert omdat de uitkomst van die berekening anders in de resultset komt te staan onder een naam die gelijk is aan de berekening, en dat is bijzonder onhandig.


SELECT
  simpele_alias.ingewikkelde_kolomnaam AS mijnalias
  , (1+4/6 * veldwaarde) AS uitkomst
  , DATE_FORMAT(datum, '%d-%m-%Y') AS datumgeformatteerd
FROM
  tabel_met_een_ingewikkelde_naam AS simpele_alias
INNER JOIN
  (SELECT * FROM users WHERE role="meester") AS meesterusers
ON
  simpele_alias.userid = meesterusers.userid

Aliassen voor tabellen

Tabellen kunnen ook een alias krijgen. Dit is in elk geval nodig als 1 tabel vaker voorkomt in je query, maar dit kan ook gedaan worden als je lange tabelnamen wilt inkorten omdat je anders op veel plaatsen in je code de lange tabelnaam nodig hebt.

Site Toolbox:

Persoonlijke hulpmiddelen
De laatste wijziging op deze pagina vond plaats op 14 jul 2010 23:16. - Deze pagina werd 6.495 maal bekeken. - Disclaimers - Over PFZWIKI