<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: dr_gos(☕ 💻)</title>
    <description>The latest articles on DEV Community by dr_gos(☕ 💻) (@drgos_dev).</description>
    <link>https://dev.to/drgos_dev</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1120786%2F2cbbb6cc-8c62-43c1-af5f-42ccf11bffcd.png</url>
      <title>DEV Community: dr_gos(☕ 💻)</title>
      <link>https://dev.to/drgos_dev</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/drgos_dev"/>
    <language>en</language>
    <item>
      <title>Browser Quest: Finding the Perfect Alternative to Arc Browser</title>
      <dc:creator>dr_gos(☕ 💻)</dc:creator>
      <pubDate>Sun, 05 Jan 2025 22:37:54 +0000</pubDate>
      <link>https://dev.to/drgos_dev/beyond-arc-my-journey-through-alternative-browsers-39cn</link>
      <guid>https://dev.to/drgos_dev/beyond-arc-my-journey-through-alternative-browsers-39cn</guid>
      <description>&lt;p&gt;You know that feeling when you're ready for a change, but you're not quite sure what you want? That's where I found myself with Arc Browser. Don't get me wrong – Arc is innovative and beautiful, but sometimes you need to explore what else is out there. So I embarked on a month-long browser-shopping spree that took me through some fascinating alternatives. Here's what I discovered.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Browser Wishlist: More Than Just Pretty Tabs
&lt;/h2&gt;

&lt;p&gt;Before diving into alternatives, I sat down and really thought about what matters in a modern browser:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Resource efficiency, I want to be able to browse the internet for a long time.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Vertical tabs that actually make sense (not just tacked on as an afterthought)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Rock-solid &lt;strong&gt;security&lt;/strong&gt; and &lt;strong&gt;privacy&lt;/strong&gt; features&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Support for my essential extensions, my carefully curated collection of tools.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Smart workspace management because my brain works better with organized chaos&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Native-feeling performance&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Sounds simple enough, right? Well, buckle up – this journey got interesting fast.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://zen-browser.app" rel="noopener noreferrer"&gt;Zen Browser: The Beautiful But Complicated Date&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F99mmn219expayt205amc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F99mmn219expayt205amc.png" alt="Zen Browser" width="800" height="605"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;First up was Zen Browser, which caught my eye with its stunning Firefox-based interface. It's like someone took Firefox to a design workshop and came back with a masterpiece.&lt;/p&gt;

&lt;p&gt;What made me swoon:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Those gorgeous design and vertical tabs that look stunning.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Workspaces that actually understand how people work&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A split-view system that makes research feel natural&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;"Zen Glance" preview feature (goodbye, risky clicks!)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Powerful theming through "Zen Mods"&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Firefox's battle-tested privacy features&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A treasure trove of Firefox extensions&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But then reality hit. No DRM support meant saying goodbye to some streaming services, and Google Meet (a daily necessity) performed like it was running on a potato. It's like dating someone who looks perfect on paper but snores like a chainsaw – some deal-breakers you just can't ignore.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://vivaldi.com" rel="noopener noreferrer"&gt;Vivaldi: The Overly Customizable Ex&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://vivaldi.com" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffkfbs6ozuv2fg61v6cn0.png" alt="Vivaldi" width="800" height="426"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Remember that friend who got really into modding their car and now can't stop talking about torque ratios? That's Vivaldi. It's incredibly powerful, but sometimes power isn't everything.&lt;/p&gt;

&lt;p&gt;I tried the custom CSS route with themes like &lt;a href="https://github.com/tovifun/VivalArc" rel="noopener noreferrer"&gt;VivalArc&lt;/a&gt; and &lt;a href="https://github.com/HKayn/vivaldi-vh/" rel="noopener noreferrer"&gt;Vivaldi VH&lt;/a&gt;. The results looked amazing, but maintaining custom CSS felt like adopting a high-maintenance pet – one that needs attention after every single update. It's the browser equivalent of dating someone who needs you to compliment their outfit five times before leaving the house.&lt;/p&gt;

&lt;p&gt;Don’t get me wrong, the browser is great, it feature packed, and it was my main browser for a week. I even created &lt;a href="https://homepage.drgos.com" rel="noopener noreferrer"&gt;homepage.drgos.com&lt;/a&gt; to be my homepage for it. But i don’t want to tinker with it that often, that what i was feeling like, everyday making a small change.&lt;/p&gt;

&lt;p&gt;Dear &lt;strong&gt;Vivaldi team&lt;/strong&gt;: How about letting users share complete configurations? Reducing the barrier to entry for new users and letting existing users be your megaphone. Imagine clicking once to import someone's perfect setup instead of spending hours in settings menus. Do some competitions on X.com or Reddit and give some prize for the ones with the most votes. Just a thought!&lt;br&gt;
(make sure to disable CSS url requests to avoid hacks)&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://sigmaos.com" rel="noopener noreferrer"&gt;SigmaOS: The Productivity Guru Next Door&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe5oc1jq5gl99btz58jvs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe5oc1jq5gl99btz58jvs.png" alt="SigmaOS Broswer" width="800" height="508"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Walking into SigmaOS feels like entering a minimalist's dream office. Everything has its place, and there's a place for everything. It's not just another browser; it's a complete reimagining of how we should interact with the web.&lt;/p&gt;

&lt;p&gt;The standout features read like a productivity wishlist:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Workspaces that feel like well-organized rooms in a digital house&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Airis AI assistant that i haven’t used, so i can’t say anything about it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Breadcrumb navigation that maps your diving expeditions into Wikipedia&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Universal "Lazy Search" that finds anything, anywhere (because who has time to remember where they saw that thing?)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Dynamic theming that plays nice with every website&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Built-in ad blocking that doesn't break sites&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Team collaboration tools that don't feel bolted on&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Using SigmaOS feels like having a personal assistant who organizes your digital life while you sleep. It's perfect for those who color-code their calendar and alphabetize their spice rack.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://kagi.com/orion/" rel="noopener noreferrer"&gt;Orion Browser: The Unexpected Perfect Match&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk98v9kbu6zia3ltfqsag.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk98v9kbu6zia3ltfqsag.png" alt="Orion Browser" width="800" height="495"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Sometimes the best things in life come from unexpected places. Enter Orion Browser, I discoverd it through a youtube video recommandation. It’s built on WebKit, similar to SigmaOS. It's like finding out that quiet person at work is actually the most interesting one there.&lt;/p&gt;

&lt;p&gt;What makes Orion special:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Speed - the browser feels really snappy and fast.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The holy grail of extension support Chrome AND Firefox. But some extensions might not work as expected. Luckly the 4 extentions that i use are compatible.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Vertical tabs that feel natural, not forced with breadcrumbs&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Mac integration that feels like it came from Apple itself especially when in compact mode.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Transform websited into native apps.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Picture in picture when you want to watch youtube while working on that document.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Privacy features or at least they advertise that.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Dynamic theming - it’s more of a miss for me, but it’s not a deal breaker. SigmaOS dynamic theming is better.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Even the Google Meet issue (no virtual backgrounds) had a simple fix using macOS features. It's these thoughtful solutions that make Orion feel like home.&lt;br&gt;&lt;br&gt;
Also i like a lot more the way share screen / tab looks on webkit than on Chromium.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Surprising Discovery: The Search Engine Renaissance
&lt;/h2&gt;

&lt;p&gt;During this browser adventure, I stumbled into another rabbit hole – the world of alternative search engines. Turns out, while we've all been googling away, a whole ecosystem of innovative search tools has evolved.&lt;/p&gt;

&lt;p&gt;There's Kagi (made by the Orion folks) with its privacy-first approach, &lt;a href="http://You.com" rel="noopener noreferrer"&gt;You.com&lt;/a&gt; with its AI-powered results, Perplexity for those who want ChatGPT-style answers to everything, Phind for developers who need technical answers fast with AI ofc, and even Brave Search building its own independent index and a lot more. I know that everyone knows DuckDuckGo, but there are a lot more search engines out there.&lt;/p&gt;

&lt;p&gt;Each one brings something unique to the table. I’m not the biggest fan of Perplexity and You.com as main search engine, even though i use them from time to time. Especially when i want to buy some product and I want to compare multiple options.&lt;/p&gt;

&lt;p&gt;Kagi caught my attention with its promise of unfiltered, ad-free results, so I'm giving it a trial run. Who knows? Maybe finding the right search engine is just as important as finding the right browser.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Happy Ending
&lt;/h2&gt;

&lt;p&gt;After weeks of testing and probably confusing every website's tracking algorithms, I've settled into &lt;strong&gt;Orion Browser&lt;/strong&gt;. It hits that sweet spot between innovation and stability, power and simplicity. It's like finding the perfect coffee shop – not too busy, not too quiet, with just the right amount of character.&lt;/p&gt;

&lt;p&gt;I will keep SigmaOS installed so that i can give Airis AI a try.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Takeaways
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The perfect browser isn't about having every feature – it's about having the right features&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Beautiful design needs to be backed by solid performance&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Sometimes the best solution comes from the most unexpected place&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Privacy and functionality aren't mutually exclusive&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The browser market is more exciting than it's been in years. For a while i thought that everything will go Chromium, I’m exited to see that Firefox and WebKit hang in there.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Words of Wisdom
&lt;/h2&gt;

&lt;p&gt;Finding your ideal browser is like finding your favorite pair of jeans – what works perfectly for one person might be completely wrong for another. Don't be afraid to experiment, and remember that it's okay to change your mind as your needs evolve.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;P.S. Remember, the "perfect" browser today might not be perfect tomorrow. Technology evolves, our needs change, and that's okay. The joy is in the journey of discovery – and having a reliable browser to help you along the way!&lt;/em&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>browser</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Deep Diving the SQL Iceberg - Level 0: Sky Zone</title>
      <dc:creator>dr_gos(☕ 💻)</dc:creator>
      <pubDate>Mon, 27 Nov 2023 02:47:09 +0000</pubDate>
      <link>https://dev.to/drgos_dev/deep-diving-the-sql-iceberg-level-0-sky-zone-50gk</link>
      <guid>https://dev.to/drgos_dev/deep-diving-the-sql-iceberg-level-0-sky-zone-50gk</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"Deep Diving the SQL Iceberg" is a blog series designed to demystify the submerged complexities of SQL databases. Taking this educational journey I hope to become more proficient in the field of database technology, focusing on PostgreSQL as the exemplar. Each post will surface a few concepts from the vast array of topics encapsulated in the&lt;/em&gt; &lt;a href="https://x.com/largedatabank/status/1559651463919452161?s=20" rel="noopener noreferrer"&gt;&lt;em&gt;"SQL Iceberg" by Jordan Lewis&lt;/em&gt;&lt;/a&gt; &lt;em&gt;meme—from foundational elements like "JOIN" and "indexes" to advanced intricacies such as "query plans and EXPLAIN" and "The Halloween Problem."&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I've seen firsthand that the Achilles' heel of many web applications often lies in suboptimal database architecture and interaction, or in flawed API design(topic for another series). My objective is to deepen my expertise and evolve as a professional and as an architect. By making my insights and discoveries accessible to others, I aspire not only to enhance my own skills but also to potentially assist others on similar quests for improvement.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Thanks to &lt;a href="https://x.com/largedatabank/status/1559651463919452161?s=20" rel="noopener noreferrer"&gt;Jordan Lewis &amp;amp; friends for creating the "SQL Iceberg"&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Most images are generated by ChatGPT&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h1&gt;
  
  
  Level 0: Sky Zone
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvhyaesq1914l7daur0l9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvhyaesq1914l7daur0l9.png" alt="Image description" width="800" height="134"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Concepts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;ORMs&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;data types&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;CREATE TABLE&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;indexes&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;foreign keys&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;SELECT / INSERT / UPDATE / DELETE&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;JOIN&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;ORDER BY / GROUP BY&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;LIMIT and OFFSET&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;NULL&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  ORMs &lt;strong&gt;(Object-Relational Mapping)&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9uococjycwakzfw16img.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9uococjycwakzfw16img.png" alt="Image description" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Definition:&lt;/strong&gt; ORMs are programming libraries that facilitate the conversion of data between incompatible type systems in object-oriented programming languages and relational databases. They enable developers to interact with a database using high-level programming constructs instead of direct SQL queries.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt; In the context of PostgreSQL, an ORM like Hibernate (Java) or Sequelize (Node.js) can be used. For instance, using Sequelize, you can define a model for a table &lt;code&gt;users&lt;/code&gt; like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;sequelize&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;define&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Sequelize&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;INTEGER&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;primaryKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Sequelize&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;STRING&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Pros of Using ORMs&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Abstraction from SQL:&lt;/strong&gt; ORMs abstract away the complexity of raw SQL queries, allowing developers to interact with the database using the object-oriented paradigm of their programming language.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Increased Productivity:&lt;/strong&gt; By automating the task of writing SQL queries and handling database connections, ORMs can significantly speed up the development process, especially for standard database operations.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Database Agnosticism:&lt;/strong&gt; ORMs often allow applications to become largely independent of the underlying database system. This means you can switch databases with minimal changes in the application code.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Automated Schema Management:&lt;/strong&gt; &lt;em&gt;Many ORMs&lt;/em&gt; provide tools for automatically generating and updating database schemas based on the object model, which can simplify migrations and schema changes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Support for Complex Relationships and Operations:&lt;/strong&gt; ORMs generally provide a straightforward way to handle complex joins, nested selects, and transactions.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Cons of Using ORMs&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Performance Overhead:&lt;/strong&gt; ORMs add an extra layer of abstraction which can lead to performance issues, especially with large datasets or complex queries. The automatically generated SQL might not be as optimized as hand-written queries.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Complex Queries Can Be Challenging:&lt;/strong&gt; For complex database operations, ORM queries can become cumbersome and less efficient than native SQL. Sometimes, the abstraction can limit the ability to perform certain highly specialized operations.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Steep Learning Curve:&lt;/strong&gt; While ORMs simplify database interactions, they often have their own complexities. Learning to use an ORM effectively can require a significant investment of time and effort.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Less Control Over the Execution:&lt;/strong&gt; ORMs tend to hide the details of data retrieval and manipulation, which can be a disadvantage when fine-tuning queries for performance optimizations.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Potential for Poor Database Design:&lt;/strong&gt; Relying heavily on ORMs can sometimes lead to suboptimal database design, as the database schema is often a reflection of the object model, which may not always be the most efficient representation of the data.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In summary, while ORMs offer a high level of convenience and productivity gains, especially for standard CRUD (Create, Read, Update, Delete) operations, they also introduce complexities and performance considerations.&lt;/p&gt;

&lt;p&gt;One of the main reasons for starting this series is my frustration with ORNs. They provide a great medium for inserting data. However, abstracting the queries makes the developers &lt;strong&gt;not&lt;/strong&gt; think about the impact that each call has on the overall performance of the application. I've encountered far too often queries called inside a loop or the famous &lt;a href="https://stackoverflow.com/a/97253/4278407" rel="noopener noreferrer"&gt;n+1 problem&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;RECOMMENDATION&lt;/strong&gt;: use ORMs for inserting data and basic queries but switch to native queries for more complex stuff and use the ORM mapping capabilities to convert the result to entities or projection objects. Be careful with &lt;em&gt;eager&lt;/em&gt; and &lt;em&gt;lazy&lt;/em&gt; fetching and what data you need in your business logic.&lt;/p&gt;

&lt;h2&gt;
  
  
  Data types
&lt;/h2&gt;

&lt;p&gt;To be honest I don't think there is a need for me to write about SQL data types. Depending on what database you use you can easily find the information in their documentation. &lt;a href="https://www.postgresql.org/docs/current/datatype.html" rel="noopener noreferrer"&gt;Here is a link for PostgreSQL&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;A few recommendations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Floating-Point Precision:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Be cautious with floating-point types (&lt;code&gt;REAL&lt;/code&gt; and &lt;code&gt;DOUBLE PRECISION&lt;/code&gt;). They can introduce rounding errors and are not suitable for storing exact values like monetary amounts.&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;DECIMAL&lt;/code&gt; or &lt;code&gt;NUMERIC&lt;/code&gt; for precise calculations where rounding errors are unacceptable. (Currency, etc)&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Character Types:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;VARCHAR(n)&lt;/code&gt; and &lt;code&gt;CHAR(n)&lt;/code&gt; have a performance difference: &lt;code&gt;CHAR(n)&lt;/code&gt; pads spaces to the defined length, which can increase storage usage unnecessarily for variable-length strings.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;TEXT&lt;/code&gt; and &lt;code&gt;VARCHAR&lt;/code&gt; are very similar, but &lt;code&gt;TEXT&lt;/code&gt; is preferable when you don't have a specific limit on string length. Internally, PostgreSQL treats &lt;code&gt;VARCHAR&lt;/code&gt; without a length specifier as &lt;code&gt;TEXT&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Date and Time Types:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Be mindful of timezone handling with &lt;code&gt;TIMESTAMP WITH TIME ZONE&lt;/code&gt; and &lt;code&gt;TIMESTAMP WITHOUT TIME ZONE&lt;/code&gt;. The former converts the stored time to the current timezone of the server, while the latter does not.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;DATE&lt;/code&gt;, &lt;code&gt;TIME&lt;/code&gt;, and &lt;code&gt;TIMESTAMP&lt;/code&gt; types have different precision levels and functions, and choosing the correct type for your needs is crucial.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Array Types:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;PostgreSQL supports arrays for most data types. However, managing and querying arrays can be more complex than simple scalar types.&lt;/li&gt;
&lt;li&gt;Use arrays judiciously, as they can complicate query writing and impact performance.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;JSON vs. JSONB:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;JSON&lt;/code&gt; and &lt;code&gt;JSONB&lt;/code&gt; are both used to store JSON data, but they behave differently. &lt;code&gt;JSONB&lt;/code&gt; stores data in a decomposed binary format, offering better performance for querying and indexing at the cost of slightly slower write times and more storage space.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;JSON&lt;/code&gt; preserves the exact input format, which might be necessary in some cases.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;UUID Type:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Using &lt;code&gt;UUID&lt;/code&gt; as a primary key can be beneficial for distributed systems, but it's larger and slower to generate compared to traditional integer types. &lt;a href="https://www.youtube.com/watch?v=f53-Iw_5ucA" rel="noopener noreferrer"&gt;Here is a great video about it&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  CREATE TABLE
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1s35zc3zdrk5iol9r3wv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1s35zc3zdrk5iol9r3wv.png" alt="Image description" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;CREATE TABLE&lt;/code&gt; command in SQL is used to create a new table in a specific database. This command defines the table structure, specifying the columns and the types of data each column can hold. It's akin to laying the blueprint for a building — you're setting the foundation and structure on which your data will reside.&lt;/p&gt;

&lt;h4&gt;
  
  
  Syntax and Usage
&lt;/h4&gt;

&lt;p&gt;The basic syntax of the &lt;code&gt;CREATE TABLE&lt;/code&gt; command is straightforward, yet powerful:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;employees&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="nb"&gt;SERIAL&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;email&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;UNIQUE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;join_date&lt;/span&gt; &lt;span class="nb"&gt;DATE&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, we create a table named &lt;code&gt;employees&lt;/code&gt; with four columns: &lt;code&gt;id&lt;/code&gt;, &lt;code&gt;name&lt;/code&gt;, &lt;code&gt;email&lt;/code&gt;, and &lt;code&gt;join_date&lt;/code&gt;. The &lt;code&gt;id&lt;/code&gt; column is a serial type, automatically incrementing and serving as the primary key.&lt;/p&gt;

&lt;h4&gt;
  
  
  Best Practices:
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Naming Conventions:&lt;/strong&gt; Use clear, descriptive names for tables and columns.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Normalizing Data:&lt;/strong&gt; Aim for a normalized database design to reduce data redundancy and improve data integrity.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Defining Constraints:&lt;/strong&gt; Use constraints wisely to enforce data integrity.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Planning for Scalability:&lt;/strong&gt; Consider how your tables will scale and perform as data grows. Thinking about sharding keys might come in handy.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Indexes
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsej1wzw6fgqlb8ua36yi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsej1wzw6fgqlb8ua36yi.png" alt="Image description" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Indexes in PostgreSQL are special database objects that are primarily used to improve the speed of data retrieval operations. Think of them like the index in a book - instead of reading the whole book to find a topic, you refer to the index to quickly locate the pages you need. In a database, indexes help the database server to find and retrieve specific rows much faster than it could do by scanning the entire table.&lt;/p&gt;

&lt;h4&gt;
  
  
  The Mechanism of Indexes on Insert Operations
&lt;/h4&gt;

&lt;p&gt;While indexes are widely known for enhancing query performance, their impact on data insertion is a critical aspect often overlooked. Here's what happens during an insert operation in a PostgreSQL table with indexes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Data Insertion and Index Update:&lt;/strong&gt; When a new record is inserted into a table, PostgreSQL not only saves this record into the table but also updates all the indexes that the table is associated with. Each index must reflect the change to ensure it remains accurate for read operations.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Movement and Sorting:&lt;/strong&gt; For certain types of indexes, particularly those like B-tree (the default in PostgreSQL), the new data must be correctly sorted into the existing structure. This might involve moving and rearranging data within the index to maintain its order and integrity.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Write Amplification:&lt;/strong&gt; Each additional index results in more write operations. This phenomenon, known as write amplification, can significantly impact the performance of insert operations, especially in write-heavy databases.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  Choosing the Right Indexes: A Balance Act
&lt;/h4&gt;

&lt;p&gt;Given the overhead indexes can create during data insertion, choosing the right indexes becomes a crucial decision. Here's why careful index selection is important:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Performance Trade-off:&lt;/strong&gt; Every index you add can improve query performance but might slow down data insertion. It's essential to strike a balance - create indexes that will benefit your most common and critical queries without overly hindering write operations.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Index Selectivity:&lt;/strong&gt; Highly selective indexes, where the index entries have unique or near-unique values, are generally more effective. They allow PostgreSQL to quickly narrow down the search to a few rows, enhancing query performance significantly.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Index Types Matter:&lt;/strong&gt; Different index types &lt;a href="https://www.postgresql.org/docs/current/indexes-types.html" rel="noopener noreferrer"&gt;(like B-tree (default), Hash, GIN, and GiST)&lt;/a&gt; have different characteristics and use cases. Understanding the nature of your data and queries can guide you to choose the most appropriate type.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Maintenance and Monitoring:&lt;/strong&gt; Regularly monitor the performance of your indexes. Unused or less frequently used indexes might be candidates for removal to improve write performance.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Partial Indexes:&lt;/strong&gt; In cases where you only query a subset of your data, consider using partial indexes. These indexes are smaller and faster to update, as they only index a portion of the table.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Foreign Keys
&lt;/h2&gt;

&lt;p&gt;Foreign keys in PostgreSQL are a type of constraint used to link two tables together. This link is based on the relationship between columns in these tables - typically, the primary key in one table becomes a foreign key in another. They play a crucial role in preventing invalid data entry and maintaining the consistency of data across tables.&lt;/p&gt;

&lt;h4&gt;
  
  
  When to Use Foreign Keys
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Enforcing Referential Integrity:&lt;/strong&gt; Use foreign keys when you need to ensure that a relationship exists between rows in different tables. For example, an &lt;code&gt;order&lt;/code&gt; should always be linked to a valid &lt;code&gt;customer&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Representing Relationships:&lt;/strong&gt; They are essential for representing real-world relationships in your database design, such as one-to-many or many-to-one relationships.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  Examples of Foreign Keys in Action
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;E-Commerce Database:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In an e-commerce database, you might have &lt;code&gt;customers&lt;/code&gt; and &lt;code&gt;orders&lt;/code&gt; tables.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;orders&lt;/code&gt; table can have a foreign key that references the &lt;code&gt;customer_id&lt;/code&gt; in the &lt;code&gt;customers&lt;/code&gt; table, ensuring that every order is associated with a valid customer.
&lt;/li&gt;
&lt;/ul&gt;

&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;customers&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;customer_id&lt;/span&gt; &lt;span class="nb"&gt;SERIAL&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;email&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;orders&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;order_id&lt;/span&gt; &lt;span class="nb"&gt;SERIAL&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;order_date&lt;/span&gt; &lt;span class="nb"&gt;DATE&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;customer_id&lt;/span&gt; &lt;span class="nb"&gt;INTEGER&lt;/span&gt; &lt;span class="k"&gt;REFERENCES&lt;/span&gt; &lt;span class="n"&gt;customers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;customer_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;




&lt;/li&gt;

&lt;/ul&gt;

&lt;h4&gt;
  
  
  Best Practices for Using Foreign Keys
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Careful Planning:&lt;/strong&gt; Design your database schema with the relationships between tables in mind. Ensure that foreign keys are used to enforce meaningful and necessary relationships.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Indexing Foreign Key Columns:&lt;/strong&gt; Indexes on foreign key columns can significantly improve the performance of joins and other queries that involve these columns.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Avoiding Cascade Deletes:&lt;/strong&gt; While cascade deletes can be convenient, they can also lead to unintentional loss of data. Use them judiciously and ensure that your application logic accounts for their effects.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Consistent Data Types:&lt;/strong&gt; Ensure that the data type of the foreign key column matches the data type of the referenced primary key column.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Regular Integrity Checks:&lt;/strong&gt; Periodically check the integrity of your relationships, especially if you perform bulk data operations that might bypass foreign key constraints.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Documenting Relationships:&lt;/strong&gt; Maintain clear documentation of your database schema, including the foreign key relationships. This aids in understanding the data model and troubleshooting issues.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Select / Insert / Update / Delete
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5e5hoeh1cecgbhyruf0y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5e5hoeh1cecgbhyruf0y.png" alt="Image description" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;SELECT, INSERT, UPDATE, and DELETE – are commands that form the core of data manipulation and querying.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The example I give in this section only scratches the surface, so I recommend that you read about the different operations from other sources. The most important part when it comes to these operations is time in the saddle. The more you need them the better you'll get at writing them.&lt;/em&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  1. SELECT - Fetching Data from the Database. &lt;a href="https://www.postgresql.org/docs/16/sql-select.html" rel="noopener noreferrer"&gt;(Postgres Docs)&lt;/a&gt;
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Usage:&lt;/strong&gt; The SELECT statement is used to query and retrieve data from a database table.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;customers&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This query retrieves the name and email columns from the customers table.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best Practices:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Avoid&lt;/strong&gt; &lt;code&gt;SELECT *&lt;/code&gt;: Instead of using &lt;code&gt;SELECT *&lt;/code&gt;, specify the columns you need. This reduces the data load, especially when the table has many columns.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Use WHERE for Filtering:&lt;/strong&gt; Leverage the &lt;strong&gt;WHERE&lt;/strong&gt; clause to filter data. This minimizes the amount of data processed and transferred.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  2. INSERT - Adding New Records
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Usage:&lt;/strong&gt; INSERT is used to add new rows to a table.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;INSERT&lt;/span&gt; &lt;span class="k"&gt;INTO&lt;/span&gt; &lt;span class="n"&gt;orders&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order_date&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;customer_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;VALUES&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'2023-01-15'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This adds a new order with the specified date and customer ID.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best Practices:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Specify Column Names:&lt;/strong&gt; Always specify column names for clarity and to avoid errors if the table structure changes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Use Batch Inserts for Multiple Rows:&lt;/strong&gt; For inserting multiple rows, use batch inserts to reduce the number of database round-trips.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  3. UPDATE - Modifying Existing Data
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Usage:&lt;/strong&gt; UPDATE modifies existing records in a table.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;UPDATE&lt;/span&gt; &lt;span class="n"&gt;orders&lt;/span&gt; &lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="n"&gt;order_date&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'2023-01-16'&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;order_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This changes the order date for the order with ID 1.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best Practices:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Be Specific with WHERE:&lt;/strong&gt; Always use a WHERE clause to target specific rows. Without it, you risk updating all rows in the table.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Limit the Scope:&lt;/strong&gt; When updating large tables, limit the scope of your update to avoid performance issues.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  4. DELETE - Removing Records
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Usage:&lt;/strong&gt; DELETE is used to remove rows from a table.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;DELETE&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;orders&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;order_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This deletes the order with ID 1 from the orders table.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best Practices:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Use WHERE with Caution:&lt;/strong&gt; Similar to UPDATE, always use a WHERE clause to specify which rows to delete.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Consider Using Soft Deletes:&lt;/strong&gt; Instead of physically deleting records, you can mark them as inactive. This allows for data recovery and audit trails.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Join
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnfjsb9vf5n7q0zlc0uen.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnfjsb9vf5n7q0zlc0uen.jpg" alt="Image description" width="800" height="629"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;JOINs are used to retrieve data from multiple tables by linking them through a common field. The most common types of JOINs are INNER JOIN, LEFT JOIN, RIGHT JOIN, and FULL OUTER JOIN.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://learnsql.com/blog/sql-joins/" rel="noopener noreferrer"&gt;&lt;em&gt;Here is a good article that explains it in detail.&lt;/em&gt;&lt;/a&gt; &lt;em&gt;The example I give in this section only scratches the surface, so I recommend that you read about joins from other sources. The most important part when it comes to these operations is time in the saddle. The more you need them the better you'll get at writing them.&lt;/em&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;INNER JOIN:&lt;/strong&gt; Selects records with matching values in both tables. Intersection between the two tables.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;LEFT (OUTER) JOIN:&lt;/strong&gt; Selects all records from the left table, and the matched records from the right table. For rows on the left that don't have a match on the right, &lt;code&gt;null&lt;/code&gt; will be placed instead.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;RIGHT (OUTER) JOIN:&lt;/strong&gt; Selects all records from the right table, and the matched records from the left table. For rows on the right that don't have a match on the left, &lt;code&gt;null&lt;/code&gt; will be placed instead.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;FULL (OUTER) JOIN:&lt;/strong&gt; Selects all records when there is a match in either the left or right table.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  Examples of JOINs
&lt;/h4&gt;

&lt;p&gt;Consider two tables in an e-commerce database: &lt;code&gt;customers&lt;/code&gt; and &lt;code&gt;orders&lt;/code&gt;. The &lt;code&gt;customers&lt;/code&gt; table contains customer information, and the &lt;code&gt;orders&lt;/code&gt; table contains order details.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;INNER JOIN Example:&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;Fetch all orders along with customer names.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;customers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;orders&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;order_id&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;customers&lt;/span&gt;
&lt;span class="k"&gt;INNER&lt;/span&gt; &lt;span class="k"&gt;JOIN&lt;/span&gt; &lt;span class="n"&gt;orders&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;customers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;customer_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;orders&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;customer_id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;LEFT JOIN Example:&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;Retrieve all customers and their orders, including customers who have not placed any orders.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;customers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;orders&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;order_id&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;customers&lt;/span&gt;
&lt;span class="k"&gt;LEFT&lt;/span&gt; &lt;span class="k"&gt;JOIN&lt;/span&gt; &lt;span class="n"&gt;orders&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;customers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;customer_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;orders&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;customer_id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;RIGHT JOIN Example:&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;Fetch all orders, including those not linked to a customer in the &lt;code&gt;customers&lt;/code&gt; table.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;customers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;orders&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;order_id&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;customers&lt;/span&gt;
&lt;span class="k"&gt;RIGHT&lt;/span&gt; &lt;span class="k"&gt;JOIN&lt;/span&gt; &lt;span class="n"&gt;orders&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;customers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;customer_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;orders&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;customer_id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;FULL JOIN Example:&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;Retrieve all records of customers and orders, with or without a match.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;customers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;orders&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;order_id&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;customers&lt;/span&gt;
&lt;span class="k"&gt;FULL&lt;/span&gt; &lt;span class="k"&gt;OUTER&lt;/span&gt; &lt;span class="k"&gt;JOIN&lt;/span&gt; &lt;span class="n"&gt;orders&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;customers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;customer_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;orders&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;customer_id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Best Practices for Using JOINs
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Use Specific Columns in SELECT:&lt;/strong&gt; Instead of using &lt;code&gt;SELECT *&lt;/code&gt;, specify the columns you need to retrieve. This enhances performance, especially in large tables.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Optimize ON Conditions:&lt;/strong&gt; Ensure that the ON condition in your JOIN is efficient and uses indexed columns if possible. This can significantly improve query performance.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Avoid Unnecessary JOINs:&lt;/strong&gt; Only JOIN tables that are essential for your query. Extra JOINs can complicate the query and degrade performance.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Understand the Data Model:&lt;/strong&gt; A clear understanding of the relationships between your tables is crucial. This helps in determining the right type of JOIN to use.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Be Aware of NULL Values:&lt;/strong&gt; In LEFT or RIGHT JOINs, if there is no match, the result set will contain NULLs. It’s important to handle these cases in your queries.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Use Aliases for Clarity:&lt;/strong&gt; When dealing with tables having similar column names, use aliases to make your query more readable and avoid confusion.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  ORDER BY / GROUP BY
&lt;/h2&gt;

&lt;p&gt;In SQL, two of the most powerful clauses for organizing and summarizing data are &lt;code&gt;ORDER BY&lt;/code&gt; and &lt;code&gt;GROUP BY&lt;/code&gt;. Both play a crucial role in data analysis and reporting.&lt;/p&gt;

&lt;h4&gt;
  
  
  ORDER BY: Sorting Your Data
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Functionality:&lt;/strong&gt; The &lt;code&gt;ORDER BY&lt;/code&gt; clause is used to sort the result set of a query by one or more columns. It can sort data in ascending (&lt;code&gt;ASC&lt;/code&gt;) or descending (&lt;code&gt;DESC&lt;/code&gt;) order. By default, &lt;code&gt;ORDER BY&lt;/code&gt; sorts in ascending order.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;department&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;salary&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;employees&lt;/span&gt;
&lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;department&lt;/span&gt; &lt;span class="k"&gt;ASC&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;salary&lt;/span&gt; &lt;span class="k"&gt;DESC&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This query sorts employees first by department in ascending order and then by salary in descending order within each department.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Be careful of:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Performance Overhead:&lt;/strong&gt; Sorting large datasets can be resource-intensive and slow down query execution.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Limited by Memory:&lt;/strong&gt; Extremely large sorts may exceed memory limits and require disk-based sorting, which is slower.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Best Practices:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Index Usage:&lt;/strong&gt; Use indexes on sorting columns to speed up &lt;code&gt;ORDER BY&lt;/code&gt; operations.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Limit Sorted Data:&lt;/strong&gt; When working with large datasets, try to limit the result set before applying &lt;code&gt;ORDER BY&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  GROUP BY: Aggregating Your Data
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Functionality:&lt;/strong&gt; The &lt;code&gt;GROUP BY&lt;/code&gt; clause is used to group rows that have the same values in specified columns into summary rows, like "find the number of customers in each country."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;department&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;AVG&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;salary&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;average_salary&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;employees&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;
&lt;span class="k"&gt;GROUP&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;department&lt;/span&gt;
&lt;span class="k"&gt;HAVING&lt;/span&gt; &lt;span class="k"&gt;AVG&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;salary&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;50000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This query calculates the average salary per department for employees over 30 years old, but only for departments where this average is over 50,000.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Be careful of:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Complexity in Queries:&lt;/strong&gt; Can make queries more complex, especially with the addition of &lt;code&gt;HAVING&lt;/code&gt; clauses.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Potential for Misinterpretation:&lt;/strong&gt; Incorrect use can lead to misleading results, especially if the SELECT statement includes columns not in the &lt;code&gt;GROUP BY&lt;/code&gt; clause.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Best Practices:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Clear Grouping Criteria:&lt;/strong&gt; Ensure that your &lt;code&gt;GROUP BY&lt;/code&gt; criteria align with your analytical goals.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Use Aggregative Functions Wisely:&lt;/strong&gt; Functions like &lt;code&gt;COUNT()&lt;/code&gt;, &lt;code&gt;AVG()&lt;/code&gt;, &lt;code&gt;SUM()&lt;/code&gt;, etc., should be used thoughtfully to avoid incorrect interpretations.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Consider Using&lt;/strong&gt; &lt;code&gt;HAVING&lt;/code&gt;: Use the &lt;code&gt;HAVING&lt;/code&gt; clause for filtering groups, but be aware of its additional processing overhead.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;While &lt;code&gt;ORDER BY&lt;/code&gt; enhances the readability and presentation of query results, &lt;code&gt;GROUP BY&lt;/code&gt; allows for powerful data aggregation and summary. Understanding their strengths and limitations, and following best practices, can help you harness their full potential, enabling you to conduct more effective and insightful data analysis.&lt;/p&gt;

&lt;h2&gt;
  
  
  Limit and offset
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fprgolge0oqz8hxb7i761.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fprgolge0oqz8hxb7i761.png" alt="Image description" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;LIMIT:&lt;/strong&gt; This clause is used to specify the maximum number of records to return in a query result. It's particularly useful for limiting the size of the result set to a manageable number.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;OFFSET:&lt;/strong&gt; OFFSET is used alongside LIMIT to skip a specified number of records before starting to return records from the query.&lt;/p&gt;

&lt;h4&gt;
  
  
  Use case
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Paginating Query Results:&lt;/strong&gt; Imagine an e-commerce platform with a products table containing thousands of entries. To display these products over multiple pages, you would use both LIMIT and OFFSET.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;products&lt;/span&gt;
&lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;
&lt;span class="k"&gt;LIMIT&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="k"&gt;OFFSET&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;This query retrieves 10 products, skipping the first 20 (essentially showing the third page of results if each page shows 10 products).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Sequential Data Processing:&lt;/strong&gt; In scenarios where you need to process data in batches (like sending out batches of emails), LIMIT and OFFSET can be used to manage this.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;customers&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;subscription_status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'active'&lt;/span&gt;
&lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;signup_date&lt;/span&gt;
&lt;span class="k"&gt;LIMIT&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt; &lt;span class="k"&gt;OFFSET&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;Here, you would process the third batch of 100 active subscribers.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  Pros and Cons
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Improved Performance:&lt;/strong&gt; By limiting the amount of data processed and returned, you can significantly reduce server load and improve response times.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Enhanced User Experience:&lt;/strong&gt; In applications with large datasets, like web interfaces, using LIMIT and OFFSET for pagination can drastically improve user experience.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Be careful of:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Offset Performance Issue:&lt;/strong&gt; OFFSET can be inefficient on large tables because it still has to read through all the preceding rows, which becomes more costly as the offset increases.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Risk of Inconsistent Data:&lt;/strong&gt; When data is added or removed between queries, OFFSET can lead to skipping or duplicating rows.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Best Practices
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Use with ORDER BY:&lt;/strong&gt; Always use LIMIT and OFFSET in conjunction with ORDER BY to ensure a consistent order in paginated results.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Be Cautious with Large OFFSETs:&lt;/strong&gt; For large datasets, consider alternative pagination strategies like keyset pagination (using a WHERE clause with a column value) instead of OFFSET to improve performance.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Avoid Using OFFSET for Sequential Processing:&lt;/strong&gt; For sequential processing of data, it's often more efficient to use a WHERE clause to specify a range or condition, rather than OFFSET.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Indexed Columns in ORDER BY:&lt;/strong&gt; Ensure that the column used in the ORDER BY clause is indexed, particularly when using LIMIT and OFFSET, to optimize the query performance.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  NULL
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzsxu6rjqob4t381e82bh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzsxu6rjqob4t381e82bh.png" alt="Image description" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://hackernoon.com/null-the-billion-dollar-mistake-8t5z32d6" rel="noopener noreferrer"&gt;NULL: The Billion Dollar Mistake&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In SQL, &lt;code&gt;NULL&lt;/code&gt; represents a unique concept: the absence of a value. It's neither zero nor an empty string but a distinct marker indicating that a value is unknown or undefined. While &lt;code&gt;NULL&lt;/code&gt; is a powerful aspect of SQL, its proper use requires understanding its behavior, advantages, and potential pitfalls.&lt;/p&gt;

&lt;h4&gt;
  
  
  Understanding NULL in SQL
&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;NULL&lt;/code&gt; is used in SQL to denote that a value is missing or unknown. It's a state that signifies the lack of a value, and therefore, &lt;code&gt;NULL&lt;/code&gt; is not equal to &lt;code&gt;NULL&lt;/code&gt; (since both represent unknown values, they can't be considered equal).&lt;/p&gt;

&lt;h4&gt;
  
  
  Examples of NULL in SQL
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Creating a Table with Nullable Columns:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;employees&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="nb"&gt;INT&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;manager_id&lt;/span&gt; &lt;span class="nb"&gt;INT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;In this example, &lt;code&gt;manager_id&lt;/code&gt; can be &lt;code&gt;NULL&lt;/code&gt;, indicating that some employees might not have a manager.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Inserting NULL Values:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;INSERT&lt;/span&gt; &lt;span class="k"&gt;INTO&lt;/span&gt; &lt;span class="n"&gt;employees&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;manager_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;VALUES&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'John Doe'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;This adds an employee who doesn’t have a manager assigned.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Querying with NULL Values:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;employees&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;manager_id&lt;/span&gt; &lt;span class="k"&gt;IS&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;This query selects all employees without a manager.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  Pros and Cons of Using NULL
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Flexibility:&lt;/strong&gt; &lt;code&gt;NULL&lt;/code&gt; allows for flexibility in database design by providing a way to represent unknown or inapplicable information.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Data Integrity:&lt;/strong&gt; It helps maintain data integrity by differentiating between "unknown" and "empty" or "zero".&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Complexity in Queries:&lt;/strong&gt; &lt;code&gt;NULL&lt;/code&gt; values can complicate query logic, especially in calculations and comparisons.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Ambiguity:&lt;/strong&gt; The meaning of &lt;code&gt;NULL&lt;/code&gt; can be ambiguous – is the data unknown, not applicable, or simply not entered yet?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Unexpected Results:&lt;/strong&gt; Operations involving &lt;code&gt;NULL&lt;/code&gt; (like &lt;code&gt;NULL + 1&lt;/code&gt;) result in &lt;code&gt;NULL&lt;/code&gt;, which can lead to unexpected outcomes in calculations.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Best Practices for Handling NULL
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Explicit Handling in Queries:&lt;/strong&gt; Always handle &lt;code&gt;NULL&lt;/code&gt; explicitly in your SQL queries. Use &lt;code&gt;IS NULL&lt;/code&gt; and &lt;code&gt;IS NOT NULL&lt;/code&gt; for checking &lt;code&gt;NULL&lt;/code&gt; values.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Consider Using COALESCE:&lt;/strong&gt; &lt;code&gt;COALESCE&lt;/code&gt; can be used to provide default values when dealing with &lt;code&gt;NULL&lt;/code&gt;, ensuring more predictable results.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;COALESCE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;manager_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;employees&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Avoid NULL in Calculations:&lt;/strong&gt; Be cautious with calculations involving &lt;code&gt;NULL&lt;/code&gt; values. They can propagate through your expressions and result in &lt;code&gt;NULL&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Use NOT NULL Constraints:&lt;/strong&gt; When designing your database schema, use &lt;code&gt;NOT NULL&lt;/code&gt; constraints where a value is always required, to ensure data completeness.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Clear Definition of NULL:&lt;/strong&gt; Define what &lt;code&gt;NULL&lt;/code&gt; represents in each column of your database to avoid ambiguity and misuse.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;NULL in Indexes:&lt;/strong&gt; Remember that &lt;code&gt;NULL&lt;/code&gt; values are typically not included in indexes. If you need to frequently query for &lt;code&gt;NULL&lt;/code&gt; values, consider indexing strategies that account for them.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;This is a long article and I didn't even went to deep in most topics. Note to self for the future, split into multiple articles if the topics are complex.&lt;/p&gt;

</description>
      <category>database</category>
      <category>webdev</category>
      <category>programming</category>
      <category>postgres</category>
    </item>
    <item>
      <title>Implementing Git Hook-Style functionality in Your Terminal</title>
      <dc:creator>dr_gos(☕ 💻)</dc:creator>
      <pubDate>Fri, 24 Nov 2023 22:39:52 +0000</pubDate>
      <link>https://dev.to/drgos_dev/implementing-git-hook-style-functionality-in-your-terminal-oi9</link>
      <guid>https://dev.to/drgos_dev/implementing-git-hook-style-functionality-in-your-terminal-oi9</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;The power of the terminal lies in its flexibility and the ability to customize it to fit our unique workflows. Drawing inspiration from Git hooks, a powerful feature in Git that triggers custom scripts at certain points in its execution flow, we can similarly extend the functionality of our terminal. This article delves into how I used this concept to streamline my workflow, not just limited to Go development, but applicable to a range of tasks in the terminal.&lt;/p&gt;

&lt;h2&gt;
  
  
  Understanding Git Hooks
&lt;/h2&gt;

&lt;p&gt;Git hooks are scripts that Git executes before or after events such as &lt;code&gt;commit&lt;/code&gt;, &lt;code&gt;push&lt;/code&gt;, and &lt;code&gt;pull&lt;/code&gt;. They are a vital part of automating tasks in the software development process. This concept can be extrapolated to the terminal, where we often perform repetitive tasks that could benefit from automation. For example, I automated the &lt;a href="https://gist.github.com/drgsn/d0e7e9a7b64e220ccdd5fafda712e35a" rel="noopener noreferrer"&gt;prefixing of each of my commit messages with the ticket id&lt;/a&gt; and &lt;a href="https://gist.github.com/drgsn/900559fc321b43d4a7ea14a8f4345c71" rel="noopener noreferrer"&gt;checks that I don't commit any secrets in my repos&lt;/a&gt; (not that well optimized).&lt;/p&gt;

&lt;h2&gt;
  
  
  Identifying Repetitive Tasks
&lt;/h2&gt;

&lt;p&gt;My journey began with recognizing a repetitive task: running &lt;code&gt;asdf reshim golang&lt;/code&gt; every time after using &lt;code&gt;go install&lt;/code&gt; or &lt;code&gt;go get&lt;/code&gt;. This was necessary due to using &lt;code&gt;asdf&lt;/code&gt; as a version manager for Go, but it was easy to forget. This scenario is just one example; think about your daily terminal use and identify similar repetitive commands.&lt;/p&gt;

&lt;h2&gt;
  
  
  Implementing the hook
&lt;/h2&gt;

&lt;p&gt;To automate this, I created a bash script named &lt;code&gt;.go_install_hook.sh&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;
&lt;span class="c"&gt;# Display a custom pre-run message.&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Running a Go command..."&lt;/span&gt;

&lt;span class="c"&gt;# Run the original 'go run' command.&lt;/span&gt;
go &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$@&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="c"&gt;# Check if the command is 'go run' or 'go install'&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;"run"&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;"install"&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
  &lt;span class="c"&gt;# If it's 'go run' or 'go install', run 'asdf reshim golang'&lt;/span&gt;
  &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"it's 'go run' or 'go install', running 'asdf reshim golang'"&lt;/span&gt;
  asdf reshim golang
&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This script acts as a wrapper around your intended command, in my case &lt;code&gt;go whatever&lt;/code&gt; allowing you to execute additional logic before or after the main command.&lt;/p&gt;

&lt;p&gt;In the example above I print a statement, this is more for debugging purposes, after that I run the intended &lt;code&gt;go&lt;/code&gt; command and at the end I check if the command was &lt;code&gt;go run&lt;/code&gt; or &lt;code&gt;go install&lt;/code&gt; and run the reshim command.&lt;/p&gt;

&lt;h2&gt;
  
  
  Integrating with the Terminal
&lt;/h2&gt;

&lt;p&gt;The script was then integrated into my daily workflow by aliasing the original command in my bash configuration (&lt;code&gt;.zshrc&lt;/code&gt; in my case):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;alias &lt;/span&gt;&lt;span class="nv"&gt;go&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"~/.go_install_hook.sh"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In my case, it was the &lt;code&gt;go&lt;/code&gt; command, but this can be adapted to any command where you see a pattern of repetitive post-command actions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Expanding Beyond Go
&lt;/h2&gt;

&lt;p&gt;While my initial use case was specific to &lt;code&gt;Go&lt;/code&gt; and &lt;code&gt;asdf&lt;/code&gt;, the principle applies universally. For instance, you could create a script that cleans up temporary files after compiling a program, or one that automatically pushes changes to a remote repository after a successful commit.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion: A World of Possibilities
&lt;/h2&gt;

&lt;p&gt;This approach opens up a world of possibilities in terminal automation. By emulating the functionality of Git hooks, we can create a more efficient, error-resistant, and customized command-line experience. This method's adaptability across various commands and workflows demonstrates the power of custom scripting in enhancing our daily interactions with the terminal.&lt;/p&gt;

</description>
      <category>terminal</category>
      <category>bash</category>
      <category>programming</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
