Kennisbank · data-rariteiten

Wanneer een hoofdletter geen hoofdletter is

Hoofdletters en kleine letters lijken eenvoudige varianten van hetzelfde teken. In Unicode hangt hun relatie soms af van de taal, de context en het doel waarvoor u de tekst verwerkt.

Vier letters I

Wie uitsluitend Nederlands of Engels verwerkt, kan gemakkelijk aannemen dat de hoofdletter I en de kleine letter i altijd bij elkaar horen. In het Turks bestaan echter twee verschillende letterparen: een I zonder punt en een I met punt.

I U+0049 hoofdletter zonder punt
ı U+0131 kleine letter zonder punt
İ U+0130 hoofdletter met punt
i U+0069 kleine letter met punt

In een Turkse context wordt I dus ı en wordt i de hoofdletter İ. Een taalneutrale omzetting kan andere resultaten geven. Daarmee is “zet alles om naar kleine letters” geen volledige specificatie.

Case mapping, case folding en collatie

Drie begrippen worden in dit verband gemakkelijk door elkaar gehaald:

Begrip Doel Voorbeeld
Case mapping Tekst omzetten naar hoofdletters, kleine letters of titelvorm. Een naam voor weergave naar hoofdletters omzetten.
Case folding Hoofdletterverschillen verwijderen om teksten zonder onderscheid naar letterkast te vergelijken. Een interne zoeksleutel maken voor een identifier.
Collatie Bepalen hoe teksten worden gesorteerd en met elkaar worden vergeleken. Vaststellen of DATA en data voor een index gelijk zijn.

Case folding is dus niet simpelweg hetzelfde als lower(). Unicode definieert daarvoor afzonderlijke regels. De resulterende tekst is bedoeld voor interne vergelijking en in het algemeen niet om aan gebruikers te tonen of als vervanging van de oorspronkelijke waarde op te slaan.

Eén teken kan meerdere tekens worden

Hoofdletteromzetting levert bovendien niet altijd per invoerteken precies één uitvoerteken op. De Duitse letter ß kan bij omzetting naar hoofdletters bijvoorbeeld SS worden. Een algoritme dat wel van een vaste tekenlengte uitgaat, heeft dan een probleem.

Ook context kan meetellen. De Griekse hoofdletter sigma Σ heeft bij omzetting naar kleine letters een gewone vorm σ en aan het einde van een woord een slotvorm ς. Unicode bevat daarom naast eenvoudige tekenkoppelingen ook taal- en contextgevoelige regels.

Dit raakt lengtecontroles, vaste posities, indexsleutels en iedere toepassing die tekst eerst omzet en daarna veronderstelt dat de structuur gelijk is gebleven.

Waar het in de praktijk misgaat

  • Inloggen: gebruikersnamen worden in twee systemen volgens andere regels hoofdletterongevoelig gemaakt.
  • Zoeken: een zoekterm vindt niet alle namen omdat de omzetting niet bij de taal van de gegevens past.
  • Unieke sleutels: een applicatie beschouwt twee waarden als gelijk, terwijl de unieke database-index beide toestaat – of andersom.
  • Sorteren: de volgorde verandert wanneer een andere collatie, taalinstelling of softwareversie wordt gebruikt.
  • Koppelingen: een afgeleide kleineletterwaarde uit systeem A sluit niet aan op die uit systeem B.
  • Migraties: opnieuw genereren van zoeksleutels levert andere waarden op dan in het bronsysteem.

De lastigste variant ontstaat wanneer de regels meestal wel goed gaan. Een fout die uitsluitend optreedt bij een Turkse naam, een Duitse straatnaam of een Grieks woord blijft gemakkelijk lang onopgemerkt.

Een PostgreSQL-collatie voor hoofdletterongevoelige vergelijking

PostgreSQL kan met een niet-deterministische ICU-collatie teksten gelijk behandelen die niet uit dezelfde bytes bestaan. Onderstaand voorbeeld maakt een hoofdletterongevoelige collatie. Hiervoor moet PostgreSQL met ICU-ondersteuning zijn geïnstalleerd.

CREATE COLLATION unicode_case_insensitive
(
    provider = icu,
    locale = 'und-u-ks-level2',
    deterministic = false
);

SELECT
    'DATA' = 'data' COLLATE unicode_case_insensitive
        AS gelijk_zonder_hoofdletteronderscheid;

Het resultaat is true. De instelling und staat voor een niet nader bepaalde taal en ks-level2 voor een vergelijkingsniveau waarop letterkast wordt genegeerd. Dat maakt deze collatie nog niet automatisch geschikt voor iedere gegevenssoort. Taalgebonden namen kunnen om een specifieke locale vragen en identifiers kunnen juist een strikter, taalneutraal contract nodig hebben.

Niet-deterministische collaties hebben bovendien gevolgen voor prestaties en indexgedrag. De keuze hoort daarom bewust bij het gegevensmodel te worden gemaakt, niet incidenteel in één query.

De herbruikbare oplossing: een DOMAIN

Wanneer verschillende kolommen volgens exact dezelfde vergelijkingsregel moeten werken, kan die regel aan een PostgreSQL-DOMAIN worden gekoppeld:

CREATE DOMAIN zoektekst_ci AS text
    COLLATE unicode_case_insensitive;

CREATE TABLE gebruiker
(
    gebruiker_id bigint GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
    gebruikersnaam zoektekst_ci NOT NULL UNIQUE,
    weergavenaam   text NOT NULL
);

De gebruikersnaam wordt hierdoor volgens de afgesproken collatie vergeleken; de weergavenaam blijft de oorspronkelijke tekst behouden. Dat onderscheid is belangrijk: een vergelijkingsvorm is een technisch hulpmiddel en niet noodzakelijk de waarde die de gebruiker heeft ingevoerd.

Dit is opnieuw Single Point of Maintenance: definieer de vergelijkingsregel één keer voor de betrokken data class en gebruik haar consequent in tabellen, controles en koppelingen.

Wat goed datamanagement hier vraagt

  • Maak het doel expliciet. Wilt u tekst weergeven, zoeken, sorteren, ontdubbelen of als identifier gebruiken?
  • Leg de taalcontext vast. Een persoonsnaam, productcode en vrije tekst vragen niet vanzelfsprekend om dezelfde regels.
  • Bewaar de oorspronkelijke waarde. Gebruik een afgeleide vergelijkingssleutel alleen waar die functioneel nodig is.
  • Definieer normalisatie en case folding samen. De volgorde van bewerkingen en de gekozen Unicode-versie moeten onderdeel zijn van het contract.
  • Test uitzonderingen. Neem minimaal de Turkse I, Duitse ß, Griekse sigma en canoniek gelijkwaardige Unicode-reeksen op.
  • Beheer collatieversies. Een wijziging van besturingssysteem, ICU of database kan herindexering of hertesten noodzakelijk maken.

De kern is eenvoudig: “hoofdletterongevoelig” is geen technische implementatie, maar een functionele afspraak die nog moet worden uitgewerkt.

Bronnen en verdere verdieping

  1. Unicode Consortium – FAQ over case mapping en case folding
  2. Unicode Character Database – SpecialCasing.txt
  3. Unicode Character Database – CaseFolding.txt
  4. The Unicode Standard – Implementation Guidelines
  5. PostgreSQL – Collation Support
  6. PostgreSQL – CREATE COLLATION

Een simpele hoofdletterregel bestaat niet

Wilt u weten waar impliciete tekstregels, collaties of afgeleide sleutels de datakwaliteit binnen uw organisatie beïnvloeden? Met de datamanagement quickscan brengt u sterke punten, risico’s en concrete verbeterkansen in beeld.