lesson 66 Database engineering · advanced
Stored procedures: parameters & contracts
Understand parameters and the expectations of stored procedures.
the idea
A stored procedure packages a parameterized operation behind a stable contract: given inputs, return defined columns. SQLite has no stored procedures; the same contract is a query with one parameter value. Design the result first: inputs, output columns, ordering and what happens when nothing matches.
Dataset: Logistics
The tables the challenges use, with their first 6 rows. Under each column name: the kind of value it holds, and which table it links to.
packages8 columns · 11,505 rows
| package_idnumber · unique id | shipment_idnumber · links to shipments | tracking_numbertext | package_typetext | weight_kgdecimal | length_cmnumber | width_cmnumber | height_cmnumber |
|---|---|---|---|---|---|---|---|
| 1 | 1 | RT100007919B | box | 2.85 | 52 | 15 | 30 |
| 2 | 1 | RT100015838C | box | 1.1 | 69 | 45 | 24 |
| 3 | 2 | RT10 0023 757D | envelope | 0.49 | 32 | 24 | 2 |
| 4 | 3 | RT100031676E | box | 2.93 | 51 | 35 | 5 |
| 5 | 4 | RT100039595F | envelope | 0.38 | 32 | 24 | 3 |
| 6 | 5 | RT100047514G | box | 1.9 | 30 | 27 | 25 |
- package_idnumber · unique id
- 1
- shipment_idnumber · links to shipments
- 1
- tracking_numbertext
- RT100007919B
- package_typetext
- box
- weight_kgdecimal
- 2.85
- length_cmnumber
- 52
- width_cmnumber
- 15
- height_cmnumber
- 30
- package_idnumber · unique id
- 2
- shipment_idnumber · links to shipments
- 1
- tracking_numbertext
- RT100015838C
- package_typetext
- box
- weight_kgdecimal
- 1.1
- length_cmnumber
- 69
- width_cmnumber
- 45
- height_cmnumber
- 24
- package_idnumber · unique id
- 3
- shipment_idnumber · links to shipments
- 2
- tracking_numbertext
- RT10 0023 757D
- package_typetext
- envelope
- weight_kgdecimal
- 0.49
- length_cmnumber
- 32
- width_cmnumber
- 24
- height_cmnumber
- 2
- package_idnumber · unique id
- 4
- shipment_idnumber · links to shipments
- 3
- tracking_numbertext
- RT100031676E
- package_typetext
- box
- weight_kgdecimal
- 2.93
- length_cmnumber
- 51
- width_cmnumber
- 35
- height_cmnumber
- 5
- package_idnumber · unique id
- 5
- shipment_idnumber · links to shipments
- 4
- tracking_numbertext
- RT100039595F
- package_typetext
- envelope
- weight_kgdecimal
- 0.38
- length_cmnumber
- 32
- width_cmnumber
- 24
- height_cmnumber
- 3
- package_idnumber · unique id
- 6
- shipment_idnumber · links to shipments
- 5
- tracking_numbertext
- RT100047514G
- package_typetext
- box
- weight_kgdecimal
- 1.9
- length_cmnumber
- 30
- width_cmnumber
- 27
- height_cmnumber
- 25
first 6 of 11,505 rows · your queries use all of them
tracking_events9 columns · 100,515 rows
| event_idnumber · unique id | package_idnumber · links to packages | event_typetext | event_atdate & time | recorded_atdate & time | warehouse_idnumber · links to warehouses | event_sourcetext | exception_codetext | driver_idnumber |
|---|---|---|---|---|---|---|---|---|
| 1 | 6359 | created | 2025-01-01 00:03:46 | 2025-01-01 00:04:36 | NULL | manual | NULL | NULL |
| 2 | 10950 | created | 2025-01-01 00:33:12 | 2025-01-01 00:35:16 | NULL | manual | NULL | NULL |
| 3 | 2045 | created | 2025-01-01 00:35:00 | 2025-01-01 00:37:08 | NULL | manual | NULL | NULL |
| 4 | 5977 | created | 2025-01-01 00:47:34 | 2025-01-01 00:48:13 | NULL | manual | NULL | NULL |
| 5 | 4930 | created | 2025-01-01 00:55:09 | 2025-01-01 00:57:10 | NULL | manual | NULL | NULL |
| 6 | 6331 | created | 2025-01-01 01:34:23 | 2025-01-01 01:35:30 | NULL | manual | NULL | NULL |
- event_idnumber · unique id
- 1
- package_idnumber · links to packages
- 6359
- event_typetext
- created
- event_atdate & time
- 2025-01-01 00:03:46
- recorded_atdate & time
- 2025-01-01 00:04:36
- warehouse_idnumber · links to warehouses
- NULL
- event_sourcetext
- manual
- exception_codetext
- NULL
- driver_idnumber
- NULL
- event_idnumber · unique id
- 2
- package_idnumber · links to packages
- 10950
- event_typetext
- created
- event_atdate & time
- 2025-01-01 00:33:12
- recorded_atdate & time
- 2025-01-01 00:35:16
- warehouse_idnumber · links to warehouses
- NULL
- event_sourcetext
- manual
- exception_codetext
- NULL
- driver_idnumber
- NULL
- event_idnumber · unique id
- 3
- package_idnumber · links to packages
- 2045
- event_typetext
- created
- event_atdate & time
- 2025-01-01 00:35:00
- recorded_atdate & time
- 2025-01-01 00:37:08
- warehouse_idnumber · links to warehouses
- NULL
- event_sourcetext
- manual
- exception_codetext
- NULL
- driver_idnumber
- NULL
- event_idnumber · unique id
- 4
- package_idnumber · links to packages
- 5977
- event_typetext
- created
- event_atdate & time
- 2025-01-01 00:47:34
- recorded_atdate & time
- 2025-01-01 00:48:13
- warehouse_idnumber · links to warehouses
- NULL
- event_sourcetext
- manual
- exception_codetext
- NULL
- driver_idnumber
- NULL
- event_idnumber · unique id
- 5
- package_idnumber · links to packages
- 4930
- event_typetext
- created
- event_atdate & time
- 2025-01-01 00:55:09
- recorded_atdate & time
- 2025-01-01 00:57:10
- warehouse_idnumber · links to warehouses
- NULL
- event_sourcetext
- manual
- exception_codetext
- NULL
- driver_idnumber
- NULL
- event_idnumber · unique id
- 6
- package_idnumber · links to packages
- 6331
- event_typetext
- created
- event_atdate & time
- 2025-01-01 01:34:23
- recorded_atdate & time
- 2025-01-01 01:35:30
- warehouse_idnumber · links to warehouses
- NULL
- event_sourcetext
- manual
- exception_codetext
- NULL
- driver_idnumber
- NULL
first 6 of 100,515 rows · your queries use all of them
worked example
Run these steps in order to see the idea before you write your own query. The step marked “the pattern” is what the challenges ask for. Running the example does not count toward progress.
Inspect one shipment header. Shipment 6 stands in for :shipment_id. You see the reference, service level, and created_at—the inputs a caller passes into get_shipment_packages.
step-1.sqlSELECT shipment_id, order_reference, service_level_id, created_at FROM shipments WHERE shipment_id = 6;
List packages for that shipment. These rows are the contract output: package_id, tracking_number, and weight_kg. An unknown shipment would still return the same columns with zero rows.
step-2.sqlSELECT package_id, tracking_number, weight_kg FROM packages WHERE shipment_id = 6;
Put it together. The lesson's pattern in one query.the pattern
example.sql-- get_shipment_packages(:shipment_id) SELECT package_id, tracking_number, weight_kg FROM packages WHERE shipment_id = 6;
common mistake
A contract that returns an empty result for an unknown id must still return the same columns, so callers can rely on the shape.