A la lliçó 01-01 vam fer servir paraules com taula, fila, columna, clau primària i clau forana de manera deliberadament informal: ens servien per diagnosticar el full de càlcul de BiblioRed sense haver de definir res amb rigor. Ara toca fer-ho bé. El model relacional no és "una manera bonica d'organitzar taules": és una teoria matemàtica, publicada per Edgar F. Codd el 1970, i aquesta base formal és exactament la raó que els sistemes relacionals portin mig segle sense ser desplaçats.

Entendre el model té una conseqüència molt pràctica. Quan d'aquí a dues lliçons escriguis un JOIN i no retorni el que esperaves, o quan una comparació amb NULL no filtri cap fila, l'explicació no serà al manual de PostgreSQL: serà a la teoria que veurem avui. Aquesta és l'última lliçó sense teclejar (gairebé: hi ha SQL d'il·lustració, però encara no l'executaràs). Al final tindràs el plànol complet de l'esquema de BiblioRed, que a la lliçó següent convertirem en taules reals dins de biblioredb.

Contingut

  1. Relació, tupla, atribut i domini
  2. Grau i cardinalitat
  3. Per què una relació és un conjunt
  4. Relació davant de full de càlcul
  5. La família de les claus: superclau, candidata, primària, alternativa
  6. Claus foranes i el vincle entre relacions
  7. Clau natural davant de clau subrogada: el cas de l'ISBN
  8. Les tres regles d'integritat del model
  9. El valor NULL i la lògica de tres valors
  10. Introducció a l'àlgebra relacional
  11. L'esquema conceptual de BiblioRed
  12. Errors habituals i consells
  13. Exercicis
  14. Conclusió

  1. Relació, tupla, atribut i domini

El model relacional es construeix sobre quatre conceptes. Els presentem amb el seu nom formal i amb el seu nom col·loquial, perquè a la feina diària sentiràs tots dos.

Nom formal Nom col·loquial (SQL) Què és
Relació Taula Un conjunt de tuples que comparteixen la mateixa estructura
Tupla Fila o registre Un element de la relació: les dades d'un soci, d'un llibre
Atribut Columna o camp Una propietat amb nom, present a totes les tuples
Domini Tipus de dada El conjunt de valors vàlids per a un atribut

Compte amb una confusió molt estesa: "relació" no vol dir "vincle entre taules". En el model relacional, una relació és una taula. El vincle entre taules s'anomena clau forana (o, en disseny, interrelació). Que el model es digui "relacional" no ve del fet que les taules es relacionin entre si, sinó del fet que cada taula és, matemàticament, una relació en el sentit de la teoria de conjunts: un subconjunt del producte cartesià dels seus dominis.

Vegem-ho amb la relació socis de BiblioRed:

soci_id nom cognoms email data_alta sucursal_id
14 Marta Alsina [email protected] 2021-03-08 2
15 Ivan Pereda [email protected] 2021-09-19 2
16 Núria Bastos [email protected] 2022-01-30 1
  • La relació és socis.
  • Cadascuna de les tres línies és una tupla.
  • nom, email, data_alta… són atributs.
  • El domini de data_alta és "les dates vàlides del calendari"; el de soci_id, "els enters positius"; el d'email, "cadenes de fins a 120 caràcters". El domini és el que impedeix que a data_alta hi aparegui "dimarts passat".

Esquema i instància, un altre cop

A 01-01 vam distingir esquema (l'estructura) d'instància (les dades d'un moment concret). Formalment:

  • L'esquema de la relació s'escriu socis(soci_id, nom, cognoms, email, data_alta, sucursal_id). És estable: canvia només quan el dissenyador el canvia.
  • La instància o extensió és el conjunt concret de tuples que hi ha ara mateix. Canvia amb cada préstec, cada alta i cada baixa.

Quan parlem de "la taula socis" gairebé sempre ens referim a l'esquema; quan diem "hi ha 12.000 socis", a la instància.

  1. Grau i cardinalitat

Dues mesures elementals d'una relació:

  • Grau (o aritat): el nombre d'atributs. La relació socis de l'exemple té grau 6. El grau és una propietat de l'esquema.
  • Cardinalitat: el nombre de tuples. A l'exemple, 3; a BiblioRed de veritat, 12.000. La cardinalitat és una propietat de la instància.

Una regla mnemotècnica: el grau es compta d'ample i gairebé mai no canvia; la cardinalitat es compta d'alt i canvia contínuament.

Casos límit que convé tenir clars:

  • Una relació de cardinalitat 0 (sense tuples) és perfectament vàlida: és exactament el que tenim ara a biblioredb, on les taules encara ni tan sols existeixen, i el que tindrem després de crear-les a la lliçó següent.
  • Una relació de grau 0 és una curiositat matemàtica sense utilitat pràctica; SQL no l'admet.

  1. Per què una relació és un conjunt

Aquí hi ha la idea que més conseqüències té. Una relació és un conjunt de tuples, i els conjunts matemàtics tenen dues propietats que els fulls de càlcul no tenen:

No hi ha ordre

En un conjunt, {a, b, c} i {c, a, b} són el mateix conjunt. Per tant, les files d'una taula no tenen ordre intrínsec. Tampoc no en tenen les columnes, tot i que en SQL es declaren en una seqüència.

La conseqüència pràctica és contundent: si executes una consulta sense ORDER BY, el gestor pot retornar-te les files en qualsevol ordre, i aquest ordre pot canviar entre dues execucions idèntiques sense que ningú hagi tocat res. No és una errada: és el model. Si l'ordre importa, cal demanar-lo explícitament (ho veurem a 02-03).

No hi ha duplicats

En un conjunt, un element hi és o no hi és; no pot ser-hi "dues vegades". Per tant, en una relació no hi pot haver dues tuples idèntiques. Aquesta propietat és la que justifica l'existència obligatòria d'una clau primària: sempre hi ha d'haver alguna cosa que distingeixi una tupla d'una altra.

La lletra petita: SQL no és tan estricte

Honestedat intel·lectual: SQL no implementa el model relacional pur. Una taula SQL és tècnicament un multiconjunt (bag), no un conjunt: si no declares una clau primària ni una restricció d'unicitat, SQL et deixarà inserir dues files idèntiques i totes dues conviuran.

-- Legal en SQL si la taula no té clau primària.
-- Prohibit en el model relacional pur.
INSERT INTO socis_sense_clau VALUES ('Marta', 'Alsina');
INSERT INTO socis_sense_clau VALUES ('Marta', 'Alsina');
-- Resultat: dues files indistingibles, impossibles d'esborrar per separat

Per això una de les primeres regles pràctiques del curs és: tota taula porta clau primària. No és burocràcia; és el que retorna a la taula la seva condició de relació.

  1. Relació davant de full de càlcul

El full de càlcul de BiblioRed que vam diagnosticar a 01-01 s'assemblava molt a una taula. Aquestes són les diferències que el feien fallar:

Aspecte Relació (model relacional) Full de càlcul
Ordre de les files No existeix; es demana amb ORDER BY És intrínsec: la fila 7 és entre la 6 i la 8
Duplicats Prohibits (clau primària) Permesos i freqüents
Domini d'una columna Fix i verificat pel gestor Cada cel·la pot tenir el tipus que vulgui
Cel·les buides NULL, amb semàntica definida Buit ambigu: zero, text buit, no s'aplica?
Identificació d'una fila Pel valor de la seva clau Per la seva posició (A7)
Referències entre dades Claus foranes verificades Fórmules fràgils que es trenquen en inserir files
Accés simultani Controlat pel gestor Un usuari cada vegada, o conflictes de versió

La diferència decisiva és la penúltima línia. En un full de càlcul, una fila s'identifica per on és; en una relació, per quant val. Per això inserir una fila al mig d'un full trenca fórmules, i per això en una base de dades no trenca res: ningú no depèn de la posició.

  1. La família de les claus: superclau, candidata, primària, alternativa

Per garantir que no hi ha tuples duplicades necessitem identificar cada tupla. El model defineix una jerarquia precisa de conceptes. Treballarem sobre la relació llibres de BiblioRed:

llibre_id isbn titol autor_id editorial any_publicacio
331 9788401339097 El mapa del temps 1 Editorial Andana 2008
332 9788401337208 Els pilars de la Terra 2 Editorial Andana 1989
333 9788412007701 La casa de les marees 3 Edicions Marlia 2015

Superclau

Un conjunt d'atributs que identifica unívocament cada tupla: no hi pot haver dues tuples amb els mateixos valors en tots ells.

A llibres són superclaus, entre d'altres:

  • {llibre_id}
  • {isbn}
  • {llibre_id, titol}
  • {isbn, editorial, any_publicacio}
  • El conjunt de tots els atributs (sempre és superclau, perquè no hi ha tuples duplicades)

Fixa't que a una superclau li pots afegir atributs irrellevants i continua sent superclau. Per això cal afinar.

Clau candidata

Una superclau mínima: si li treus qualsevol atribut, deixa d'identificar unívocament. {llibre_id, titol} no és candidata, perquè {llibre_id} ja n'hi ha prou tot sol. A llibres les claus candidates són:

  • {llibre_id}
  • {isbn}

Una relació pot tenir diverses claus candidates, i sempre en té almenys una.

Clau primària

La clau candidata que el dissenyador tria com a identificador oficial. És la que faran servir les claus foranes d'altres taules i la que el gestor empra per organitzar l'emmagatzematge. A llibres triarem llibre_id (a l'apartat 7 justifiquem per què).

Clau alternativa

Les claus candidates no triades. A llibres, isbn és clau alternativa. En SQL es declaren amb UNIQUE, i continuen sent tan obligatòries de respectar com la primària: si deixes que dos llibres comparteixin ISBN, el catàleg de BiblioRed es corromp igualment.

Clau composta

Una clau (candidata o primària) formada per més d'un atribut. Si BiblioRed tingués una taula llibres_autors per a llibres escrits a diverses mans, la seva clau primària natural seria {llibre_id, autor_id}: ni el llibre sol ni l'autor sol no basten, però la parella sí.

flowchart TD
    A["Tots els conjunts d'atributs"] --> B["Superclaus<br/>identifiquen unívocament"]
    B --> C["Claus candidates<br/>superclaus mínimes"]
    C --> D["Clau primària<br/>la candidata triada"]
    C --> E["Claus alternatives<br/>les candidates no triades<br/>(UNIQUE en SQL)"]

  1. Claus foranes i el vincle entre relacions

Una clau forana (foreign key) és un atribut, o conjunt d'atributs, d'una relació els valors del qual han de coincidir amb els de la clau primària d'una altra relació (o de la mateixa).

A BiblioRed:

  • socis.sucursal_id és clau forana cap a sucursals.sucursal_id: cada soci pertany a una sucursal existent.
  • exemplars.llibre_id és clau forana cap a llibres.llibre_id: cada exemplar físic és una còpia d'un llibre del catàleg.
  • prestecs.soci_id i prestecs.exemplar_id són dues claus foranes a la mateixa taula: un préstec connecta un soci amb un exemplar.

Vocabulari: la taula que conté la clau forana és la filla o referenciant; la que conté la clau primària apuntada és la pare o referenciada.

Dues observacions importants:

  1. Una clau forana pot admetre NULL (llevat que es declari NOT NULL), i aquest NULL significa "aquesta fila no apunta a ningú". Si permetéssim exemplars.sucursal_id nul, estaríem dient que hi ha exemplars sense sucursal assignada. A BiblioRed no volem això, així que serà NOT NULL.
  2. Una clau forana es pot repetir. Que sucursal_id valgui 2 en centenars de socis és exactament el que s'espera: és una relació un-a-molts.

El tractament pràctic de les claus foranes —què passa quan esborres la fila pare, ON DELETE CASCADE, RESTRICT, restriccions diferibles— és el contingut complet de la lliçó 02-06. Aquí ens quedem en el concepte.

  1. Clau natural davant de clau subrogada: el cas de l'ISBN

Aquest és un debat real de disseny, i BiblioRed el té al davant.

  • Una clau natural és un identificador que ja existeix al món real i que hem adoptat com a clau: l'ISBN d'un llibre, el NIF d'una persona, el codi IATA d'un aeroport.
  • Una clau subrogada (o artificial) és un número que inventa la mateixa base de dades, sense significat fora d'ella: llibre_id = 331.

Hauria de tenir llibres com a clau primària l'isbn (natural) o un llibre_id (subrogada)? Comparem:

Criteri Clau natural (isbn) Clau subrogada (llibre_id)
Significat Té sentit fora de la BD Cap; només serveix a dins
Estabilitat Pot canviar o corregir-se (ISBN-10 → ISBN-13, errades de catalogació) No canvia mai
Mida 13 caràcters, replicats a cada clau forana 4 bytes d'enter
Llegibilitat en depurar Alta: veus l'ISBN i saps quin llibre és Baixa: 331 no diu res
Universalitat No tots els ítems el tenen: revistes, fullets, donacions antigues Sempre existeix
Risc de duplicats Real: reedicions mal catalogades comparteixen ISBN per error Nul

Decisió per a BiblioRed: clau primària subrogada llibre_id, i isbn com a clau alternativa UNIQUE. Els tres motius que pesen més:

  1. No tot el que presta BiblioRed té ISBN. Fons anteriors a 1970, publicacions municipals i donacions sense catalogar quedarien sense clau. I una clau primària no admet NULL (ho veurem a l'apartat següent).
  2. L'ISBN es corregeix. Quan un bibliotecari detecta que es va teclejar malament un ISBN i l'arregla, amb clau natural caldria propagar el canvi a totes les taules filles; amb clau subrogada, es corregeix un únic valor i ningú més no se n'assabenta.
  3. Les claus foranes s'abarateixen. exemplars té 40.000 files: guardar a cadascuna un enter de 4 bytes en comptes d'una cadena de 13 caràcters redueix la mida de la taula i dels seus índexs.

El que no fem és renunciar a l'ISBN: continua declarat UNIQUE, de manera que continua sent impossible catalogar dues vegades el mateix llibre. Triar clau subrogada no és excusa per perdre les restriccions del món real; aquest és l'error clàssic.

El mateix raonament s'aplica a exemplars: l'etiqueta física EJ-3081 que porta enganxada l'exemplar és una clau natural excel·lent per al taulell, però la guardarem en una columna codi amb UNIQUE, i la clau primària serà l'enter exemplar_id.

  1. Les tres regles d'integritat del model

El model relacional defineix tres regles que tot sistema ha de fer complir. S'anomenen regles d'integritat perquè la seva funció és impedir que la base de dades entri en un estat impossible.

Integritat de domini

Tot valor d'un atribut ha de pertànyer al seu domini.

És la regla més elemental i la que més feina estalvia. Si el domini de data_prestec són les dates, el gestor rebutja 'ahir', '32/13/2026' i '-1'. Si el domini d'any_publicacio són els enters, rebutja 'mil nou-cents vuitanta-nou'.

En SQL, la integritat de domini s'expressa amb els tipus de dades (els veurem operativament a 02-02) i es refina amb restriccions CHECK i NOT NULL (catàleg complet a 04-04).

Al full de càlcul de BiblioRed no hi havia integritat de domini: per això convivien 2026-06-02, 02/06/26 i pendent a la mateixa columna de dates.

Integritat d'entitat

Cap atribut de la clau primària no pot ser NULL.

El raonament és directe: la clau primària serveix per identificar la tupla. Si el seu valor és desconegut, la tupla no és identificable, i llavors no pot formar part d'una relació (recorda: sense duplicats, i dues tuples amb clau desconeguda no es poden distingir).

D'aquí surt la conseqüència pràctica de l'apartat anterior: com que no tots els ítems de BiblioRed tenen ISBN, l'ISBN no pot ser clau primària, perquè hauria d'admetre NULL.

En SQL, aquesta regla és automàtica: declarar PRIMARY KEY implica NOT NULL encara que no ho escriguis.

Integritat referencial

Tot valor no nul d'una clau forana s'ha de correspondre amb un valor existent de la clau primària referenciada.

Enunciada així de simple, prohibeix les files òrfenes: un préstec el soci_id del qual sigui 9999 quan no existeix el soci 9999; un exemplar d'un llibre que no és al catàleg. Al full de càlcul de BiblioRed n'hi havia a cabassos, perquè res no impedia teclejar un número de soci inventat.

Com es declara, què comprova el gestor a cada operació i què fer quan esborres la fila pare és el contingut íntegre de la lliçó 02-06. Aquí n'hi ha prou de retenir l'enunciat.

  1. El valor NULL i la lògica de tres valors

NULL no és zero. NULL no és la cadena buida. NULL no és "fals". NULL és l'absència de valor, i admet almenys tres lectures diferents que el model no distingeix:

  • Desconegut: el soci 19, Pau Miralles, té correu però no el va donar en donar-se d'alta.
  • No aplicable: data_devolucio d'un préstec encara obert — el llibre no s'ha retornat, així que no hi ha data que posar-hi.
  • Pendent: encara no s'ha registrat.

A BiblioRed farem servir data_devolucio IS NULL com a definició operativa de "préstec obert". És un ús net i molt comú: l'absència de data significa alguna cosa.

La lògica de tres valors

Com que NULL significa "no ho sé", qualsevol comparació amb NULL dóna com a resultat… no ho sé. SQL formalitza això amb una lògica de tres valors: CERT, FALS i DESCONEGUT.

Expressió Resultat
5 = 5 CERT
5 = 3 FALS
5 = NULL DESCONEGUT
NULL = NULL DESCONEGUT
NULL <> NULL DESCONEGUT

Sí: NULL = NULL no és cert. I té tota la lògica del món: si no sé l'edat de la Marta ni la de l'Ivan, no puc afirmar que siguin iguals.

Taules de veritat dels operadors lògics (D = desconegut):

A B A AND B A OR B
C C C C
C F F C
C D D C
F F F F
F D F D
D D D D

Dues caselles mereixen atenció: FALS AND DESCONEGUT és FALS (si una part ja falla, tant se val la resta) i CERT OR DESCONEGUT és CERT (si una part ja es compleix, tant se val la resta).

La conseqüència que més disgustos causa

Un filtre només deixa passar les files per a les quals la condició és CERTA. DESCONEGUT no passa. Per això:

-- MALAMENT: no retorna RES, ni tan sols els préstecs oberts
SELECT * FROM prestecs WHERE data_devolucio = NULL;

-- BÉ: l'operador correcte per preguntar per l'absència
SELECT * FROM prestecs WHERE data_devolucio IS NULL;

La primera consulta no dóna error de sintaxi —i això la fa perillosa—, simplement retorna zero files sempre. Els operadors correctes són IS NULL i IS NOT NULL. Els practicarem a 02-03.

Un parany més subtil, i molt real: WHERE estat <> 'prestat' no retorna les files l'estat de les quals sigui NULL, perquè NULL <> 'prestat' és DESCONEGUT. Si les vols incloure, cal demanar-ho: WHERE estat <> 'prestat' OR estat IS NULL.

  1. Introducció a l'àlgebra relacional

Codd no es va limitar a definir què és una relació: va definir també una àlgebra per operar-hi. La idea és elegant: cada operació pren una o dues relacions i retorna una altra relació. En ser tancada (entra relació, surt relació), es poden encadenar operacions indefinidament, i d'aquí neix la possibilitat de consultar.

Aquí només la presentem conceptualment, sense exercicis de notació. L'important és que vegis que cada operació de l'àlgebra té la seva traducció directa en SQL: SQL és la realització pràctica de l'àlgebra relacional, i l'optimitzador que vam veure a 01-04 treballa precisament reordenant aquestes operacions perquè costin menys.

Selecció (σ)

Tria files que compleixen una condició. El resultat té el mateix grau i menor o igual cardinalitat.

"Els exemplars de la sucursal 2"σ sucursal_id = 2 (exemplars)

SELECT * FROM exemplars WHERE sucursal_id = 2;   -- la clàusula WHERE

Projecció (π)

Tria columnes. El resultat té menor grau. A l'àlgebra pura, la projecció elimina duplicats (perquè el resultat ha de ser un conjunt); en SQL no ho fa llevat que escriguis DISTINCT.

"Només el títol i l'ISBN dels llibres"π titol, isbn (llibres)

SELECT DISTINCT titol, isbn FROM llibres;   -- la llista de columnes del SELECT

Producte cartesià (×)

Combina cada tupla d'una relació amb cada tupla de l'altra. Si socis té 12.000 files i llibres 8.000, el producte en té 96.000.000. Poques vegades es vol per si mateix, però és el fonament teòric de totes les combinacions.

SELECT * FROM socis CROSS JOIN llibres;   -- CROSS JOIN

Reunió (⋈, join)

Un producte cartesià seguit d'una selecció que aparella les tuples relacionades. És l'operació que recompon la informació repartida en diverses taules.

"Cada préstec amb les dades del seu soci"prestecs ⋈ prestecs.soci_id = socis.soci_id socis

SELECT * FROM prestecs JOIN socis ON socis.soci_id = prestecs.soci_id;

És tan central que li dediquem la lliçó sencera 02-04.

Unió (∪)

Ajunta les tuples de dues relacions compatibles (mateix nombre d'atributs i dominis compatibles) i elimina duplicats.

"Tots els identificadors de soci que apareixen en préstecs o en reserves"

SELECT soci_id FROM prestecs
UNION
SELECT soci_id FROM reserves;

Diferència (−)

Les tuples que són a la primera relació i no a la segona. És l'operació que respon a les preguntes negatives.

"Socis que han reservat però que no han agafat mai res en préstec"

SELECT soci_id FROM reserves
EXCEPT
SELECT soci_id FROM prestecs;

Un mapa de correspondències

Operació de l'àlgebra Símbol Clàusula SQL
Selecció σ WHERE
Projecció π llista de columnes del SELECT (+ DISTINCT)
Producte cartesià × CROSS JOIN
Reunió JOIN ... ON
Unió UNION
Diferència EXCEPT (MINUS a Oracle)
Intersecció INTERSECT
Reanomenament ρ AS

Aquesta taula és, a la pràctica, l'índex de les tres lliçons següents.

  1. L'esquema conceptual de BiblioRed

Amb tot el vocabulari a la mà, aquest és el plànol que construirem a la lliçó 02-02. Set relacions:

erDiagram
    SUCURSALS ||--o{ SOCIS : "és sucursal d'alta de"
    SUCURSALS ||--o{ EXEMPLARS : "custodia"
    AUTORS    ||--o{ LLIBRES : "escriu"
    LLIBRES   ||--o{ EXEMPLARS : "té còpies a"
    SOCIS     ||--o{ PRESTECS : "realitza"
    EXEMPLARS ||--o{ PRESTECS : "és objecte de"
    SOCIS     ||--o{ RESERVES : "sol·licita"
    LLIBRES   ||--o{ RESERVES : "és objecte de"

    SUCURSALS {
        int sucursal_id PK
        varchar nom UK
        varchar adreca
        varchar telefon
        date data_obertura
    }
    SOCIS {
        int soci_id PK
        varchar nom
        varchar cognoms
        varchar email UK
        date data_alta
        int sucursal_id FK
        boolean actiu
    }
    AUTORS {
        int autor_id PK
        varchar nom
        varchar cognoms
        varchar nacionalitat
        int any_naixement
    }
    LLIBRES {
        int llibre_id PK
        varchar isbn UK
        varchar titol
        int autor_id FK
        varchar editorial
        int any_publicacio
        varchar idioma
    }
    EXEMPLARS {
        int exemplar_id PK
        varchar codi UK
        int llibre_id FK
        int sucursal_id FK
        varchar estat
        date data_adquisicio
    }
    PRESTECS {
        int prestec_id PK
        int soci_id FK
        int exemplar_id FK
        date data_prestec
        date data_devolucio_prevista
        date data_devolucio
        numeric recarrec
    }
    RESERVES {
        int reserva_id PK
        int soci_id FK
        int llibre_id FK
        date data_reserva
        date data_expiracio
        varchar estat
    }

Les decisions de disseny que ja podem justificar amb el que hem après:

  • Set claus primàries subrogades, una per taula, totes enteres i autogenerades. Compleixen la integritat d'entitat sense dependre de dades del món real.
  • llibres.isbn i exemplars.codi com a claus alternatives (UNIQUE): conservem les restriccions naturals sense convertir-les en clau primària.
  • La distinció entre llibres i exemplars és la clau del model. llibres és l'obra (el títol, l'ISBN, l'autor); exemplars és l'objecte físic que es presta i que és en un prestatge concret. BiblioRed té uns 8.000 llibres diferents i 40.000 exemplars. Prestar un "llibre" no vol dir res: es presta un exemplar.
  • prestecs apunta a exemplars, no a llibres, precisament pel que acabem de dir. reserves, en canvi, apunta a llibres: un soci reserva l'obra, i ja se li assignarà l'exemplar que s'alliberi abans. Aquesta asimetria no és un descuit, és el model del negoci.
  • data_devolucio admet NULL i aquest NULL significa "préstec obert". És l'ús legítim del valor nul que vam veure a l'apartat 9.
  • recarrec és NUMERIC, no coma flotant, perquè representa diners. La justificació completa és a la lliçó següent.

Aquest esquema encara no és un disseny acabat: un llibre pot tenir diversos autors, i amb llibres.autor_id només n'hi cap un. És una simplificació conscient per al mòdul 2; les tècniques per modelar bé aquest cas (diagrames E-R, relacions N:M, taules intermèdies) arriben al mòdul 4, i la teoria que diu per què certs dissenys degeneren, al mòdul 5.

Errors Habituals i Consells

  • Confondre "relació" amb "vincle entre taules". Una relació és una taula. El vincle és una clau forana. És el malentès número u del vocabulari relacional.
  • Suposar que les files tenen un ordre. "Els últims préstecs són al final de la taula" és fals. Sense ORDER BY no hi ha ordre garantit, i refiar-se del que surti avui és una avaria ajornada.
  • Dissenyar taules sense clau primària. SQL ho permet, i per això cal imposar-s'ho un mateix. Sense clau primària pots acabar amb dues files idèntiques que no es poden actualitzar ni esborrar per separat.
  • Escriure = NULL en comptes d'IS NULL. No dóna error: retorna zero files en silenci. És l'errada més cara d'aquesta lliçó.
  • Triar clau natural per comoditat. L'ISBN sembla perfecte fins que apareix el primer fullet municipal sense ISBN o la primera errata que cal corregir en cascada.
  • Renunciar al UNIQUE perquè ja hi ha clau subrogada. Posar llibre_id no autoritza a permetre dos llibres amb el mateix ISBN. La clau subrogada identifica; l'alternativa protegeix la realitat.
  • Fer servir NULL com a comodí polivalent. Si NULL a estat significa de vegades "no ho sé" i de vegades "donat de baixa", ningú no podrà tornar a consultar aquesta columna amb confiança. Un NULL, un significat.
  • Consell: quan una consulta futura et retorni menys files de les esperades, comprova primer si hi ha NULL implicats. La lògica de tres valors és darrere de la majoria dels resultats "inexplicables".

Exercicis

Exercici 1: Vocabulari formal sobre una relació

Donada aquesta instància de la relació exemplars de BiblioRed:

exemplar_id codi llibre_id sucursal_id estat data_adquisicio
1 EJ-3081 331 2 prestat 2019-03-14
2 EJ-3082 331 1 disponible 2019-03-14
3 EJ-3083 331 3 disponible 2021-06-01
4 EJ-3084 332 1 prestat 2015-11-20

Respon:

  1. Quin és el grau i quina la cardinalitat?
  2. Proposa un domini raonable per a estat i un altre per a data_adquisicio.
  3. Indica dues superclaus, totes les claus candidates, la clau primària triada i la clau alternativa.
  4. És {llibre_id, sucursal_id} clau candidata? Justifica-ho amb les dades.
  5. Enumera les claus foranes d'aquesta relació i cap on apunten.

Exercici 2: Lògica de tres valors

La taula prestecs conté aquestes files:

prestec_id soci_id data_devolucio recarrec
1 14 2026-03-19 0.00
2 15 2026-04-02 1.40
9 14 NULL NULL
12 19 NULL NULL

Digues quantes files retorna cada consulta i per què:

  1. SELECT * FROM prestecs WHERE data_devolucio = NULL;
  2. SELECT * FROM prestecs WHERE data_devolucio IS NULL;
  3. SELECT * FROM prestecs WHERE recarrec > 0;
  4. SELECT * FROM prestecs WHERE recarrec > 0 OR data_devolucio IS NULL;
  5. SELECT * FROM prestecs WHERE soci_id = 14 AND recarrec > 0;
  6. SELECT * FROM prestecs WHERE NOT (recarrec > 0);

Exercici 3: Traduir preguntes a àlgebra relacional

Expressa cada pregunta fent servir les operacions de l'àlgebra (σ, π, ⋈, ∪, −) i digues quina clàusula SQL li correspondrà. Encara no cal sintaxi SQL correcta.

  1. Els codis dels exemplars que estan en reparació.
  2. Els títols de tots els llibres, sense repetir.
  3. Cada exemplar acompanyat del títol del seu llibre.
  4. Els socis que tenen préstecs o reserves.
  5. Els llibres que no s'han reservat mai.

Solucions

Solució 1

  1. Grau 6 (sis atributs: exemplar_id, codi, llibre_id, sucursal_id, estat, data_adquisicio). Cardinalitat 4 (quatre tuples). El grau pertany a l'esquema; la cardinalitat, a la instància.
  2. Per a estat, un domini tancat d'etiquetes: {'disponible', 'prestat', 'reparacio', 'baixa'}. Per a data_adquisicio, les dates vàlides del calendari, no posteriors a avui (una biblioteca no adquireix en el futur). El primer s'implementarà amb un CHECK, tema de 04-04.
  3. Superclaus: {exemplar_id}, {codi}, {exemplar_id, estat}, {codi, llibre_id, sucursal_id}, el conjunt de tots els atributs… Claus candidates: {exemplar_id} i {codi}, perquè totes dues identifiquen i cap no es pot reduir. Clau primària: exemplar_id (subrogada, estable, barata a les claus foranes de prestecs). Clau alternativa: codi, declarada UNIQUE, perquè l'etiqueta física també ha de ser única.
  4. No. Amb aquestes dades no es repeteix cap combinació, però això és casualitat de la instància: res no impedeix que la sucursal 2 tingui dos exemplars del llibre 331 (de fet és el normal en una biblioteca). Les claus es determinen per les regles del negoci, mai inspeccionant una instància concreta; una instància només pot refutar una clau candidata, mai confirmar-la.
  5. llibre_idllibres.llibre_id, i sucursal_idsucursals.sucursal_id. Totes dues haurien de ser NOT NULL: un exemplar sense llibre no té sentit i un exemplar sense sucursal no es pot localitzar al prestatge.

Solució 2

# Files Motiu
1 0 data_devolucio = NULL dóna DESCONEGUT a les quatre files (també on el valor és NULL). El filtre només deixa passar CERT. És el parany clàssic: no falla, calla.
2 2 (préstecs 9 i 12) IS NULL és l'operador correcte; retorna CERT exactament on falta el valor.
3 1 (préstec 2) Per al 1, 0.00 > 0 és FALS. Per al 9 i el 12, NULL > 0 és DESCONEGUT, i DESCONEGUT no passa el filtre.
4 3 (préstecs 2, 9 i 12) Fila 2: CERT OR FALS = CERT. Files 9 i 12: DESCONEGUT OR CERT = CERT (n'hi ha prou que una part es compleixi). Fila 1: FALS OR FALS = FALS.
5 0 Les files del soci 14 són la 1 (0.00 > 0 és FALS → C AND F = FALS) i la 9 (NULL > 0 és DESCONEGUT → C AND D = DESCONEGUT, no passa).
6 1 (préstec 1) NOT FALS = CERT (fila 1). NOT CERT = FALS (fila 2). NOT DESCONEGUT = DESCONEGUT (files 9 i 12): negar una cosa desconeguda continua sent desconegut. Aquest és el punt més contraintuïtiu: la 3 retorna 1 fila i la seva negació també en retorna 1, no 3.

Solució 3

# Àlgebra relacional Clàusula SQL
1 π codi ( σ estat = 'reparacio' (exemplars) ) SELECT codi ... WHERE estat = 'reparacio'
2 π titol (llibres) — la projecció de l'àlgebra ja elimina duplicats SELECT DISTINCT titol FROM llibres
3 exemplars ⋈ exemplars.llibre_id = llibres.llibre_id llibres JOIN ... ON (lliçó 02-04)
4 π soci_id (prestecs) ∪ π soci_id (reserves) UNION
5 π llibre_id (llibres) − π llibre_id (reserves) EXCEPT (o un LEFT JOIN ... IS NULL, lliçó 02-04)

Observa el patró del punt 5: tota pregunta que comença per "els que mai no…" és una diferència. Reté-ho, perquè a 02-04 i a 02-06 tornarà diverses vegades.

Conclusió

Hem convertit el vocabulari informal de la primera lliçó en un model amb regles precises:

  • Una relació és un conjunt de tuples amb els mateixos atributs, cadascun amb el seu domini. El seu grau és el nombre d'atributs i la seva cardinalitat, el de tuples.
  • En ser un conjunt, no té ordre ni duplicats, i això la separa radicalment d'un full de càlcul, on una fila s'identifica per la seva posició i no pel seu valor.
  • Les claus formen una jerarquia: superclau → clau candidata (superclau mínima) → clau primària (la triada) i claus alternatives (les altres, UNIQUE). Les claus foranes vinculen unes relacions amb unes altres.
  • En el debat clau natural davant de subrogada, BiblioRed tria llibre_id com a primària i conserva isbn com a alternativa: perquè no tot té ISBN, perquè l'ISBN es corregeix i perquè un enter és més barat de replicar.
  • Les tres regles d'integritat: de domini (els valors pertanyen al seu tipus), d'entitat (la clau primària no és mai nul·la) i referencial (tota clau forana apunta a alguna cosa que existeix; el seu tractament pràctic és la lliçó 02-06).
  • NULL significa "no ho sé", i d'aquí la lògica de tres valors: NULL = NULL és DESCONEGUT, IS NULL és l'únic operador vàlid per preguntar per la seva absència, i NOT DESCONEGUT continua sent DESCONEGUT.
  • L'àlgebra relacional —selecció, projecció, producte cartesià, reunió, unió, diferència— és la maquinària que SQL implementa: cada operació té la seva clàusula, i l'optimitzador de 01-04 no fa altra cosa que reordenar-les.
  • I tenim el plànol de BiblioRed: sucursals, socis, autors, llibres, exemplars, prestecs i reserves, amb les seves claus i els seus vincles.

El plànol està dibuixat; falta aixecar-lo. A la lliçó 02-02, Llenguatge SQL, coneixeràs el llenguatge amb què es parla amb un sistema relacional —per què és declaratiu, quins subllenguatges té, com s'escriuen els seus tipus de dades— i acabaràs executant l'script CREATE TABLE complet de les set taules dins de biblioredb. En acabar-la, el diagrama d'aquesta lliçó haurà deixat de ser un dibuix.

© Copyright 2026. Tots els drets reservats