{"id":30,"date":"2023-06-03T09:50:00","date_gmt":"2023-06-03T07:50:00","guid":{"rendered":"https:\/\/djax.se\/blog\/?p=30"},"modified":"2023-06-03T09:50:00","modified_gmt":"2023-06-03T07:50:00","slug":"sql-som-applikations-sprak","status":"publish","type":"post","link":"https:\/\/djax.se\/?p=30","title":{"rendered":"SQL som applikations spr\u00e5k"},"content":{"rendered":"\n<p>Mjukvara \u00e4r skriven i programmeringsspr\u00e5k. Dessa spr\u00e5k delas upp p\u00e5 olika s\u00e4tt som h\u00f6g- och l\u00e5gniv\u00e5 eller i generationer som <a href=\"https:\/\/en.wikipedia.org\/wiki\/Fourth-generation_programming_language\">&#8221;fj\u00e4rde generationens spr\u00e5k&#8221;<\/a>. SQL \u00e4r ett s\u00e5dant &#8221;fj\u00e4rde generationens&#8221; spr\u00e5k. Tanken var att kunna beskriva vad som \u00f6nskas fr\u00e5n datorn ist\u00e4llet f\u00f6r p\u00e5 ett exakt vis koda <strong>hur <\/strong>informationen skall samlas ihop p\u00e5. G\u00e4rna att personer utan programmeringsbakgrund skulle kunna <strong>deklarera <\/strong>egna fr\u00e5gor d\u00e5 spr\u00e5ken ofta f\u00f6rs\u00f6ker efterlikna vanlig engelska.<\/p>\n\n\n\n<pre class=\"wp-block-merpress-mermaidjs mermaid\">stateDiagram-v2\n        State1: 1 Gen\n        State1 --> State2\n        State2: 2 Gen\n        note left of State2 : Assembly\n        State2 --> State3\n        State3: 3 Gen\n        note left of State3 : C, Java, Python\n        State3 --> State4\n        State4: 4 Gen\n        note left of State4 : SQL, ABAP\n        State4 --> State5\n        State5: 5 Gen\n        note left of State5 : AI? LLM?<\/pre>\n\n\n\n<p>Tanken \u00e4r bra och det \u00e4r ocks\u00e5 vad dagens <a href=\"https:\/\/en.wikipedia.org\/wiki\/Low-code_development_platform\" data-type=\"URL\" data-id=\"https:\/\/en.wikipedia.org\/wiki\/Low-code_development_platform\">low-code<\/a> l\u00f6sningar f\u00f6rs\u00f6ker g\u00f6ra igen. Allts\u00e5 h\u00f6ja abstraktionsniv\u00e5n med hj\u00e4lp av f\u00e4rdigskriven kod som f\u00f6rhoppningsvis blir p\u00e5 en h\u00f6gre och enklare niv\u00e5. Detta nya verktyg kan vara allt fr\u00e5n <a href=\"https:\/\/www.winglang.io\/\" data-type=\"URL\" data-id=\"https:\/\/www.winglang.io\/\">lite f\u00e4rdiga funktioner<\/a> i ett befintligt spr\u00e5k eller en hel plattform d\u00e4r du <a href=\"https:\/\/www.sap.com\/products\/technology-platform\/no-code-app-builder.html\">drar och sl\u00e4pper<\/a> grafiska objekt p\u00e5 varandra som ett s\u00e4tt att programmera maskinen.<\/p>\n\n\n\n<p><\/p>\n\n\n\n<p>Men ett lager till av abstraktion har ett pris. Det kan vara om\u00f6jligt att beskriva en l\u00f6sning p\u00e5 vissa problem med den detaljrikedom som funnits till hand med ett &#8221;vanligt&#8221; programmeringsspr\u00e5k p\u00e5 en l\u00e4gre niv\u00e5. Alternativt blir den SQL-baserade l\u00f6sningen on\u00f6digt komplex f\u00f6r att det inte \u00e4r m\u00f6jligt att \u00e5teranv\u00e4nda kod p\u00e5 samma s\u00e4tt.<\/p>\n\n\n\n<p>Detta leder mig till k\u00e4rnan av detta inl\u00e4gg: <a href=\"https:\/\/en.wikipedia.org\/wiki\/Stored_procedure\">Stored procedures<\/a> som spr\u00e5k i backend. Allts\u00e5 system d\u00e4r det mesta av aff\u00e4rslogiken (det som \u00e4r v\u00e4rt pengar) \u00e4r inl\u00e5st i SQL, ett spr\u00e5k d\u00e4r inga satsningar g\u00f6rs p\u00e5 ergonomin f\u00f6r utvecklaren. Ett spr\u00e5k som saknar arv, klasser, inkapsling, reflektion, generics och annat g\u00f6tt som \u00f6vriga spr\u00e5k uppfinner just f\u00f6r att hantera en skenande komplexitet.<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>Let me put this another way: Stack Overflow has only 1 stored procedure in the database and I intend to move that last vestige into code.<\/p>\n<cite><a href=\"https:\/\/nickcraver.com\/blog\/2016\/02\/17\/stack-overflow-the-architecture-2016-edition\/\">https:\/\/nickcraver.com\/blog\/2016\/02\/17\/stack-overflow-the-architecture-2016-edition\/<\/a><\/cite><\/blockquote>\n\n\n\n<p>Ovan \u00e4r citat fr\u00e5n arkitekten p\u00e5 Stackoverflow och vad denna k\u00e4nner stored procedures har f\u00f6r plats i systemet.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Hur kom vi hit?<\/h2>\n\n\n\n<p>P\u00e5 90-talet n\u00e4r relationsdatabaser fick ordentligt genomslag s\u00e5 gissar jag att det s\u00e5gs som en smidig l\u00f6sning att uppn\u00e5 en klient-server arkitektur genom att skapa en &#8221;fet klient&#8221; i till exempel VB eller C++ som blev h\u00e5rt knyten till sin server som ocks\u00e5 samtidigt \u00e4r en databas d\u00e4r &#8221;koden&#8221; \u00e4r i form av stora m\u00e4ngder SQL procedurer.<\/p>\n\n\n\n<p>M\u00e5let var att avlasta de kanske svagare klientdatorerna med att de (misst\u00e4nkt) allra tyngsta funktionerna k\u00f6rdes direkt i databasen, p\u00e5 en annan maskin. Samt att l\u00f6ftet var ocks\u00e5 att fj\u00e4rde generationens spr\u00e5k skulle vara mer l\u00e4mpade och kraftfullare i att beskriva aff\u00e4rsprocesserna i mjukvaran.<\/p>\n\n\n\n<pre class=\"wp-block-merpress-mermaidjs mermaid\">graph LR; \nKlient1-->|SQL|D[(Databas)] \nKlient2-->|SQL|D \nKlient3-->|SQL|D \nE(ev. Servertj\u00e4nst)-->|SQL|D <\/pre>\n\n\n\n<p>Klienterna h\u00e4mtade data och utf\u00f6rde f\u00f6r\u00e4ndringar i databasen genom att skicka SQL str\u00e4ngar synkront &#8221;\u00f6ver tr\u00e5den&#8221;. <\/p>\n\n\n\n<p>Resultatet blev att system byggdes upp med <strong>tv\u00e5 mycket olika programmeringsspr\u00e5k<\/strong>. D\u00e4r det ena f\u00f6rmodligen var ett tredje generations objekt-orienterat spr\u00e5k i klienten, och det andra ett fj\u00e4rde generations data-fr\u00e5ge spr\u00e5k. <\/p>\n\n\n\n<pre class=\"wp-block-merpress-mermaidjs mermaid\">pie title Andel programmeringsspr\u00e5k i ett hypotetiskt system\n    \"VB\" : 15\n    \"SQL\" : 85<\/pre>\n\n\n\n<p>Databasen kan inte i denna arkitektur vara den f\u00f6rsta att reagera och initiera kontakt tillbaka till en klient n\u00e4r n\u00e5gon ny h\u00e4ndelse intr\u00e4ffat. Klienterna f\u00e5r ist\u00e4llet konstant polla dabasen efter intressanta \u00e4ndringar att reagera p\u00e5. \u00d6nskar anv\u00e4ndarna att systemet skall bli rappare \u00e4r enda alternativet att klienterna pollar h\u00e5rdare. Detta \u00e4r bara en form av <a href=\"https:\/\/en.wikipedia.org\/wiki\/Busy_waiting\" data-type=\"URL\" data-id=\"https:\/\/en.wikipedia.org\/wiki\/Busy_waiting\">busy waiting<\/a>, d\u00e5ligt f\u00f6r milj\u00f6n.<\/p>\n\n\n\n<p>Att bygga ett system med tv\u00e5 s\u00e5 pass olika spr\u00e5k \u00e4r en on\u00f6dig kostnad i den mentala energi det g\u00e5r \u00e5t att byta mellan dessa. F\u00f6rutom att spr\u00e5ken som anv\u00e4nds skiftar konstant s\u00e5 skiftar ocks\u00e5 verktygen som anv\u00e4nds, s\u00e4ttet \u00e4ndringar testas, s\u00e4ttet \u00e4ndringar versionshanteras p\u00e5 och s\u00e4ttet  \u00e4ndringar transporteras till produktion.<\/p>\n\n\n\n<figure class=\"wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio\"><div class=\"wp-block-embed__wrapper\">\n<iframe loading=\"lazy\" title=\"Full-stack development is dead, long live full-stack development! by Simon Martinelli\" width=\"500\" height=\"281\" src=\"https:\/\/www.youtube.com\/embed\/R3V0DAW-BiA?start=59&#038;feature=oembed\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share\" referrerpolicy=\"strict-origin-when-cross-origin\" allowfullscreen><\/iframe>\n<\/div><\/figure>\n\n\n\n<p>F\u00f6rel\u00e4saren pratar h\u00e4r om att historien upprepar sig med dagens webb &#8221;applikationer&#8221; som <strong>k\u00f6rs lokalt<\/strong> p\u00e5 anv\u00e4ndarens dator.<\/p>\n\n\n\n<pre class=\"wp-block-merpress-mermaidjs mermaid\">graph LR; \nKlient1-->|HTTP|B((Backend)) \nKlient2-->|HTTP|B \nKlient3-->|HTTP|B \nB-->|SQL|D[(Databas)] <\/pre>\n\n\n\n<p>I dessa system \u00e5terkommer det h\u00e4r problemet i form av att det webbaserade anv\u00e4ndargr\u00e4nssnittet g\u00f6rs interaktivt med Javascript medans n\u00e5got annat spr\u00e5k sannolikt anv\u00e4nds f\u00f6r att implementera bakomliggande API. Kanske finns \u00e4ven h\u00e4r ocks\u00e5 logik skrivet med SQL i databasen vilket g\u00f6r att 3 olika spr\u00e5k anv\u00e4nds i systemet. <\/p>\n\n\n\n<pre class=\"wp-block-merpress-mermaidjs mermaid\">pie title Spr\u00e5k i \"modern\" \"webapp\"\n    \"TypeScript\" : 45\n    \"Python\" : 45\n    \"SQL\" : 10<\/pre>\n\n\n\n<p>Det \u00e4r inte konstigt att behovet av &#8221;frontend&#8221; utvecklare skapades n\u00e4r det blev normalt att anv\u00e4nda flera programmeringsspr\u00e5k och verktyg inom samma system. Innan dess, enligt Simon Martinelli i klippet ovan, var vi alla &#8221;fullstack&#8221; och detta var det normala. Det fanns inget annat ord \u00e4n bara &#8221;utvecklare&#8221;.<\/p>\n\n\n\n<p>Men detta inl\u00e4gg skall inte handla om arkitektur, det skall handla om hur det \u00e4r att utveckla i SQL med allt vad det inneb\u00e4r f\u00f6r b\u00e5de funktionella och icke-funktionella behov.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Programmeringen<\/h2>\n\n\n\n<p>Testdriven utveckling \u00e4r inget som f\u00f6rekommer i den h\u00e4r typen av programmering. Stega sig igenom (debugga) koden \u00e4r heller inget som g\u00e5r att g\u00f6ra, mer om det nedan under fels\u00f6kning.<\/p>\n\n\n\n<p>I objektorienterade spr\u00e5k finns m\u00f6jligheter i spr\u00e5ket som kan anv\u00e4ndas till att undvika att skjuta b\u00e5de sig sj\u00e4lv i foten och andra som skall underh\u00e5lla koden i i framtiden. Genom superklasser och konstruktorer  kan du till exempel garantera att ditt objekt (och f\u00f6r dig ok\u00e4nda framtida arvsklasser) skapas upp i r\u00e4tt tillst\u00e5nd.  Avancerade ramverk som <a href=\"https:\/\/spring.io\/\" data-type=\"URL\" data-id=\"https:\/\/spring.io\/\">Spring <\/a>anv\u00e4nder sig av <a href=\"https:\/\/en.wikipedia.org\/wiki\/Aspect-oriented_programming\" data-type=\"URL\" data-id=\"https:\/\/en.wikipedia.org\/wiki\/Aspect-oriented_programming\">Aspect-oriented programming<\/a> och <a href=\"https:\/\/en.wikipedia.org\/wiki\/Reflective_programming\" data-type=\"URL\" data-id=\"https:\/\/en.wikipedia.org\/wiki\/Reflective_programming\">reflektion <\/a>f\u00f6r att bjuda in till att f\u00f6renkla och modularisera systemet ytterligare. Inget av detta existerar i SQL ekomilj\u00f6n.<\/p>\n\n\n\n<p>I SQL procedurer \u00e4r det i st\u00e4llet konventioner som m\u00e5ste f\u00f6ljas. Till exempel <a href=\"https:\/\/www.brentozar.com\/archive\/2021\/06\/what-does-set-nocount-on-do\/\" data-type=\"URL\" data-id=\"https:\/\/www.brentozar.com\/archive\/2021\/06\/what-does-set-nocount-on-do\/\">saker som m\u00e5ste placeras l\u00e4ngst upp<\/a> i alla procedurer. Eller komplex <a href=\"https:\/\/www.sommarskog.se\/error_handling\/Part1.html\">felhanteringslogik <\/a>som m\u00e5ste kopieras och klistras in i varje procedur. Detta kunde l\u00e4tt byggas dynamiskt, datadrivet och underh\u00e5llas i en enda tappning p\u00e5 en central plats i ett konventionellt spr\u00e5k.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"743\" src=\"http:\/\/localhost:8081\/wp-content\/uploads\/2023\/02\/ssms-1024x743.png\" alt=\"\" class=\"wp-image-211\" srcset=\"https:\/\/djax.se\/wp-content\/uploads\/2023\/02\/ssms-1024x743.png 1024w, https:\/\/djax.se\/wp-content\/uploads\/2023\/02\/ssms-300x218.png 300w, https:\/\/djax.se\/wp-content\/uploads\/2023\/02\/ssms-768x557.png 768w, https:\/\/djax.se\/wp-content\/uploads\/2023\/02\/ssms.png 1499w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Editorn du sitter i \u00e4r f\u00f6rmodligen inte lika kraftfullt som ett vanligt IDE s\u00e5 som Visual Studio eller Eclipse och f\u00f6rmodligen gjord f\u00f6r att anv\u00e4ndas b\u00e5de av utvecklare, de som tar backup och n\u00e5gon som vill skapa en rapport<\/li>\n\n\n\n<li>Inte s\u00e4kert att syntax highlighting eller m\u00f6rkt tema finns. <\/li>\n\n\n\n<li>Troligen saknas integration till versionshanteringssystemet. <\/li>\n\n\n\n<li>Om du trycker p\u00e5 ett procedur anrop \u00f6ppnas inte implementationen. <\/li>\n\n\n\n<li>Inget st\u00f6d f\u00f6r automatisk refaktorisering.<\/li>\n<\/ul>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>In contrast, stored procedures require the skilled DBA to write SQL, which is far from as straightforward as application code. A stored-procedure-heavy architecture is one that is either terrible because of bad stored procedures, or requires substantial talent of the DBA writing the stored procedures to do them properly.<\/p>\n<cite><a href=\"https:\/\/medium.com\/@JoeEmison\/stored-procedures-as-a-litmus-test-c7ec772b985e\">https:\/\/medium.com\/@JoeEmison\/stored-procedures-as-a-litmus-test-c7ec772b985e<\/a><\/cite><\/blockquote>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Skall du k\u00f6ra din kod beh\u00f6ver du koppla upp dig mot en databasserver och s\u00e4kerst\u00e4lla att koden i dit f\u00f6nster \u00e4r den aktuella koden som ocks\u00e5 lagrats p\u00e5 servern.<\/li>\n\n\n\n<li>Det \u00e4r generellt en uppf\u00f6rsbacke att bryta ut och skapa \u00e5teranv\u00e4ndbar kod d\u00e5 dessa ocks\u00e5 blir likv\u00e4rdiga procedurer som allt annat i det globala scopet utan n\u00e5got s\u00e4tt att kapsla in (g\u00f6mma) de i klasser, paket, moduler etc.<\/li>\n<\/ul>\n\n\n\n<p>Det \u00e4r konstigt att fj\u00e4rde generationens spr\u00e5k som var f\u00f6rhoppningen till framtida b\u00e4ttre mjukvara har blivit omk\u00f6rd av den tidigare generationens moderna verktyg och designm\u00f6nster, fast dessa spr\u00e5k \u00e4r \u00e4ldre.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Felhantering<\/h2>\n\n\n\n<p>En bra taktik i all systemutveckling \u00e4r  <a href=\"https:\/\/en.wikipedia.org\/wiki\/Fail-fast\">&#8221;fail-fast&#8221;.<\/a> Du vill allts\u00e5 att om minsta lilla grej g\u00e5r fel i en av dina allra st\u00f6rsta operationer som h\u00e4mtar och \u00e4ndrar data fr\u00e5n stora delar av din databas att koden direkt skall sluta k\u00f6ras, kasta fel som loggar vilken rad i din kod d\u00e4r undantaget uppstod och \u00e5terst\u00e4ll all data som hittills \u00e4ndrats till utg\u00e5ngsl\u00e4get. <\/p>\n\n\n\n<p>Du t\u00e4nker att detta \u00e4r varf\u00f6r vi har en databas och att en transaktion runt alla procedurer som skall k\u00f6ras l\u00f6ser detta? Njaa vi tar MS SQL Server som exempel p\u00e5 hur mycket detaljer man faktiskt beh\u00f6ver k\u00e4nna till f\u00f6r att inneh\u00e5llet i databasen inte skall bli &#8221;korrupt&#8221; (helt fel att s\u00e4ga korrupt).<\/p>\n\n\n\n<p>L\u00e4s lite grann i den h\u00e4r serien om tv\u00e5 tabeller som skall \u00e4ndras: <a href=\"https:\/\/www.brentozar.com\/archive\/2022\/01\/error-handling-quiz-week-tryin-try-catch\/\">Error Handling Quiz Week: Tryin\u2019 TRY\/CATCH<\/a><\/p>\n\n\n\n<p>F\u00f6r att ha en chans att f\u00e5 ett stabilt system skrivet med T-SQL d\u00e4r koden slutar k\u00f6ras vid fel beh\u00f6ver du allts\u00e5 ha try-catch runt all din kod, hela tiden, i varje procedur. Men:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>So to recap, TRY\/CATCH doesn\u2019t catch small problems or big problems \u2013 only medium-sized problems.<\/p>\n<\/blockquote>\n\n\n\n<p>Ok, s\u00e5 vi l\u00e4gger till transaktioner. Men:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>I know, right? You thought that by combining try\/catch with a transaction, you\u2019d get robust error handling. &nbsp;Instead, you ended up with half the tables populated, and a leftover open transaction. You\u2019d already forgotten Tuesday\u2019s post in which I pointed out that TRY\/CATCH doesn\u2019t catch low severity or high severity errors.<\/p>\n<\/blockquote>\n\n\n\n<p>Du beh\u00f6ver tydligen komma ih\u00e5g att l\u00e4gga till n\u00e5gon grej som heter XACT_ABORT \u00f6verallt hela tiden:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>We start with the XACT_ABORT option which increases our odds that entire transactions are rolled back or forwards together. However, that alone still may not be enough \u2013 remember Tuesday\u2019s post where I talked about how some catastrophic errors skip the CATCH block altogether<\/p>\n<\/blockquote>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>For good error handling in SQL Server, you need both TRY-CATCH and SET XACT_ABORT ON. Of these two, SET XACT_ABORT ON is the most important. For production-grade code it&#8217;s not really sufficient to rely on XACT_ABORT, but for quick and simple stuff it can do.<\/p>\n<cite><a href=\"https:\/\/www.sommarskog.se\/error_handling\/Part1.html\">Error and Transaction Handling in SQL Server<\/a><\/cite><\/blockquote>\n\n\n\n<p>Det \u00d6KAR (!?) chansen att det kommer fungera? <\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Fels\u00f6kning<\/h2>\n\n\n\n<p>Det finns ett ansvar hos utvecklare att skapa icke-funktionella f\u00f6ruts\u00e4ttningar f\u00f6r att kunna observera systemet under drift samt fels\u00f6ka det djupare i testb\u00e4nk. <\/p>\n\n\n\n<p>Den st\u00f6rsta klassikern f\u00f6r fels\u00f6kning \u00e4r att s\u00e4tta en breakpoint och stega genom koden samtidigt som du unders\u00f6ker v\u00e4rdet p\u00e5 variablerna i programmet. Hur g\u00f6r vi detta i SQL server? Det g\u00f6r vi inte. Det fanns tidigare i SSMS men har nu tagits bort. <a href=\"https:\/\/www.brentozar.com\/archive\/2023\/01\/3-ways-to-debug-t-sql-code\/\" data-type=\"URL\" data-id=\"https:\/\/www.brentozar.com\/archive\/2023\/01\/3-ways-to-debug-t-sql-code\/\">Brent Ozar f\u00f6resl\u00e5r<\/a> ist\u00e4llet att k\u00f6ra lite olika varianter av att &#8221;skriva till konsolen&#8221;. <\/p>\n\n\n\n<p>Det som oftast hj\u00e4lper mig att l\u00f6sa problem i ett system \u00e4r om hela stackens sp\u00e5rning sparas ut till systemets logg. H\u00e4r ses uppifr\u00e5n och ned vad f\u00f6r typ av fel det var som avbr\u00f6t anropskedjan och d\u00e4refter listas varje klass och vilken rad i koden d\u00e4r f\u00f6ljande funktionsanrop gjordes f\u00f6r att komma dit d\u00e4r det sm\u00e4llde. Det \u00e4r fantastiskt att kunna f\u00e5 automatiskt vilken rad i koden problemet befinner sig p\u00e5! Raden blir mer exakt ju h\u00e5rdare fail-fast g\u00f6rs.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"900\" height=\"347\" src=\"http:\/\/localhost:8081\/wp-content\/uploads\/2023\/04\/eclipse_75EyDw1zwv.png\" alt=\"\" class=\"wp-image-319\" srcset=\"https:\/\/djax.se\/wp-content\/uploads\/2023\/04\/eclipse_75EyDw1zwv.png 900w, https:\/\/djax.se\/wp-content\/uploads\/2023\/04\/eclipse_75EyDw1zwv-300x116.png 300w, https:\/\/djax.se\/wp-content\/uploads\/2023\/04\/eclipse_75EyDw1zwv-768x296.png 768w\" sizes=\"auto, (max-width: 900px) 100vw, 900px\" \/><\/figure>\n\n\n\n<p>I Eclipse trycker jag enkelt p\u00e5 &#8221;Kantela.java:111&#8221; som tar mig direkt till rad 111 i klassen d\u00e4r undantaget kastades. Jag ser p\u00e5 metodnamnet innan p\u00e5 rad 219 att n\u00e5got g\u00e5tt fel n\u00e4r ett dubbelklick gjorts. Tyv\u00e4rr k\u00e4nner jag inte till n\u00e5got s\u00e4tt att f\u00e5 denna superkraft i SQL server d\u00e4r jag t\u00e4nker mig att jag vill ha en lista med varje procedur som anropades samt vilken rad f\u00f6ljande anropades vid.<\/p>\n\n\n\n<p>Prestandan i systemet \u00e4r sv\u00e5r att m\u00e4ta n\u00e4r alla anv\u00e4ndare som sitter p\u00e5 respektive klient n\u00e4r som helst (och i olika konstellationer) skickar mer eller mindre resurskr\u00e4vande SQL fr\u00e5gor direkt till databasen utan n\u00e5gon m\u00f6jlighet att aktivt k\u00f6a, prioritera eller rent av neka (f\u00f6r stunden) oviktiga f\u00f6rfr\u00e5gningar. <\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Kontinuerlig utveckling<\/h2>\n\n\n\n<p>Det vedertagna s\u00e4ttet att v\u00e4va in en relationsdatabas i sitt systems kontinuerliga utveckling \u00e4r med hj\u00e4lp av migrationer som tar databasens schema till den aktuella versionen. F\u00f6rslagsvis med verktyg som <a href=\"https:\/\/github.com\/flyway\/flyway\">Flyway<\/a>.<\/p>\n\n\n\n<p>Dock \u00e4r dessa verktyg b\u00e4sta p\u00e5 att hantera delta \u00e4ndringar av sj\u00e4lva databas schemat. Men kan \u00e4ndringar av din aff\u00e4rslogik i SQL enkelt drifts\u00e4ttas p\u00e5 detta s\u00e4tt? Det \u00e4r inte allt f\u00f6r trevligt att skapa upp en procedur p\u00e5 ett antal hundra rader SQL i en migrering, f\u00f6r att sedan g\u00f6ra en mindre \u00e4ndring p\u00e5 en enstaka rad men \u00e4nd\u00e5 bli tvingad att droppa och skapa upp hela proceduren med alla sina rader i en framtida migrering.<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>because stored procedures are deployed separately from the application, and, because there is usually only one database master, the deployment of stored procedures is usually done separately from application deployments and by separate staff<\/p>\n<cite><a href=\"https:\/\/medium.com\/@JoeEmison\/stored-procedures-as-a-litmus-test-c7ec772b985e\">https:\/\/medium.com\/@JoeEmison\/stored-procedures-as-a-litmus-test-c7ec772b985e<\/a><\/cite><\/blockquote>\n\n\n\n<p>Ett annat vanligt f\u00f6rekommande arbetss\u00e4tt \u00e4r att sonika \u00e4ndra direkt i produktionsmilj\u00f6n (kanske med sina initialer och datum) och manuellt klippa och klistra in \u00e4ndringarna (senare) i versionshanteringssystemet. H\u00e4r s\u00e4tts migreringar, versionshantering och f\u00f6rm\u00e5gan att resonera kring systemets samlade komponenter ur spel n\u00e4r det inte l\u00e4ngre g\u00e5r att peka p\u00e5 systemet och s\u00e4ga &#8221;jag vet exakt vad som k\u00f6rs h\u00e4r&#8221;, det \u00e4r denna commit. <\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>In contrast, ORMs are just part of regular application code and don\u2019t create any dependencies or requirements on any IT staff beyond whatever existing dev\/test\/QA\/prod processes already exist for the application servers<\/p>\n<cite><a href=\"https:\/\/medium.com\/@JoeEmison\/stored-procedures-as-a-litmus-test-c7ec772b985e\">https:\/\/medium.com\/@JoeEmison\/stored-procedures-as-a-litmus-test-c7ec772b985e<\/a><\/cite><\/blockquote>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Vad s\u00e4ger litteraturen?<\/h2>\n\n\n\n<p>S\u00e5 h\u00e4r s\u00e4ger en kursbok som anv\u00e4nds p\u00e5 minst ett svenskt l\u00e4ros\u00e4te:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large is-style-default\"><img decoding=\"async\" src=\"https:\/\/djax.se\/blog\/wp-content\/uploads\/2023\/02\/wp-1676622444963-scaled-1-1024x771.jpg\" alt=\"\" class=\"wp-image-198\"\/><\/figure>\n\n\n\n<p>&#8221;B\u00e4ttre systemstruktur (punkt)&#8221; \ud83e\udd28. Se n\u00e4sta sektion ang\u00e5ende konsistenta uppdateringar och fantomer.<\/p>\n\n\n\n<p><strong>Kontroll av indata<\/strong> \u00e4r mycket viktigt och om du v\u00e4ljer att g\u00f6ra det i T-SQL f\u00e5r du automatiskt hj\u00e4lp av korta av alla dina str\u00e4ngar automatiskt (sarkasm) till r\u00e4tt l\u00e4ngd innan de stoppas in i tabellen: <a href=\"https:\/\/stackoverflow.com\/questions\/4628140\/sql-server-silently-truncates-varchars-in-stored-procedures\">SQL Server silently truncates varchar&#8217;s in stored procedures<\/a>.  <\/p>\n\n\n\n<p>Om vi nu skall anv\u00e4nda SQL som programmeringsspr\u00e5k \u00e4r det otroligt att variabler tyst kan f\u00f6r\u00e4ndras n\u00e4r de skickas med som argument till en procedur. I ett vanligt spr\u00e5k intr\u00e4ffar inte denna klass av problem och str\u00e4ngen kunde ocks\u00e5 omslutas i ett l\u00e4mpligt dom\u00e4nklass d\u00e4r en instans av detta objekt ist\u00e4llet kunde skickas till funktionen och p\u00e5 s\u00e5 s\u00e4tt f\u00e5 en <a href=\"https:\/\/www.typescriptlang.org\/docs\/handbook\/2\/everyday-types.html#literal-types\" data-type=\"URL\" data-id=\"https:\/\/www.typescriptlang.org\/docs\/handbook\/2\/everyday-types.html#literal-types\">typs\u00e4kerhet <\/a>vid kompileringen att r\u00e4tt form av data anv\u00e4nds i alla anrop runtom i kodbasen.<\/p>\n\n\n\n<p>Till en bra klient f\u00f6rv\u00e4ntas validering g\u00f6ras kontinuerligt med feedback per f\u00e4lt allt eftersom anv\u00e4ndaren matar in data. Finns ingen l\u00e4ngre som vill v\u00e4nta p\u00e5 resultatet av en procedur i databasen.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Hur skall vi g\u00f6ra ist\u00e4llet?<\/h2>\n\n\n\n<p>Fundera p\u00e5 vad du vill att databasens uppgift skall vara. Det fr\u00e4msta problemet det h\u00e4r stora beroendet du lyfter in i din arkitektur skall l\u00f6sa \u00e4r att bibeh\u00e5lla informationen i systemet vid en omstart. Helst skall bara det n\u00f6dv\u00e4ndigaste lagras som beh\u00f6vs f\u00f6r att starta upp systemet igen. Annan information kan ber\u00e4knas fram vid behov i minnet.<\/p>\n\n\n\n<p>Undvik triggers, stored procedures och annan funktionalitet databasmotorn erbjuder som ett s\u00e4tt att representera funktionalitet. Se SQL som ett<a href=\"https:\/\/lostechies.com\/chadmyers\/2008\/02\/22\/sql-is-the-assembly-language-of-the-modern-world\/\"> assembly spr\u00e5k som kan tas till <\/a>n\u00e4r den sista extra prestandan m\u00e5ste kl\u00e4mmas ut.<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>Our goal should be to get out of the SQL crafting business and get back into the data access business.<\/p>\n<cite><a href=\"https:\/\/lostechies.com\/chadmyers\/2008\/02\/22\/sql-is-the-assembly-language-of-the-modern-world\/\">SQL is the assembly language of the modern world<\/a><\/cite><\/blockquote>\n\n\n\n<p>Fundera p\u00e5 om <a href=\"https:\/\/www.unixsheikh.com\/articles\/sqlite-the-only-database-you-will-ever-need-in-most-cases.html\">allt du kanske beh\u00f6ver<\/a> \u00e4r SQLite. G\u00e5r utm\u00e4rkt att anv\u00e4nda som lagring i webbaserade system med flera anv\u00e4ndare. SQLite har ocks\u00e5 isolations niv\u00e5n <a href=\"https:\/\/www.sqlite.org\/isolation.html\">SERIALIZABLE <\/a>vilket \u00e4r det s\u00e4tt man kan tro alla databaser fungerar p\u00e5. Annars rekommenderas att<a href=\"https:\/\/fauna.com\/blog\/introduction-to-transaction-isolation-levels\"> l\u00e4sa p\u00e5 om detta<\/a> s\u00e5 ingen fantom kommer och tar dig.<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>Furthermore, even if you could know exactly which concurrency bugs are possible for a particular isolation level, writing an application in a way that these bugs will not happen in practice (or if they do, that they will not cause negative experiences for the users of the application) is also very challenging<\/p>\n<\/blockquote>\n\n\n\n<p>Som standard anv\u00e4nder allts\u00e5 de flesta databasmotorer n\u00e5gon form av svag isolation mellan andra samtidiga l\u00e4sningar och skrivningar. Detta g\u00f6r att en form av &#8221;<a href=\"https:\/\/en.wikipedia.org\/wiki\/Race_condition#In_software\">race condition<\/a>&#8221; kan g\u00f6ra att tillst\u00e5nd som inte borde kunna representeras (enligt schema och applikation) \u00e4nd\u00e5 i enstaka fall, beroende p\u00e5 vad som h\u00e4nder i \u00f6vrigt i systemet, lyckas skrivas till disk.<\/p>\n\n\n\n<figure class=\"wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio\"><div class=\"wp-block-embed__wrapper\">\n<iframe loading=\"lazy\" title=\"&quot;Transactions: myths, surprises and opportunities&quot; by Martin Kleppmann\" width=\"500\" height=\"281\" src=\"https:\/\/www.youtube.com\/embed\/5ZjhNTM8XU8?start=594&#038;feature=oembed\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share\" referrerpolicy=\"strict-origin-when-cross-origin\" allowfullscreen><\/iframe>\n<\/div><\/figure>\n\n\n\n<p>Datan blir &#8221;korrupt&#8221; fick jag h\u00f6ra en g\u00e5ng, men systemet g\u00f6r faktiskt precis det de \u00e4r designat f\u00f6r under r\u00e5dande inst\u00e4llningar, och datan ligger d\u00e4r p\u00e5 disk korrekt representerad, dock i sammanhanget i ett tillst\u00e5nd ingen kunnat f\u00f6rutse.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Fast SQL \u00e4r bra<\/h2>\n\n\n\n<p>Jag har stor respekt f\u00f6r hur kraftfullt SQL \u00e4r som datarelaterat spr\u00e5k och anv\u00e4nder det g\u00e4rna. Ett genomt\u00e4nkt schema och lite SQL kunskap kommer man l\u00e5ngt p\u00e5. <\/p>\n\n\n\n<p>Vi beh\u00f6ver n\u00e5gonstans att lagra information och det g\u00f6rs b\u00e4st i en databas med SQL. Att databaser \u00e4r komplexa kommer fr\u00e5n att kompromisser beh\u00f6ver g\u00f6ras f\u00f6r att g\u00f6ra de tillr\u00e4ckligt snabba samtidigt som de \u00e4r tillr\u00e4ckligt konsistenta.<\/p>\n\n\n\n<p>F\u00f6r vissa uppgifter \u00e4r SQL en bra abstraktion men att anv\u00e4nda det som generellt programmeringsspr\u00e5k \u00e4r att anv\u00e4nda hammare som enda verktyg. Och d\u00e5 blir alla problem en spik. Synd n\u00e4r det ocks\u00e5 (n\u00e4stan) alltid \u00e4r databasen som \u00e4r flaskhalsen.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Mera l\u00e4sning<\/h2>\n\n\n\n<p><a href=\"https:\/\/thomaslarock.com\/2018\/07\/databases-101\/\" data-type=\"URL\" data-id=\"https:\/\/thomaslarock.com\/2018\/07\/databases-101\/\">Databases 101<\/a><\/p>\n\n\n\n<p><a href=\"https:\/\/medium.com\/@JoeEmison\/stored-procedures-as-a-litmus-test-c7ec772b985e\">Stored Procedures as a Litmus Test<\/a><\/p>\n\n\n\n<p><a href=\"https:\/\/blog.codinghorror.com\/who-needs-stored-procedures-anyways\/\">Who Needs Stored Procedures, Anyways?<\/a><\/p>\n\n\n\n<p><a href=\"https:\/\/stackoverflow.com\/questions\/1761601\/is-the-usage-of-stored-procedures-a-bad-practice\">Is the usage of stored procedures a bad practice?<\/a><\/p>\n\n\n\n<p><a href=\"https:\/\/fly.io\/blog\/sqlite-internals-rollback-journal\/\" data-type=\"URL\" data-id=\"https:\/\/fly.io\/blog\/sqlite-internals-rollback-journal\/\">How SQLite Helps You Do ACID<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Mjukvara \u00e4r skriven i programmeringsspr\u00e5k. Dessa spr\u00e5k delas upp p\u00e5 olika s\u00e4tt som h\u00f6g- och l\u00e5gniv\u00e5 eller i generationer som &#8221;fj\u00e4rde generationens spr\u00e5k&#8221;. SQL \u00e4r ett s\u00e5dant &#8221;fj\u00e4rde generationens&#8221; spr\u00e5k. Tanken var att kunna beskriva vad som \u00f6nskas fr\u00e5n datorn ist\u00e4llet f\u00f6r p\u00e5 ett exakt vis koda hur informationen skall samlas ihop p\u00e5. G\u00e4rna att [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":205,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[5],"tags":[],"class_list":["post-30","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-systemutveckling"],"_links":{"self":[{"href":"https:\/\/djax.se\/index.php?rest_route=\/wp\/v2\/posts\/30","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/djax.se\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/djax.se\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/djax.se\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/djax.se\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=30"}],"version-history":[{"count":0,"href":"https:\/\/djax.se\/index.php?rest_route=\/wp\/v2\/posts\/30\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/djax.se\/index.php?rest_route=\/wp\/v2\/media\/205"}],"wp:attachment":[{"href":"https:\/\/djax.se\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=30"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/djax.se\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=30"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/djax.se\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=30"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}