Vous n'êtes pas identifié(e).
Pages : 1
Merci pour cette réponse très claire.
Voila donc la transformation du code qui fonctionne :
DO $$
DECLARE
y record;
x record;
BEGIN
FOR y IN (
SELECT id,chaine
FROM matable
WHERE id < 1000
) LOOP
FOR x IN EXECUTE concat ('SELECT count(1) nb'
,' FROM matable m'
,' WHERE m.chaine LIKE ',quote_literal(y.chaine)
,' AND m.id <> ',y.id
)
LOOP
RAISE INFO '%-%-%',y.id,y.chaine,x.nb;
END LOOP;
END LOOP;
END$$;
A noter qu'il faut impérativement ne pas mettre de parenthèses dans "FOR x IN EXECUTE" (autrement dit FOR x IN (EXECUTE...) ne fonctionne pas, alors que FOR x IN (SELECT ...) fonctionne).
Bonjour,
Soit une bête table avec une clef primaire et un champ varchar indexé :
CREATE TABLE matable
(
id integer NOT NULL,
chaine character varying,
CONSTRAINT pk_id PRIMARY KEY (id )
) WITH ( OIDS=FALSE);
CREATE INDEX idx_chaine ON matable USING btree (chaine COLLATE pg_catalog."default" );
Si je fais
SELECT * FROM matable where chaine = '000ZX34/14';
SELECT * FROM matable where chaine LIKE '000ZX34/14' ;
Dans les deux cas l'optimiseur utilise l'index idx_chaine.
Par contre si je fais le script suivant :
DO $$
DECLARE
y record;
x record;
BEGIN
FOR y IN (
SELECT id,chaine
FROM matable
WHERE id < 200
) LOOP
FOR x IN (SELECT count(1) nb
FROM matable m
WHERE m.chaine LIKE y.chaine
AND m.id <> y.id
)
LOOP
RAISE INFO '%-%-%',y.id,y.chaine,x.nb;
END LOOP;
END LOOP;
END$$;
L'index ne sera pas utilisé dans la requête imbriquée (FOR x), à la place on a un seq scan. En remplaçant le like par =, l'index est utilisé.
J'ai essayé en ajoutant un index sur chaine avec la classe opérateur "varchar_pattern_ops" mais sans plus de succès.
Le bout de code ci-dessus est un peu idiot mais je voudrais surtout comprendre le fonctionnement du LIKE dans ce cas là et pourquoi il n'utilise pas l'index.
Merci.
Pages : 1