web-dev-qa-db-fra.com

Le classement insensible à la casse compare toujours la casse

J'essaie actuellement de créer un tableau avec une colonne de texte qui comparera la casse en sensible par défaut. En effet, nous avons un programme tiers qui exécute une recherche dans notre base de données. Les instructions SELECT utilisées par ce programme ne peuvent pas être modifiées.

Le problème abstrait est que nous avons en quelque sorte besoin que cette recherche soit insensible à la casse mais elle est actuellement sensible à la casse.

J'ai lu que Postgres 12 prend en charge les classements non déterministes qui permettent ce comportement.

J'ai un serveur Postgres (version PostgreSQL 12.1, compilé par Visual C++ build 1914, 64 bits) installé sur une machine Windows allemande.

Donc, à des fins de test, j'ai créé une nouvelle base de données pour tester sur:

CREATE DATABASE collation_test
    WITH 
    OWNER = postgres
    ENCODING = 'UTF8'
    CONNECTION LIMIT = -1;

Dans cette base de données, j'ai créé le classement suivant que j'ai trouvé dans n article sur ces classements

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

Après cela, j'avais besoin d'une table pour tester cette collation avec

CREATE TABLE public.person
(
    "Id" bigint NOT NULL,
    "Name" text COLLATE public.collat_ci,
    PRIMARY KEY ("Id")
);

ALTER TABLE public.person
    OWNER to postgres;

INSERT INTO person VALUES
(1, 'Robin'),
(2, 'robin');

Alors maintenant, j'ai essayé la requête de sélection suivante:

SELECT 
(
    SELECT "Name" FROM person p1 WHERE p1."Id" = 1
)
= 'Robin';

Ce qui a renvoyé true comme prévu comme le texte dans la base de données et la correspondance littérale donnée complètement.

Mais si j'essaye la même chose avec un minuscule r que je m'attendrais à faire correspondre à cause de mon classement mais il renvoie toujours false.

SELECT 
(
    SELECT "Name" FROM person p1 WHERE p1."Id" = 1
)
= 'robin';

En essayant de comparer le nom des deux lignes insérées, j'ai toujours obtenu false:

SELECT 
(
    SELECT "Name" FROM person p1 WHERE p1."Id" = 1 --'Robin'
)
=
(
    SELECT "Name" FROM person p2 WHERE p2."Id" = 2 --'robin'
);

Est-ce que quelqu'un sait pourquoi ma comparaison ne se comporte pas comme prévu et comment l'obtenir?

5
Robin B

La version de ICU fournie avec les versions de Windows est assez ancienne, c'est peut-être la raison.

Essayer

CREATE COLLATION collat_ci (
  provider = 'icu',
  locale = '@colStrength=secondary',
  deterministic = false
);

Cela devrait fonctionner avec les anciennes versions de ICU.

8
Laurenz Albe