Thuta Learning
IntermediateData & Databasesbeginner

Queries and CRUD, Conceptually

What you'll walk away with

  • Explain the core ideas behind Queries and CRUD, Conceptually
  • Read the diagram/table and identify the shape of the data model, schema, or architecture
  • Explain how this concept or system choice applies to a real project

Build the mental model

A query is simply how you ask a database to do something - find, add, change, or remove rows.

A tiny example like `SELECT * FROM users WHERE active = true;` asks the database to return every active user - the full syntax lives in the SQL tutorial.

OperationSQL / REST
CreateMaps to INSERT in SQL and POST in a REST API
ReadMaps to SELECT in SQL and GET in a REST API
UpdateMaps to UPDATE in SQL and PATCH or PUT in a REST API
DeleteMaps to DELETE in SQL and DELETE in a REST API

A single API endpoint might trigger several database operations behind the scenes - creating an order might update stock, write an audit log, and record a notification, all in one request.

Always Understand Your Filter Before UPDATE or DELETE

A filter that is missing, too broad, or wrong can affect far more rows than you intended - sometimes silently. Before running any modifying operation, check exactly which rows the filter would match first.

text
CRUD ACROSS THREE LAYERS
------------------------
CONCEPT      SQL STATEMENT      REST API VERB
-------      -------------      -------------
Create   ->  INSERT         ->  POST
Read     ->  SELECT         ->  GET
Update   ->  UPDATE         ->  PATCH / PUT
Delete   ->  DELETE         ->  DELETE

One API call can trigger several DB operations,
e.g. POST /orders may INSERT an order AND UPDATE
stock AND INSERT an audit log row - not just one.

Connect it to a real scenario

Real applications build and send queries through a library or ORM. Read is usually the safest operation, while Create, Update, and Delete change data permanently.

  • a filter that is too broad
  • a filter that is missing
  • a filter that is simply wrong

Any of these can affect far more rows than intended, sometimes silently. Before modifying data, check exactly which rows the filter would match first.

The runnable example below implements create/read/update/delete and includes a safety check that warns when a filter matches more rows than expected.

Always Understand Your Filter Before UPDATE or DELETE

A filter that is missing, too broad, or wrong can affect far more rows than you intended - sometimes silently. Before running any modifying operation, check exactly which rows the filter would match first.

Try the working example

javascript
function createRow(table, row) {
  const nextId = table.length ? Math.max(...table.map((r) => r.id)) + 1 : 1;
  const newRow = { id: nextId, ...row };
  table.push(newRow);
  return newRow;
}

function readRows(table, filter) {
  return table.filter((r) => Object.keys(filter).every((k) => r[k] === filter[k]));
}

function updateRows(table, filter, changes, options = {}) {
  const { allowMultiple = false } = options;
  const matches = readRows(table, filter);
  if (matches.length > 1 && !allowMultiple) {
    return {
      ok: false,
      warning: `Filter ${JSON.stringify(filter)} matched ${matches.length} rows; expected at most 1.`,
      updated: 0,
    };
  }
  matches.forEach((r) => Object.assign(r, changes));
  return { ok: true, updated: matches.length };
}

const users = [];
createRow(users, { name: "Aye", status: "active" });
createRow(users, { name: "Bo", status: "active" });
createRow(users, { name: "Cho", status: "inactive" });

console.log("Read active:", readRows(users, { status: "active" }));
console.log("Unsafe update (matches 2):", updateRows(users, { status: "active" }, { status: "archived" }));
console.log("Safe update (matches 1):", updateRows(users, { id: 1 }, { status: "archived" }));
You should see
Read active: [ {id:1,name:'Aye',status:'active'}, {id:2,name:'Bo',status:'active'} ]
Unsafe update (matches 2): { ok: false, warning: 'Filter {"status":"active"} matched 2 rows; expected at most 1.', updated: 0 }
Safe update (matches 1): { ok: true, updated: 1 }

The unsafe call is blocked because two rows match the filter; the safe call succeeds because filtering by id matches exactly one row.

5-minute try-it

Write a deleteRows function the same way as updateRows - if the filter matches more than one row, warn and delete nothing. If allowMultiple: true is passed, allow deleting all matches.

One important caution

Assuming a one-to-one mapping between API endpoints and database operations, when one endpoint can trigger several

Running an UPDATE or DELETE without first checking how many rows the filter will actually match

Wikipedia: CRUD (create, read, update and delete)How Databases Work

Easy traps

  • Assuming a one-to-one mapping between API endpoints and database operations, when one endpoint can trigger several
  • Running an UPDATE or DELETE without first checking how many rows the filter will actually match
  • This course teaches database concepts and the product landscape at a framework-neutral level -- for hands-on SQL syntax or PostgreSQL/MongoDB/Redis depth, continue to the SQL, PostgreSQL, MongoDB, or Redis tutorials.

Exercise

Write a deleteRows function the same way as updateRows - if the filter matches more than one row, warn and delete nothing. If allowMultiple: true is passed, allow deleting all matches.

You'll know it worked when: Read active: [ {id:1,name:'Aye',status:'active'}, {id:2,name:'Bo',status:'active'} ] Unsafe update (matches 2): { ok: false, warning: 'Filter {"status":"active"} matched 2 rows; expected at most 1.', updated: 0 } Safe update (matches 1): { ok: true, updated: 1 } The unsafe call is blocked because two rows match the filter; the safe call succeeds because filtering by id matches exactly one row.

Queries and CRUD, Conceptually | Thuta Learning