<?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: Brian kiplangat</title>
    <description>The latest articles on DEV Community by Brian kiplangat (@kiplangat_brian).</description>
    <link>https://dev.to/kiplangat_brian</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3951989%2F9516465d-0ea1-41e3-9bad-212b45892344.png</url>
      <title>DEV Community: Brian kiplangat</title>
      <link>https://dev.to/kiplangat_brian</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/kiplangat_brian"/>
    <language>en</language>
    <item>
      <title>The Role of a Database Administrator: Building a Database from Scratch in PostgreSQL</title>
      <dc:creator>Brian kiplangat</dc:creator>
      <pubDate>Mon, 20 Jul 2026 17:39:34 +0000</pubDate>
      <link>https://dev.to/kiplangat_brian/the-role-of-a-database-administrator-building-a-database-from-scratch-in-postgresql-163c</link>
      <guid>https://dev.to/kiplangat_brian/the-role-of-a-database-administrator-building-a-database-from-scratch-in-postgresql-163c</guid>
      <description>&lt;p&gt;A database administrator (DBA) is the custodian of an organisation's data: the person who designs the structures that hold it, enforces the rules that keep it accurate and consistent, loads and maintains the records as the real world changes, protects it from accidental damage, and turns it into answers when the organisation asks questions. It's a role that blends architecture, discipline, and service. You build the system, you guard its integrity, and you serve everyone who depends on it. In this guide, I step into that role for Greenwood Academy, a secondary school in Nairobi with no database at all, and walk through the full process a DBA follows to build one from scratch in PostgreSQL: create the schema, design the tables, adapt the structure when requirements change, load and correct the data, and finally query it. The complete scripts available on GitHub: &lt;a href="https://github.com/kiplangatbrian85/sql-week2-assignment-brian" rel="noopener noreferrer"&gt;sql-week2-assignment-brian&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1 - Create the schema: give the database a home
&lt;/h2&gt;

&lt;p&gt;Before a single table can exist, it needs somewhere to live. In PostgreSQL that's a schema; a namespace that keeps Greenwood's tables from colliding with anything else on the server:&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;SCHEMA&lt;/span&gt; &lt;span class="n"&gt;greenwood_academy&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="n"&gt;search_path&lt;/span&gt; &lt;span class="k"&gt;TO&lt;/span&gt; &lt;span class="n"&gt;greenwood_academy&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The second line is the one beginners skip and then suffer for. &lt;code&gt;search_path&lt;/code&gt; tells PostgreSQL which schema to use by default without it, every table reference needs the full &lt;code&gt;greenwood_academy.students&lt;/code&gt; prefix for the rest of the project.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2 - Design and create the tables: write the contracts
&lt;/h2&gt;

&lt;p&gt;A DBA doesn't start typing &lt;code&gt;CREATE TABLE&lt;/code&gt; immediately. First, you ask what the organisation &lt;em&gt;is&lt;/em&gt;, in data terms. A school reduces to three entities:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Table&lt;/th&gt;
&lt;th&gt;Represents&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;students&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Who is enrolled&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;subjects&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;What is taught&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;exam_results&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;How each student performed in each subject&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Each &lt;code&gt;CREATE TABLE&lt;/code&gt; is a contract: every column gets a name, a data type, and rules the data must obey forever.&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;students&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;student_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;first_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;50&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;last_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;50&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;gender&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;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;date_of_birth&lt;/span&gt; &lt;span class="nb"&gt;DATE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;class&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;10&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;city&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;50&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;/div&gt;



&lt;p&gt;Reading the contract: every student must have a unique ID and a full name; everything else the database will accept in silence, even if missing. One rule worth memorizing early- &lt;code&gt;PRIMARY KEY&lt;/code&gt; already implies &lt;code&gt;NOT NULL&lt;/code&gt; and &lt;code&gt;UNIQUE&lt;/code&gt;, so you never write those alongside it.&lt;/p&gt;

&lt;p&gt;The subjects table adds one new promise that no two subjects may share a name:&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;subjects&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;subject_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;subject_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="k"&gt;UNIQUE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;department&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;50&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;teacher_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;credits&lt;/span&gt;      &lt;span class="nb"&gt;INT&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then the table that ties the school together:&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;exam_results&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;result_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;student_id&lt;/span&gt; &lt;span class="nb"&gt;INT&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;subject_id&lt;/span&gt; &lt;span class="nb"&gt;INT&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;marks&lt;/span&gt;      &lt;span class="nb"&gt;INT&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;exam_date&lt;/span&gt;  &lt;span class="nb"&gt;DATE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;grade&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;2&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;/div&gt;



&lt;p&gt;&lt;code&gt;exam_results&lt;/code&gt; doesn't describe a person or a subject, it describes a &lt;em&gt;relationship&lt;/em&gt; between them: this student sat this subject and scored these marks. Those &lt;code&gt;student_id&lt;/code&gt; and &lt;code&gt;subject_id&lt;/code&gt; columns are logically foreign keys, already pointing at the other two tables and waiting for the day we learn joins.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;⚠️ &lt;strong&gt;Keep an eye on that &lt;code&gt;grade&lt;/code&gt; column.&lt;/strong&gt; It stores a value that's &lt;em&gt;derived&lt;/em&gt; from &lt;code&gt;marks&lt;/code&gt;. In Step 4, that design choice comes back to bite, exactly the way it bites in real databases.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Step 3 - Adapt the schema: requirements change (ALTER TABLE)
&lt;/h2&gt;

&lt;p&gt;No schema survives contact with stakeholders. Barely a day into the job, the requests start arriving, and each one maps to one of the three &lt;code&gt;ALTER TABLE&lt;/code&gt; moves a DBA uses constantly.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;"We forgot phone numbers. Add a column."&lt;/em&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;ALTER&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;students&lt;/span&gt; &lt;span class="k"&gt;ADD&lt;/span&gt; &lt;span class="k"&gt;COLUMN&lt;/span&gt; &lt;span class="n"&gt;phone_number&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;20&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;"'Credits' is confusing. Call it 'credit_hours'."&lt;/em&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;ALTER&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;subjects&lt;/span&gt; &lt;span class="k"&gt;RENAME&lt;/span&gt; &lt;span class="k"&gt;COLUMN&lt;/span&gt; &lt;span class="n"&gt;credits&lt;/span&gt; &lt;span class="k"&gt;TO&lt;/span&gt; &lt;span class="n"&gt;credit_hours&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;"Actually, we've decided we don't need phone numbers. Remove it."&lt;/em&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;ALTER&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;students&lt;/span&gt; &lt;span class="k"&gt;DROP&lt;/span&gt; &lt;span class="k"&gt;COLUMN&lt;/span&gt; &lt;span class="n"&gt;phone_number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add, rename, drop one afternoon, all three. The lesson isn't the syntax; it's that &lt;strong&gt;schemas are living things&lt;/strong&gt;. Nobody designs a database correctly on the first try, and the DBA who evolves structure calmly is the one the school keeps. One caution: &lt;code&gt;DROP COLUMN&lt;/code&gt; destroys the column &lt;em&gt;and all its data&lt;/em&gt; immediately, with no undo  in production, that statement gets reviewed twice.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4, Load and maintain the data: the registrar arrives (DML)
&lt;/h2&gt;

&lt;p&gt;Structure without data is just an opinion. The registrar delivers the records: 10 students, 10 subjects, 10 exam results. Rather than 30 separate statements, a multi-row &lt;code&gt;INSERT&lt;/code&gt; loads each table in one go:&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;students&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;student_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;first_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;last_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;gender&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;date_of_birth&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;city&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;'Amina'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;   &lt;span class="s1"&gt;'Wanjiku'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'F'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'2008-03-12'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Form 3'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Nairobi'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="s1"&gt;'Brian'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;   &lt;span class="s1"&gt;'Ochieng'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'M'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'2007-07-25'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Form 4'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Mombasa'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="s1"&gt;'Cynthia'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Mutua'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;   &lt;span class="s1"&gt;'F'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'2008-11-05'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Form 3'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Kisumu'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="s1"&gt;'David'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;   &lt;span class="s1"&gt;'Kamau'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;   &lt;span class="s1"&gt;'M'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'2007-02-18'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Form 4'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Nairobi'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="s1"&gt;'Esther'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="s1"&gt;'Akinyi'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="s1"&gt;'F'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'2009-06-30'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Form 2'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Nakuru'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="s1"&gt;'Felix'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;   &lt;span class="s1"&gt;'Otieno'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="s1"&gt;'M'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'2009-09-14'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Form 2'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Eldoret'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="s1"&gt;'Grace'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;   &lt;span class="s1"&gt;'Mwangi'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="s1"&gt;'F'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'2008-01-22'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Form 3'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Nairobi'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="s1"&gt;'Hassan'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="s1"&gt;'Abdi'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;    &lt;span class="s1"&gt;'M'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'2007-04-09'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Form 4'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Mombasa'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="s1"&gt;'Ivy'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;     &lt;span class="s1"&gt;'Chebet'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="s1"&gt;'F'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'2009-12-01'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Form 2'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Nakuru'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'James'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;   &lt;span class="s1"&gt;'Kariuki'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'M'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'2008-08-17'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Form 3'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Nairobi'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Subjects and exam results load the same way (full statements in the &lt;a href="https://github.com/kiplangatbrian85/sql-week2-assignment-brian" rel="noopener noreferrer"&gt;repo&lt;/a&gt; ; note the subjects insert uses &lt;code&gt;credit_hours&lt;/code&gt;, the column renamed in Step 3). A roll call confirms everything arrived:&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="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;students&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&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;subjects&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&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;exam_results&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;A habit worth forcing on yourself:&lt;/strong&gt; always list column names explicitly in an &lt;code&gt;INSERT&lt;/code&gt;. The shortcut &lt;code&gt;INSERT INTO students VALUES (...)&lt;/code&gt; silently depends on column order, one schema change later, cities end up in the class column without so much as an error.&lt;/p&gt;

&lt;h3&gt;
  
  
  Corrections arrive; the safe way to UPDATE and DELETE
&lt;/h3&gt;

&lt;p&gt;The database hums along for about an hour. Then real life intervenes with three pieces of news.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Esther Akinyi has moved from Nakuru to Nairobi.&lt;/strong&gt; Before touching anything, preview exactly which rows the &lt;code&gt;WHERE&lt;/code&gt; clause will hit:&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="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;students&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;student_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;   &lt;span class="c1"&gt;-- preview first&lt;/span&gt;
&lt;span class="k"&gt;UPDATE&lt;/span&gt; &lt;span class="n"&gt;students&lt;/span&gt; &lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="n"&gt;city&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Nairobi'&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;student_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Why the ritual? An &lt;code&gt;UPDATE&lt;/code&gt; without a &lt;code&gt;WHERE&lt;/code&gt; clause rewrites &lt;strong&gt;every row in the table&lt;/strong&gt; — no confirmation dialog, no undo. The preview costs five seconds and removes all guesswork.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;An exam has been cancelled.&lt;/strong&gt; Same discipline, then delete:&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;exam_results&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;result_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;9&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;And a marks entry was wrong&lt;/strong&gt; — result 5 was recorded as 49 when the student actually scored 59:&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;exam_results&lt;/span&gt; &lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="n"&gt;marks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;59&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;result_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Fixed? Look at the row again:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; result_id | marks | grade
-----------+-------+-------
         5 |    59 | D
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The marks are corrected, but &lt;code&gt;grade&lt;/code&gt; that column from Step 2- still says &lt;strong&gt;'D'&lt;/strong&gt;, the grade that matched the &lt;em&gt;wrong&lt;/em&gt; marks. Under the scale used elsewhere in the data, 59 is a 'C'. One fact, stored twice, and only one copy got updated.&lt;/p&gt;

&lt;p&gt;This is the derived-value trap in miniature: &lt;strong&gt;&lt;code&gt;grade&lt;/code&gt; is computable from &lt;code&gt;marks&lt;/code&gt;, so storing both creates two versions of the truth and copies drift.&lt;/strong&gt; In a 10-row table a DBA spots it by eye. In a 10-million-row production table, it's a silent data quality bug that surfaces months later in a report nobody trusts. Step 6 delivers the fix.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 5 - Query the data: the staffroom discovers the database
&lt;/h2&gt;

&lt;p&gt;With the data settled, the questions start coming, and this is what the whole process was building toward. Each request from the staff maps to a filtering pattern.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;"Who's in Form 4?"&lt;/em&gt; the exam office, planning registrations. An exact match:&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="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;students&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Form 4'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;⚠️ PostgreSQL string comparisons are &lt;strong&gt;case-sensitive&lt;/strong&gt;: &lt;code&gt;'form 4'&lt;/code&gt; returns zero rows and zero errors, a classic ten-minute debugging session.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;em&gt;"Which subjects are in Sciences? And show me all the girls' records for the mentorship program":&lt;/em&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="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;subjects&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;department&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Sciences'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&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;students&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;gender&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'F'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;"Form 3 students from Nairobi specifically"&lt;/em&gt; &lt;code&gt;AND&lt;/code&gt; requires both conditions; &lt;code&gt;OR&lt;/code&gt; requires either:&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="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;students&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Form 3'&lt;/span&gt; &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="n"&gt;city&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Nairobi'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&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;students&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Form 2'&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Form 4'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;"Every result between 50 and 80 marks, and the exams from mid-March"&lt;/em&gt; &lt;code&gt;BETWEEN&lt;/code&gt; is inclusive on &lt;strong&gt;both&lt;/strong&gt; ends, and works on dates exactly like numbers:&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="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;exam_results&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;marks&lt;/span&gt; &lt;span class="k"&gt;BETWEEN&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt; &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&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;exam_results&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;exam_date&lt;/span&gt; &lt;span class="k"&gt;BETWEEN&lt;/span&gt; &lt;span class="s1"&gt;'2024-03-15'&lt;/span&gt; &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="s1"&gt;'2024-03-18'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;"Students from our three biggest cities"&lt;/em&gt; -&lt;code&gt;IN&lt;/code&gt; replaces a clumsy chain of ORs, and &lt;code&gt;NOT IN&lt;/code&gt; inverts it:&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="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;students&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;city&lt;/span&gt; &lt;span class="k"&gt;IN&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Nairobi'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Mombasa'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Kisumu'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&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;students&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;IN&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Form 2'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Form 3'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;"Names starting with A or E... and which subjects have 'Studies' in the name?"&lt;/em&gt;  pattern matching with &lt;code&gt;LIKE&lt;/code&gt;, where &lt;code&gt;%&lt;/code&gt; matches any sequence of characters:&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="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;students&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;first_name&lt;/span&gt; &lt;span class="k"&gt;LIKE&lt;/span&gt; &lt;span class="s1"&gt;'A%'&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="n"&gt;first_name&lt;/span&gt; &lt;span class="k"&gt;LIKE&lt;/span&gt; &lt;span class="s1"&gt;'E%'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&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;subjects&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;subject_name&lt;/span&gt; &lt;span class="k"&gt;LIKE&lt;/span&gt; &lt;span class="s1"&gt;'%Studies%'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;💡 PostgreSQL also offers &lt;code&gt;ILIKE&lt;/code&gt;case-insensitive &lt;code&gt;LIKE&lt;/code&gt;. A Postgres extension rather than standard SQL, and invaluable with messy real-world text.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;em&gt;"Don't show me rows. Just tell me HOW MANY."&lt;/em&gt; the deputy principal wants numbers, which is &lt;code&gt;COUNT&lt;/code&gt;'s job:&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="k"&gt;COUNT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&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;form3_students&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;students&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Form 3'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="k"&gt;COUNT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&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;high_scores&lt;/span&gt;   &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;exam_results&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;marks&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;70&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note the order of operations: &lt;code&gt;WHERE&lt;/code&gt; filters rows first, then &lt;code&gt;COUNT&lt;/code&gt; aggregates what survived. &lt;em&gt;Filter, then aggregate&lt;/em&gt; — that sequencing becomes the backbone of every complex analytical query you'll ever write.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 6 - Classify at query time: CASE WHEN redeems the grade column
&lt;/h2&gt;

&lt;p&gt;The final request comes from the academic office: label every result; Distinction, Merit, Pass, or Fail.&lt;/p&gt;

&lt;p&gt;A week-one DBA might add another column and store the labels. But Step 4 already showed where that road leads: a stored &lt;code&gt;grade&lt;/code&gt; drifting away from its own &lt;code&gt;marks&lt;/code&gt;. The professional move is the opposite, &lt;strong&gt;don't store the label at all; compute it the moment someone asks:&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;result_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;marks&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;CASE&lt;/span&gt;
        &lt;span class="k"&gt;WHEN&lt;/span&gt; &lt;span class="n"&gt;marks&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt; &lt;span class="k"&gt;THEN&lt;/span&gt; &lt;span class="s1"&gt;'Distinction'&lt;/span&gt;
        &lt;span class="k"&gt;WHEN&lt;/span&gt; &lt;span class="n"&gt;marks&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt; &lt;span class="k"&gt;THEN&lt;/span&gt; &lt;span class="s1"&gt;'Merit'&lt;/span&gt;
        &lt;span class="k"&gt;WHEN&lt;/span&gt; &lt;span class="n"&gt;marks&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;40&lt;/span&gt; &lt;span class="k"&gt;THEN&lt;/span&gt; &lt;span class="s1"&gt;'Pass'&lt;/span&gt;
        &lt;span class="k"&gt;ELSE&lt;/span&gt; &lt;span class="s1"&gt;'Fail'&lt;/span&gt;
    &lt;span class="k"&gt;END&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;performance&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;exam_results&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The mental model that makes &lt;code&gt;CASE&lt;/code&gt; click: &lt;strong&gt;it evaluates top-down and stops at the first true condition.&lt;/strong&gt; That's why &lt;code&gt;WHEN marks &amp;gt;= 60&lt;/code&gt; needs no upper bound, anything 80 or above was already claimed by the branch above it. It also means condition order &lt;em&gt;is&lt;/em&gt; your logic: swap the first two branches and every Distinction in the school silently becomes a Merit.&lt;/p&gt;

&lt;p&gt;The same pattern classifies students, with &lt;code&gt;IN&lt;/code&gt; keeping the conditions tidy:&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;first_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;last_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;CASE&lt;/span&gt;
        &lt;span class="k"&gt;WHEN&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="k"&gt;IN&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Form 3'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Form 4'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;THEN&lt;/span&gt; &lt;span class="s1"&gt;'Senior'&lt;/span&gt;
        &lt;span class="k"&gt;WHEN&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="k"&gt;IN&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Form 1'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Form 2'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;THEN&lt;/span&gt; &lt;span class="s1"&gt;'Junior'&lt;/span&gt;
    &lt;span class="k"&gt;END&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;student_level&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;students&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A label computed at read time can never disagree with its source, because it doesn't exist until the moment you ask for it. That's the resolution to Step 4's bug and a design principle you'll reuse for the rest of your career.&lt;/p&gt;

&lt;h2&gt;
  
  
  The process, in summary
&lt;/h2&gt;

&lt;p&gt;Greenwood Academy now has a single source of truth, and the path there is the same process behind every database ever built:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Create the schema&lt;/strong&gt; , give the database a namespace to live in (&lt;code&gt;CREATE SCHEMA&lt;/code&gt; + &lt;code&gt;search_path&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Design and create the tables&lt;/strong&gt; , write contracts with constraints; remember &lt;code&gt;PRIMARY KEY&lt;/code&gt; implies &lt;code&gt;NOT NULL&lt;/code&gt; and &lt;code&gt;UNIQUE&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Adapt the structure&lt;/strong&gt; ,schemas are living things; add, rename, and drop columns with &lt;code&gt;ALTER TABLE&lt;/code&gt;, treating &lt;code&gt;DROP COLUMN&lt;/code&gt; with respect.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Load and maintain the data&lt;/strong&gt; , insert with explicit column lists; preview before every &lt;code&gt;UPDATE&lt;/code&gt; or &lt;code&gt;DELETE&lt;/code&gt;; beware stored derived values, because two copies of one fact will drift.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Query it&lt;/strong&gt; ,&lt;code&gt;WHERE&lt;/code&gt;, &lt;code&gt;AND&lt;/code&gt;/&lt;code&gt;OR&lt;/code&gt;, &lt;code&gt;BETWEEN&lt;/code&gt;, &lt;code&gt;IN&lt;/code&gt;, &lt;code&gt;LIKE&lt;/code&gt;, and &lt;code&gt;COUNT&lt;/code&gt;: filter, then aggregate.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Classify at query time&lt;/strong&gt; ,&lt;code&gt;CASE WHEN&lt;/code&gt; reads top-down, first match wins, and computed labels can't lie.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The story isn't finished: those &lt;code&gt;student_id&lt;/code&gt; and &lt;code&gt;subject_id&lt;/code&gt; columns in &lt;code&gt;exam_results&lt;/code&gt; are still pointing at the other tables, waiting for &lt;strong&gt;JOINs&lt;/strong&gt; — when the principal finally gets to ask the question he's really after: &lt;em&gt;"Which students are passing which subjects?"&lt;/em&gt; That's the next article.&lt;/p&gt;

&lt;p&gt;The complete scripts, organised section by section, are on GitHub: &lt;a href="https://github.com/kiplangatbrian85/sql-week2-assignment-brian" rel="noopener noreferrer"&gt;sql-week2-assignment-brian&lt;/a&gt;. If you're building your first database and anything here doesn't click, drop a comment.&lt;/p&gt;




</description>
      <category>postgres</category>
      <category>database</category>
      <category>sql</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Linux Fundamentals for Data Engineering</title>
      <dc:creator>Brian kiplangat</dc:creator>
      <pubDate>Fri, 12 Jun 2026 01:15:31 +0000</pubDate>
      <link>https://dev.to/kiplangat_brian/linux-fundamentals-for-data-engineering-5a9p</link>
      <guid>https://dev.to/kiplangat_brian/linux-fundamentals-for-data-engineering-5a9p</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;As a data engineer, most of your work will happen &lt;br&gt;
on Linux servers. Whether you are managing databases, &lt;br&gt;
running data pipelines, or processing large datasets, &lt;br&gt;
Linux is the operating system that powers the majority &lt;br&gt;
of servers worldwide. Understanding Linux fundamentals &lt;br&gt;
is therefore not optional for data engineers it is &lt;br&gt;
a core skill that separates beginners from &lt;br&gt;
professionals.&lt;/p&gt;

&lt;p&gt;In this article, I will walk you through the &lt;br&gt;
essential Linux skills every data engineer needs, &lt;br&gt;
based on my hands-on experience setting up a remote &lt;br&gt;
Ubuntu server, configuring PostgreSQL, and performing &lt;/p&gt;
&lt;h2&gt;
  
  
  file transfers using SCP. 
&lt;/h2&gt;
&lt;h2&gt;
  
  
  1. Setting Up Linux on Windows with WSL
&lt;/h2&gt;

&lt;p&gt;Most data engineers start their journey on Windows. &lt;br&gt;
The good news is that you do not need to install a &lt;br&gt;
separate Linux machine Windows Subsystem for Linux &lt;br&gt;
(WSL) allows you to run a full Linux environment &lt;br&gt;
directly inside Windows.&lt;/p&gt;

&lt;p&gt;To install WSL, open Windows CMD as Administrator &lt;br&gt;
and run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;wsl &lt;span class="nt"&gt;--install&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; Ubuntu-22.04
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After installation, restart your PC. You can now &lt;br&gt;
launch Ubuntu directly from your Start menu or by &lt;br&gt;
typing &lt;code&gt;wsl&lt;/code&gt; in CMD.&lt;/p&gt;

&lt;p&gt;One important lesson I learned during setup: WSL &lt;br&gt;
comes in different flavors. If your prompt shows &lt;br&gt;
&lt;code&gt;-sh&lt;/code&gt; instead of &lt;code&gt;bash&lt;/code&gt;, you are running a minimal &lt;br&gt;
shell, not full Ubuntu. In that case, install Ubuntu &lt;br&gt;
specifically using the command above.&lt;/p&gt;


&lt;h2&gt;
  
  
  2. Connecting to a Remote Server with SSH
&lt;/h2&gt;

&lt;p&gt;SSH (Secure Shell) is the standard way to connect &lt;br&gt;
to remote Linux servers. As a data engineer you will &lt;br&gt;
use SSH daily to access cloud servers, manage &lt;br&gt;
databases, and run data pipelines remotely.&lt;/p&gt;

&lt;p&gt;The basic SSH command syntax is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh username@server_ip &lt;span class="nt"&gt;-p&lt;/span&gt; port_number
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For example, to connect to our assignment server:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh root@159.65.222.96 &lt;span class="nt"&gt;-p&lt;/span&gt; 22
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Port 22 is the default SSH port. When connecting &lt;br&gt;
for the first time, you will see:&lt;/p&gt;

&lt;p&gt;Are you sure you want to continue connecting?&lt;br&gt;
(yes/no)&lt;/p&gt;

&lt;p&gt;Always type &lt;code&gt;yes&lt;/code&gt; and press Enter.&lt;/p&gt;

&lt;p&gt;One important thing to understand about your &lt;br&gt;
terminal prompt:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;#&lt;/code&gt; at the end means you are root (full admin)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;$&lt;/code&gt; at the end means you are a normal user&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Always run &lt;code&gt;whoami&lt;/code&gt; to confirm which user you are &lt;br&gt;
operating as this saved me from many permission &lt;br&gt;
errors during this assignment.&lt;/p&gt;


&lt;h2&gt;
  
  
  3. Linux User Management
&lt;/h2&gt;

&lt;p&gt;On a shared server, every person should have their &lt;br&gt;
own user account. This is important for security, &lt;br&gt;
accountability, and proper file permissions.&lt;/p&gt;

&lt;p&gt;To create a new user:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;adduser briank
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;An important lesson I learned: Linux usernames must &lt;br&gt;
be lowercase. When I tried to create a user called &lt;br&gt;
&lt;code&gt;BrianK&lt;/code&gt;, I got this error:&lt;/p&gt;

&lt;p&gt;Please enter a username matching the regular&lt;br&gt;
expression configured via the NAME_REGEX&lt;br&gt;
configuration variable.&lt;/p&gt;

&lt;p&gt;The fix was simple use lowercase:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;adduser briank
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To give the user sudo (admin) privileges:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;usermod &lt;span class="nt"&gt;-aG&lt;/span&gt; &lt;span class="nb"&gt;sudo &lt;/span&gt;briank
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To verify the user was created successfully:&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;id &lt;/span&gt;briank
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output:&lt;/p&gt;

&lt;p&gt;uid=1088(briank) gid=1088(briank)&lt;br&gt;
groups=1088(briank),27(sudo),100(users)&lt;/p&gt;


&lt;h2&gt;
  
  
  4. Essential Linux Commands for Data Engineers
&lt;/h2&gt;

&lt;p&gt;Here are the most important Linux commands every &lt;br&gt;
data engineer should know, organized by category:&lt;/p&gt;
&lt;h3&gt;
  
  
  Navigation Commands
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;pwd&lt;/span&gt;          &lt;span class="c"&gt;# print current directory&lt;/span&gt;
&lt;span class="nb"&gt;ls&lt;/span&gt;           &lt;span class="c"&gt;# list files&lt;/span&gt;
&lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-la&lt;/span&gt;       &lt;span class="c"&gt;# detailed list including hidden files&lt;/span&gt;
&lt;span class="nb"&gt;cd &lt;/span&gt;Documents &lt;span class="c"&gt;# go into a folder&lt;/span&gt;
&lt;span class="nb"&gt;cd&lt;/span&gt; ..        &lt;span class="c"&gt;# go up one level&lt;/span&gt;
&lt;span class="nb"&gt;cd&lt;/span&gt; ~         &lt;span class="c"&gt;# go to home directory&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  File Operations
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;touch &lt;/span&gt;notes.txt           &lt;span class="c"&gt;# create empty file&lt;/span&gt;
&lt;span class="nb"&gt;mkdir &lt;/span&gt;linux_assignment    &lt;span class="c"&gt;# create folder&lt;/span&gt;
&lt;span class="nb"&gt;cp &lt;/span&gt;notes.txt backup.txt   &lt;span class="c"&gt;# copy file&lt;/span&gt;
&lt;span class="nb"&gt;mv &lt;/span&gt;backup.txt old.txt     &lt;span class="c"&gt;# rename/move file&lt;/span&gt;
&lt;span class="nb"&gt;rm &lt;/span&gt;old.txt                &lt;span class="c"&gt;# delete file&lt;/span&gt;
&lt;span class="nb"&gt;cat &lt;/span&gt;notes.txt             &lt;span class="c"&gt;# view file contents&lt;/span&gt;
&lt;span class="nb"&gt;head&lt;/span&gt; &lt;span class="nt"&gt;-10&lt;/span&gt; notes.txt        &lt;span class="c"&gt;# view first 10 lines&lt;/span&gt;
&lt;span class="nb"&gt;tail&lt;/span&gt; &lt;span class="nt"&gt;-10&lt;/span&gt; notes.txt        &lt;span class="c"&gt;# view last 10 lines&lt;/span&gt;
&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="s2"&gt;"error"&lt;/span&gt; log.txt      &lt;span class="c"&gt;# search inside file&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  System Information
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;whoami&lt;/span&gt;       &lt;span class="c"&gt;# current username&lt;/span&gt;
&lt;span class="nb"&gt;uname&lt;/span&gt; &lt;span class="nt"&gt;-a&lt;/span&gt;     &lt;span class="c"&gt;# system and kernel info&lt;/span&gt;
&lt;span class="nb"&gt;hostname&lt;/span&gt;     &lt;span class="c"&gt;# server name&lt;/span&gt;
&lt;span class="nb"&gt;uptime&lt;/span&gt;       &lt;span class="c"&gt;# how long server has been running&lt;/span&gt;
&lt;span class="nb"&gt;df&lt;/span&gt; &lt;span class="nt"&gt;-h&lt;/span&gt;        &lt;span class="c"&gt;# disk space usage&lt;/span&gt;
free &lt;span class="nt"&gt;-h&lt;/span&gt;      &lt;span class="c"&gt;# memory usage&lt;/span&gt;
top          &lt;span class="c"&gt;# running processes (q to quit)&lt;/span&gt;
ps aux       &lt;span class="c"&gt;# list all processes&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  File Permissions
&lt;/h3&gt;

&lt;p&gt;Linux file permissions control who can read, &lt;br&gt;
write, and execute files. They are shown as:&lt;/p&gt;

&lt;p&gt;-rwxr-xr-x&lt;/p&gt;

&lt;p&gt;Breaking this down:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;r&lt;/code&gt; = read (4)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;w&lt;/code&gt; = write (2)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;x&lt;/code&gt; = execute (1)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Three groups: owner, group, others.&lt;/p&gt;

&lt;p&gt;To change permissions:&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;chmod &lt;/span&gt;755 script.sh   &lt;span class="c"&gt;# owner: rwx, others: r-x&lt;/span&gt;
&lt;span class="nb"&gt;chmod &lt;/span&gt;644 notes.txt   &lt;span class="c"&gt;# owner: rw-, others: r--&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To change file ownership:&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;chown &lt;/span&gt;briank notes.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Networking Commands
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ip a                  &lt;span class="c"&gt;# show network interfaces&lt;/span&gt;
ping google.com &lt;span class="nt"&gt;-c&lt;/span&gt; 4  &lt;span class="c"&gt;# test connectivity&lt;/span&gt;
netstat &lt;span class="nt"&gt;-tulnp&lt;/span&gt;        &lt;span class="c"&gt;# show open ports&lt;/span&gt;
ss &lt;span class="nt"&gt;-tlnp&lt;/span&gt;              &lt;span class="c"&gt;# modern version of netstat&lt;/span&gt;
curl ifconfig.me      &lt;span class="c"&gt;# show your public IP&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  5. PostgreSQL Setup on Linux
&lt;/h2&gt;

&lt;p&gt;PostgreSQL is the most popular open source database &lt;br&gt;
for data engineering. Here is how to set it up on &lt;br&gt;
Ubuntu:&lt;/p&gt;
&lt;h3&gt;
  
  
  Installation
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;apt update
apt &lt;span class="nb"&gt;install &lt;/span&gt;postgresql postgresql-contrib &lt;span class="nt"&gt;-y&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Start and Enable the Service
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;systemctl start postgresql
systemctl &lt;span class="nb"&gt;enable &lt;/span&gt;postgresql
systemctl status postgresql
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Log Into PostgreSQL
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;su &lt;span class="nt"&gt;-s&lt;/span&gt; /bin/bash postgres
psql
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Create a Database and Schema
&lt;/h3&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;DATABASE&lt;/span&gt; &lt;span class="n"&gt;briank&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="k"&gt;c&lt;/span&gt; &lt;span class="n"&gt;briank&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;SCHEMA&lt;/span&gt; &lt;span class="n"&gt;staging&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Create a Table and Insert Data
&lt;/h3&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;staging&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;farmers&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;farmer_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;county&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;50&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;subcounty&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;50&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;acreage&lt;/span&gt; &lt;span class="nb"&gt;DECIMAL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;crop&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;50&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;loan_amount&lt;/span&gt; &lt;span class="nb"&gt;DECIMAL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;loan_status&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;20&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;season&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;20&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;INSERT&lt;/span&gt; &lt;span class="k"&gt;INTO&lt;/span&gt; &lt;span class="n"&gt;staging&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;farmers&lt;/span&gt; 
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;farmer_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;county&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;subcounty&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
&lt;span class="n"&gt;acreage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;crop&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;loan_amount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;loan_status&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;season&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;'John Kipchumba'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Uasin Gishu'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
 &lt;span class="s1"&gt;'Turbo'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Maize'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;15000&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;00&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Paid'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'2023A'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Mary Jelimo'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Uasin Gishu'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
 &lt;span class="s1"&gt;'Soy'&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="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Maize'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;12000&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;00&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Defaulted'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'2023A'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Peter Rotich'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Uasin Gishu'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
 &lt;span class="s1"&gt;'Eldoret East'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Maize'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;20000&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;00&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Paid'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'2023B'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Useful psql Commands
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;l&lt;/span&gt;          &lt;span class="c1"&gt;-- list all databases&lt;/span&gt;
&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="k"&gt;c&lt;/span&gt; &lt;span class="n"&gt;dbname&lt;/span&gt;   &lt;span class="c1"&gt;-- connect to database&lt;/span&gt;
&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;dt&lt;/span&gt;         &lt;span class="c1"&gt;-- list all tables&lt;/span&gt;
&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;du&lt;/span&gt;         &lt;span class="c1"&gt;-- list all users&lt;/span&gt;
&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;q&lt;/span&gt;          &lt;span class="c1"&gt;-- quit psql&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Allow External Connections
&lt;/h3&gt;

&lt;p&gt;To allow tools like DBeaver or pgAdmin to connect &lt;br&gt;
remotely, two configuration files need editing:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;postgresql.conf&lt;/strong&gt;  change listen_addresses:&lt;br&gt;
listen_addresses = '&lt;em&gt;'&lt;br&gt;
**pg_hba.conf&lt;/em&gt;* — add this line at the bottom:&lt;br&gt;
host  all  all  0.0.0.0/0  md5&lt;br&gt;
Then restart PostgreSQL:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;systemctl restart postgresql
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  6. File Transfers with SCP
&lt;/h2&gt;

&lt;p&gt;SCP (Secure Copy Protocol) uses SSH to transfer &lt;br&gt;
files between your local machine and a remote server. &lt;br&gt;
This is essential for data engineers who need to &lt;br&gt;
move datasets, scripts, and configuration files.&lt;/p&gt;

&lt;h3&gt;
  
  
  Upload from local PC to server
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;scp C:&lt;span class="se"&gt;\U&lt;/span&gt;sers&lt;span class="se"&gt;\B&lt;/span&gt;rian&lt;span class="se"&gt;\n&lt;/span&gt;otes.txt root@159.65.222.96:/root/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Download from server to local PC
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;scp root@159.65.222.96:/root/notes.txt C:&lt;span class="se"&gt;\U&lt;/span&gt;sers&lt;span class="se"&gt;\B&lt;/span&gt;rian&lt;span class="se"&gt;\D&lt;/span&gt;ownloads&lt;span class="se"&gt;\&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Copy an entire folder
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;scp &lt;span class="nt"&gt;-r&lt;/span&gt; myfolder/ root@159.65.222.96:/root/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Use SSH key instead of password
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;scp &lt;span class="nt"&gt;-i&lt;/span&gt; ~/.ssh/mykey.pem file.txt root@server:/path/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  7. Key Lessons Learned
&lt;/h2&gt;

&lt;p&gt;During this assignment I encountered several &lt;br&gt;
real-world challenges that taught me valuable lessons:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Lesson 1 Always check who you are&lt;/strong&gt;&lt;br&gt;
Running &lt;code&gt;whoami&lt;/code&gt; before every session saved me &lt;br&gt;
from making changes as the wrong user. I accidentally &lt;br&gt;
switched to another student's account and spent time &lt;br&gt;
wondering why permissions were denied.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Lesson 2 Usernames must be lowercase&lt;/strong&gt;&lt;br&gt;
Linux enforces strict naming rules. &lt;code&gt;BrianK&lt;/code&gt; failed &lt;br&gt;
but &lt;code&gt;briank&lt;/code&gt; worked perfectly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Lesson 3 The prompt tells you everything&lt;/strong&gt;&lt;br&gt;
&lt;code&gt;#&lt;/code&gt; means root, &lt;code&gt;$&lt;/code&gt; means normal user. &lt;br&gt;
&lt;code&gt;=#&lt;/code&gt; in psql means ready, &lt;code&gt;(#&lt;/code&gt; means incomplete &lt;br&gt;
command press Ctrl+C to cancel.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Lesson 4  WSL is not always Ubuntu&lt;/strong&gt;&lt;br&gt;
Not all WSL installations are equal. A minimal &lt;br&gt;
shell missing &lt;code&gt;apt&lt;/code&gt;, &lt;code&gt;sudo&lt;/code&gt;, and &lt;code&gt;ssh&lt;/code&gt; taught me &lt;br&gt;
to always verify my environment with &lt;br&gt;
&lt;code&gt;cat /etc/os-release&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Lesson 5 Shared servers have history&lt;/strong&gt;&lt;br&gt;
On a shared assignment server, previous students &lt;br&gt;
had already made some configurations. Always check &lt;br&gt;
before editing - use &lt;code&gt;grep&lt;/code&gt; and &lt;code&gt;tail&lt;/code&gt; to verify &lt;br&gt;
what already exists.&lt;/p&gt;




&lt;h2&gt;
  
  
  8. Conclusion
&lt;/h2&gt;

&lt;p&gt;Linux is the backbone of modern data engineering. &lt;br&gt;
From managing remote servers with SSH, to setting &lt;br&gt;
up PostgreSQL databases, to transferring files with &lt;br&gt;
SCP every skill covered in this article is used &lt;br&gt;
daily by professional data engineers.&lt;/p&gt;

&lt;p&gt;The best way to learn Linux is by doing. Set up WSL &lt;br&gt;
on your Windows machine, spin up a cloud server, &lt;br&gt;
and practice these commands every day. The more you &lt;br&gt;
use them the more natural they become.&lt;/p&gt;

&lt;p&gt;As I continue my journey in data engineering at &lt;br&gt;
LuxDevHQ Cohort 8, Linux will remain a foundation &lt;br&gt;
skill that everything else builds on  from Python &lt;br&gt;
data pipelines, to cloud infrastructure, to &lt;br&gt;
geospatial data processing with PostGIS.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Brian Kiplangat - LuxDevHQ Data Engineering &lt;br&gt;
Cohort 8 | Nairobi, Kenya&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;GitHub: &lt;a href="https://github.com/kiplangatbrian85/" rel="noopener noreferrer"&gt;https://github.com/kiplangatbrian85/&lt;/a&gt;&lt;br&gt;
linux-data-engineering&lt;/em&gt;&lt;/p&gt;

</description>
      <category>linux</category>
      <category>dataengineering</category>
      <category>postgres</category>
      <category>beginners</category>
    </item>
  </channel>
</rss>
