• nouveau

    La grande Release 2026 est disponible – Intégrez la Data Observability au cœur de votre code

  • nouveau

    Contribuez à l'avenir de l'innovation en matière d'IA et de données

  • nouveau

    • Release 2026.06 - Intégrer la Data Observability au cœur de votre code

  • nouveau

    • Contribuez à l'avenir de l'innovation en matière d'IA et de données

Enregistrements orphelins : les trouver en SQL et les tenir à l'écart

|

6

minute de lecture

Schéma : des lignes de payments référençant le compte A-777, absent de la table accounts

Une ligne de paiement indique account_id = 884213. La table accounts ne contient aucun compte portant ce numéro. Aucune erreur, le chargement se termine au vert, et le lendemain matin il manque exactement ce paiement dans le rapport de l'agence, parce que le rapport joint les paiements aux comptes et que la jointure l'écarte sans bruit. Un enregistrement orphelin est une ligne enfant dont la valeur de clé étrangère n'a aucune ligne correspondante dans la table parente à laquelle elle fait référence.

Les enregistrements orphelins, ou lignes orphelines, apparaissent partout où les clés étrangères ne sont pas appliquées : entrepôts de données, couches de staging, réplicas, pipelines qui chargent les enfants avant les parents. Les trouver est une tâche SQL classique : l'anti-jointure. Il existe quatre façons courantes de l'écrire, et l'une d'elles répond « aucun orphelin » dès qu'un seul NULL apparaît.

Ce guide présente les modèles de requête, les pièges, et la manière de faire de la requête un contrôle exécuté à chaque chargement. Pour le concept lui-même, consultez Vos données retrouvent-elles encore leurs parents ? Comprendre l'intégrité référentielle.

Points clés à retenir

  • Les jointures internes masquent les enregistrements orphelins : les lignes enfants sans correspondance disparaissent du résultat au lieu de déclencher une erreur.

  • Trouvez les orphelins avec une anti-jointure : LEFT JOIN … IS NULL, NOT EXISTS ou EXCEPT sur les clés distinctes.

  • Évitez NOT IN sur une colonne qui peut contenir des NULL : un seul NULL dans la sous-requête renvoie zéro ligne, ce qui ressemble à un résultat propre.

  • Faites correspondre les clés composites sur toutes leurs colonnes à la fois, et décidez délibérément si une clé étrangère NULL est une erreur.

  • Une requête qu'il faut penser à lancer n'est pas un contrôle. Dans digna, la même anti-jointure est une règle Referential Integrity qui s'exécute à chaque inspection.

Table des matières

  • Qu'est-ce qu'un enregistrement orphelin ?

  • Pourquoi les jointures internes masquent-elles les enregistrements orphelins ?

  • Comment trouver les enregistrements orphelins en SQL ?

    • LEFT JOIN … IS NULL

    • NOT EXISTS

    • EXCEPT (MINUS) sur les clés distinctes

  • Pourquoi NOT IN ne renvoie-t-il aucune ligne en présence d'un NULL ?

  • Quel modèle d'anti-jointure utiliser ?

  • Comment gérer les clés composites et les clés étrangères NULL ?

  • Comment trouver les enregistrements orphelins dans les grandes tables ?

  • Et si la table parente se trouve dans une autre base de données ?

  • Comment transformer une requête de recherche d'orphelins en contrôle permanent ?

  • Les trouver une fois, puis les tenir à l'écart

Qu'est-ce qu'un enregistrement orphelin ?

Un enregistrement orphelin est une ligne d'une table enfant dont la clé étrangère pointe vers une clé parente qui n'existe pas : un paiement dont l'account_id ne figure pas dans accounts, ou une administration de médicament dont le product_code ne figure pas dans medications. La ligne peut être parfaitement valide en elle-même. C'est la relation qui est brisée.

Les orphelins se trouvent toujours du côté enfant ; un compte sans paiement est normal. Les causes habituelles sont banales : le parent a été supprimé ou n'a jamais été chargé, l'enfant est arrivé avant le chargement des données de référence du lendemain, ou les formats de clé diffèrent ('00884213' contre 884213, ou un espace en fin de valeur).

Les bases de données opérationnelles comme PostgreSQL ou Oracle appliquent les clés étrangères déclarées, mais leurs copies dans l'entrepôt de données ne reprennent généralement pas ces contraintes. La plupart des entrepôts de données cloud acceptent une déclaration FOREIGN KEY sans l'appliquer ; la documentation de BigQuery indique qu'il n'applique pas les contraintes de clé primaire et de clé étrangère. Nous expliquons dans un article distinct pourquoi Snowflake, BigQuery, Redshift et Databricks n'appliquent pas les clés étrangères.

Pourquoi les jointures internes masquent-elles les enregistrements orphelins ?

Une jointure interne ne renvoie que les lignes qui ont une correspondance des deux côtés ; une ligne enfant sans parent est donc tout simplement absente du résultat. Pas d'erreur, pas d'avertissement, pas de NULL à remarquer. Les totaux sont inférieurs à ce qu'ils devraient être, et rien dans le rapport lui-même ne révèle la différence.

SELECT a.branch_code,       SUM(p.amount) AS total_paidFROM   payments pJOIN   accounts a ON a.account_id = p.account_idWHERE  p.booking_date = DATE '2026-10-08'GROUP  BY
SELECT a.branch_code,       SUM(p.amount) AS total_paidFROM   payments pJOIN   accounts a ON a.account_id = p.account_idWHERE  p.booking_date = DATE '2026-10-08'GROUP  BY
SELECT a.branch_code,       SUM(p.amount) AS total_paidFROM   payments pJOIN   accounts a ON a.account_id = p.account_idWHERE  p.booking_date = DATE '2026-10-08'GROUP  BY

Chaque paiement dont l'account_id est absent de accounts disparaît avant le SUM. Le moyen le plus rapide de voir l'écart est de compter des deux façons :

SELECT  (SELECT COUNT(*) FROM payments   WHERE booking_date = DATE '2026-10-08')               AS all_payments,  (SELECT COUNT(*) FROM payments p   JOIN accounts a ON a.account_id = p.account_id   WHERE p.booking_date = DATE '2026-10-08')             AS
SELECT  (SELECT COUNT(*) FROM payments   WHERE booking_date = DATE '2026-10-08')               AS all_payments,  (SELECT COUNT(*) FROM payments p   JOIN accounts a ON a.account_id = p.account_id   WHERE p.booking_date = DATE '2026-10-08')             AS
SELECT  (SELECT COUNT(*) FROM payments   WHERE booking_date = DATE '2026-10-08')               AS all_payments,  (SELECT COUNT(*) FROM payments p   JOIN accounts a ON a.account_id = p.account_id   WHERE p.booking_date = DATE '2026-10-08')             AS

Si account_id est unique dans accounts, la différence correspond à vos orphelins plus les éventuelles lignes dont l'account_id est NULL.

Les clés déclarées mais non vérifiées peuvent aggraver la situation. Le planificateur de requêtes d'Amazon Redshift suppose que les clés déclarées sont valides, et AWS avertit que des clés invalides peuvent amener certaines requêtes à renvoyer des résultats incorrects.

Comment trouver les enregistrements orphelins en SQL ?

On trouve les enregistrements orphelins avec une anti-jointure : une requête qui renvoie les lignes enfants pour lesquelles aucune ligne parente correspondante n'existe. En SQL, on l'écrit sous la forme LEFT JOIN … WHERE parent_key IS NULL, NOT EXISTS ou EXCEPT sur les valeurs de clé distinctes. Sur des clés non NULL, les trois donnent le même résultat.

LEFT JOIN … IS NULL

SELECT p.payment_id, p.account_id, p.amount, p.booking_dateFROM   payments pLEFT   JOIN accounts a       ON a.account_id = p.account_idWHERE  a.account_id IS NULL  AND  p.account_id IS NOT NULL
SELECT p.payment_id, p.account_id, p.amount, p.booking_dateFROM   payments pLEFT   JOIN accounts a       ON a.account_id = p.account_idWHERE  a.account_id IS NULL  AND  p.account_id IS NOT NULL
SELECT p.payment_id, p.account_id, p.amount, p.booking_dateFROM   payments pLEFT   JOIN accounts a       ON a.account_id = p.account_idWHERE  a.account_id IS NULL  AND  p.account_id IS NOT NULL

Testez une colonne du parent qui ne peut pas être NULL dans une ligne appariée, idéalement la clé de jointure. Placez les conditions portant sur le parent dans la clause ON : WHERE a.status = 'ACTIVE' n'est jamais vrai pour une ligne sans correspondance, et la requête ne renverrait donc rien.

NOT EXISTS

SELECT p.payment_id, p.account_id, p.amount, p.booking_dateFROM   payments pWHERE  p.account_id IS NOT NULL  AND  NOT EXISTS (         SELECT 1         FROM   accounts a         WHERE  a.account_id = p.account_id       )
SELECT p.payment_id, p.account_id, p.amount, p.booking_dateFROM   payments pWHERE  p.account_id IS NOT NULL  AND  NOT EXISTS (         SELECT 1         FROM   accounts a         WHERE  a.account_id = p.account_id       )
SELECT p.payment_id, p.account_id, p.amount, p.booking_dateFROM   payments pWHERE  p.account_id IS NOT NULL  AND  NOT EXISTS (         SELECT 1         FROM   accounts a         WHERE  a.account_id = p.account_id       )

Cette forme se lit comme la question elle-même. Les clés parentes en double ne multiplient pas les lignes, et les NULL dans accounts.account_id ne peuvent pas la fausser : une égalité avec NULL n'est jamais satisfaite.

EXCEPT (MINUS) sur les clés distinctes

SELECT account_id FROM payments WHERE account_id IS NOT NULLEXCEPTSELECT account_id FROM
SELECT account_id FROM payments WHERE account_id IS NOT NULLEXCEPTSELECT account_id FROM
SELECT account_id FROM payments WHERE account_id IS NOT NULLEXCEPTSELECT account_id FROM

Cette forme renvoie les valeurs de clé manquantes distinctes, pas les lignes. C'est souvent la meilleure première question : une poignée de comptes manquants peut expliquer des milliers de paiements orphelins. Oracle écrit traditionnellement cet opérateur MINUS ; BigQuery exige EXCEPT DISTINCT. Les opérateurs ensemblistes considèrent deux NULL comme égaux, une raison de plus de filtrer explicitement les clés NULL.

Pourquoi NOT IN ne renvoie-t-il aucune ligne en présence d'un NULL ?

NOT IN ne renvoie aucune ligne si sa sous-requête contient ne serait-ce qu'un seul NULL, car la logique à trois valeurs de SQL rend inconnue toute comparaison avec ce NULL. x NOT IN (1, 2, NULL) signifie x <> 1 AND x <> 2 AND x <> NULL. Le dernier terme n'est jamais vrai, donc la condition entière n'est jamais vraie.

-- Looks right. Returns nothing if any accounts.account_id is NULL.SELECT p.payment_id, p.account_idFROM   payments pWHERE  p.account_id NOT IN (SELECT a.account_id FROM accounts a);
-- Looks right. Returns nothing if any accounts.account_id is NULL.SELECT p.payment_id, p.account_idFROM   payments pWHERE  p.account_id NOT IN (SELECT a.account_id FROM accounts a);
-- Looks right. Returns nothing if any accounts.account_id is NULL.SELECT p.payment_id, p.account_idFROM   payments pWHERE  p.account_id NOT IN (SELECT a.account_id FROM accounts a);

Pour un paiement dont le compte existe, une comparaison est fausse et la ligne est correctement exclue. Pour un compte manquant, chaque comparaison avec une vraie clé est vraie, mais celle avec NULL est inconnue ; la condition est donc inconnue, et WHERE ne conserve que les lignes vraies. Le résultat est un ensemble vide, impossible à distinguer de « aucun orphelin ».

L'échec est silencieux, avec un faux feu vert, et les colonnes de clé des entrepôts de données ne sont souvent pas déclarées NOT NULL. Les paiements dont l'account_id est lui-même NULL ne sont jamais retenus non plus. Utilisez NOT EXISTS, ou ajoutez au minimum WHERE a.account_id IS NOT NULL dans la sous-requête.

Quel modèle d'anti-jointure utiliser ?

Utilisez NOT EXISTS par défaut pour les contrôles d'orphelins au niveau des lignes, EXCEPT lorsque vous voulez la liste des valeurs de clé manquantes, et LEFT JOIN … IS NULL lorsque vous voulez aussi le nombre de correspondances dans la même passe. N'utilisez NOT IN que lorsque les deux colonnes sont garanties non NULL.

Modèle

Renvoie

NULL dans la clé parente

Clé étrangère NULL dans l'enfant

Lisibilité

Performances typiques

LEFT JOIN … IS NULL

Lignes enfants

Sûr

Signalée comme orpheline, sauf si filtrée

Familier ; l'intention se trouve dans la clause WHERE

Généralement planifié comme une anti-jointure

NOT EXISTS

Lignes enfants

Sûr

Signalée comme orpheline, sauf si filtrée

Se lit comme la question

Généralement planifié comme une anti-jointure

EXCEPT / MINUS

Valeurs de clé distinctes

Sûr

Renvoyée une fois comme NULL, sauf si filtrée

Court et clair pour des listes de clés

Dédoublonne les deux côtés ; adapté aux synthèses au niveau des clés

NOT IN

Lignes enfants

Dangereux : un seul NULL renvoie zéro ligne

Exclue en silence

Se lit bien, mais induit en erreur

Correct sur des colonnes non NULL ; peut obtenir un plan moins bon sur des colonnes qui acceptent les NULL

La plupart des optimiseurs planifient LEFT JOIN et NOT EXISTS de la même manière ; vérifiez le plan d'exécution sur votre plateforme.

Comment gérer les clés composites et les clés étrangères NULL ?

Pour une clé composite, faites correspondre toutes les colonnes de la clé ensemble, dans un seul prédicat, jamais colonne par colonne : une ligne est orpheline lorsque sa combinaison est absente, même si chaque valeur existe quelque part isolément. Les clés étrangères NULL exigent une décision délibérée avant de les compter : référence manquante, ou valeur légitimement vide.

Supposons que chaque hôpital possède son propre livret thérapeutique, identifié par (hospital_id, product_code) :

SELECT m.administration_id, m.hospital_id, m.product_codeFROM   medication_administrations mWHERE  m.hospital_id IS NOT NULL  AND  m.product_code IS NOT NULL  AND  NOT EXISTS (         SELECT 1         FROM   hospital_formulary f         WHERE  f.hospital_id  = m.hospital_id           AND  f.product_code = m.product_code       )
SELECT m.administration_id, m.hospital_id, m.product_codeFROM   medication_administrations mWHERE  m.hospital_id IS NOT NULL  AND  m.product_code IS NOT NULL  AND  NOT EXISTS (         SELECT 1         FROM   hospital_formulary f         WHERE  f.hospital_id  = m.hospital_id           AND  f.product_code = m.product_code       )
SELECT m.administration_id, m.hospital_id, m.product_codeFROM   medication_administrations mWHERE  m.hospital_id IS NOT NULL  AND  m.product_code IS NOT NULL  AND  NOT EXISTS (         SELECT 1         FROM   hospital_formulary f         WHERE  f.hospital_id  = m.hospital_id           AND  f.product_code = m.product_code       )

Deux contrôles séparés, « l'hôpital existe » et « le produit existe », réussissent tous deux pour un produit référencé uniquement à l'hôpital A et administré à l'hôpital B. Seul le prédicat combiné le détecte. EXCEPT gère naturellement les clés composites. Ne concaténez pas les clés en une seule chaîne : '1' || '23' et '12' || '3' entrent en collision.

Un paiement dont l'account_id est NULL ne pointe pas vers un compte manquant ; il ne pointe nulle part. Un paiement doit avoir un compte, tandis qu'une référence facultative comme referring_doctor_id peut être vide. Excluez les NULL de la requête de recherche d'orphelins et comptez-les séparément :

SELECT COUNT(*)                      AS total_rows,       COUNT(*) - COUNT(account_id)  AS
SELECT COUNT(*)                      AS total_rows,       COUNT(*) - COUNT(account_id)  AS
SELECT COUNT(*)                      AS total_rows,       COUNT(*) - COUNT(account_id)  AS

Comment trouver les enregistrements orphelins dans les grandes tables ?

Sur les grandes tables, comptez avant de lister, comparez les valeurs de clé distinctes plutôt que chaque ligne, et limitez le côté enfant au dernier chargement ou à la dernière partition. Gardez le côté parent complet : un paiement comptabilisé aujourd'hui peut faire référence à un compte ouvert il y a des années ; ne filtrez donc jamais le parent par date de chargement.

  1. Comptez d'abord. Exécutez l'anti-jointure sous forme de COUNT(*). Ne récupérez les lignes que si le nombre est non nul, et alors avec une limite.

  2. Comparez les clés distinctes. Réduisez d'abord le côté enfant à SELECT DISTINCT account_id. Les clés distinctes sont généralement bien moins nombreuses que les lignes.

  3. Filtrez sur le dernier chargement. Limitez l'enfant à la partition la plus récente ou à la dernière load_date, afin que le moteur puisse élaguer.

  4. Gardez la colonne de jointure comparable. Même type de données des deux côtés, pas de CAST ni de TRIM dans le prédicat, ce qui peut empêcher l'utilisation des index et l'élagage. Corrigez plutôt les formats au chargement ; consultez notre guide sur le nettoyage des données en SQL.

  5. Enregistrez le résultat. Conservez la date, le nombre de lignes évaluées et le nombre d'orphelins trouvés pour suivre la tendance.

WITH child_keys AS (  SELECT DISTINCT account_id  FROM   payments  WHERE  load_date = DATE '2026-10-08'    AND  account_id IS NOT NULL)SELECT COUNT(*) AS missing_account_idsFROM   child_keys kWHERE  NOT EXISTS (         SELECT 1 FROM accounts a WHERE a.account_id = k.account_id       )
WITH child_keys AS (  SELECT DISTINCT account_id  FROM   payments  WHERE  load_date = DATE '2026-10-08'    AND  account_id IS NOT NULL)SELECT COUNT(*) AS missing_account_idsFROM   child_keys kWHERE  NOT EXISTS (         SELECT 1 FROM accounts a WHERE a.account_id = k.account_id       )
WITH child_keys AS (  SELECT DISTINCT account_id  FROM   payments  WHERE  load_date = DATE '2026-10-08'    AND  account_id IS NOT NULL)SELECT COUNT(*) AS missing_account_idsFROM   child_keys kWHERE  NOT EXISTS (         SELECT 1 FROM accounts a WHERE a.account_id = k.account_id       )

Cette requête compte les clés manquantes, pas les lignes orphelines ; récupérez ensuite les lignes correspondant à ces clés.

Et si la table parente se trouve dans une autre base de données ?

Une anti-jointure ne fonctionne que si un même moteur de requête peut lire les deux tables. Si les paiements se trouvent dans l'entrepôt de données et les comptes dans la base du core banking, le SQL seul ne voit pas les deux : vous copiez alors un côté, utilisez un lien de base de données ou une requête fédérée, ou exécutez le contrôle dans un outil capable d'accéder aux deux connexions.

Une table de référence copiée est un pipeline de plus, avec son propre décalage : une copie périmée signale de faux orphelins ou passe à côté de vrais. Les liens de base de données dépendent de la prise en charge par la plateforme et exigent une validation de sécurité pour chaque nouvelle connexion.

Comment transformer une requête de recherche d'orphelins en contrôle permanent ?

Pour transformer une requête de recherche d'orphelins en contrôle permanent, exécutez-la à chaque chargement, enregistrez le nombre de lignes réussies et en échec, fixez un seuil d'échec et conservez les lignes en échec là où l'équipe responsable peut les voir. Dans digna, cela correspond à une seule règle Referential Integrity, configurée dans une boîte de dialogue, sans SQL à écrire.

digna Data Validation propose trois types de règles : Rule, Uniqueness et Referential Integrity. Le type référentiel correspond à l'anti-jointure de cet article : à partir de colonnes d'une source de données et d'un ensemble correspondant sur une autre, digna conserve les valeurs distinctes de l'autre table et fait échouer toute ligne sans correspondance. Le contrôle s'exécute dans votre base de données source ; vos données ne quittent jamais votre infrastructure. Depuis la Release 2026.01, il fonctionne entre différentes connexions de bases de données d'un même projet, sans répliquer les données.

Les captures d'écran ci-dessous utilisent les données de démonstration de digna pour Danubia Kliniken, un groupe hospitalier autrichien fictif.

Le 22 avril 2026, les services ont enregistré 82 administrations de Coavira 2.5 mg (code produit 3858646), qui ne figurait pas encore dans le référentiel produits de la pharmacie. Chaque rapport joignant les doses aux produits affichait 0 dose de ce produit, alors que le personnel infirmier en avait administré 82. La règle hc_product_in_master a échoué : 4 244 lignes sur 4 326 ont réussi. À la main, il vous faudrait :

SELECT m.*FROM   hospital_medication_administrations mWHERE  m.product_code IS NOT NULL  AND  NOT EXISTS (         SELECT 1         FROM   hospital_medications p         WHERE  p.product_code = m.product_code       )
SELECT m.*FROM   hospital_medication_administrations mWHERE  m.product_code IS NOT NULL  AND  NOT EXISTS (         SELECT 1         FROM   hospital_medications p         WHERE  p.product_code = m.product_code       )
SELECT m.*FROM   hospital_medication_administrations mWHERE  m.product_code IS NOT NULL  AND  NOT EXISTS (         SELECT 1         FROM   hospital_medications p         WHERE  p.product_code = m.product_code       )

La vue Invalid Records affiche ce jeu de résultats sans que personne n'ait à écrire la requête :

Vue Invalid Records de digna, filtre Failed, contrôle Full - hc_product_in_master, avec la liste des administrations de médicaments : hôpital, service, département, product_code 3858646 et medication_name Coavira 2.5 mg

Invalid Records, filtré sur Failed : chaque dose orpheline avec l'hôpital, le service, le département, le code produit et le nom du médicament.

Configuration de la règle :

  1. Configuration → source de données hospital_medication_administrations → onglet Data Validation → Add Rule. La boîte de dialogue Add Data Validation Rule s'ouvre.

  2. Saisissez un Name (hc_product_in_master) et une Description.

  3. Réglez Type sur Referential Integrity et choisissez dans Attributes (attributs) la colonne product_code.

  4. Sous must exist in (doit exister dans), choisissez la Data Source hospital_medications et ses Attributes product_code. Pour une clé composite, choisissez plusieurs colonnes des deux côtés, dans le même ordre ; les listes de longueurs différentes sont rejetées.

  5. Choisissez le Threshold Mode (mode de seuil) Absolute ou Relative et définissez l'Info threshold et le Warn threshold (ici : Absolute, Info 0, Warn 1). Enregistrez. La règle s'exécute à chaque inspection, planifiée ou à la demande.

Boîte de dialogue Add Data Validation Rule de digna pour hc_product_in_master : Type Referential Integrity, Attributes product_code, must exist in Data Source hospital_medications, Attributes product_code, Threshold Mode Absolute, Info 0, Warn 1

La règle complète : deux listes d'attributs, une source de données cible et deux seuils.

Referential Integrity ignore les NULL, comme le filtre IS NOT NULL ci-dessus ; si la présence est obligatoire, ajoutez une règle distincte de type Rule avec product_code IS NOT NULL. Au-dessus de l'Info threshold, le statut est Uncertain ; au-dessus du Warn threshold, il est Failed. Avec Info à 0, le moindre orphelin fait donc sortir la règle de Passed. Les enregistrements en échec correspondent à la même requête avec la condition de réussite inversée ; ils sont exportables, et les résultats peuvent notifier l'équipe responsable des données.

Depuis la Release 2026.06, les règles peuvent aussi être gérées sous forme de code via le SDK Python (pip install digna-sdk). Pour la procédure complète, consultez notre article sur la configuration d'un contrôle d'intégrité référentielle dans digna ou la vidéo de configuration de 2 min 26.

Les trouver une fois, puis les tenir à l'écart

Pour enquêter sur les enregistrements orphelins : NOT EXISTS pour les lignes, EXCEPT pour les clés manquantes, jamais NOT IN sur une colonne qui peut contenir des NULL, et une décision délibérée sur les NULL. Les tenir à l'écart demande davantage : appliquer les clés étrangères là où la base de données le permet, charger les parents en premier, traiter explicitement les données de référence arrivant en retard et exécuter le contrôle référentiel à chaque chargement.

Pour voir ce contrôle s'exécuter sur vos propres tables, au sein de votre propre infrastructure, réservez une démo avec l'équipe digna.

Questions fréquentes

Comment trouver les enregistrements orphelins en SQL ?

Utilisez une anti-jointure qui renvoie les lignes enfants sans parent correspondant. La forme la plus robuste est NOT EXISTS avec une sous-requête corrélée sur la clé ; LEFT JOIN … WHERE parent_key IS NULL donne le même résultat. Filtrez d'abord les clés étrangères NULL et comptez-les dans un contrôle de complétude distinct.

Pourquoi NOT IN ne renvoie-t-il aucune ligne lorsque la sous-requête contient un NULL ?

À cause de la logique à trois valeurs. x NOT IN (1, 2, NULL) se développe en x <> 1 AND x <> 2 AND x <> NULL, et la dernière comparaison est inconnue, jamais vraie. WHERE ne conserve que les lignes vraies ; la requête ne renvoie donc rien, ce qui ressemble exactement à un résultat propre.

NOT EXISTS est-il plus rapide que LEFT JOIN IS NULL ?

En général, aucun des deux n'est plus rapide : la plupart des optimiseurs modernes planifient les deux comme une anti-jointure, et le choix se résume donc à la lisibilité. NOT IN est l'exception. Sur des colonnes qui acceptent les NULL, il peut obtenir un plan moins bon, et il ne renvoie aucune ligne lorsque la sous-requête contient un NULL.

Quelle est la différence entre un enregistrement orphelin et une clé étrangère NULL ?

Un enregistrement orphelin pointe vers une clé parente qui n'existe pas, tandis qu'une clé étrangère NULL ne pointe nulle part. Ils nécessitent des contrôles différents : l'intégrité référentielle pour les orphelins, et une règle IS NOT NULL lorsque la référence est obligatoire. C'est précisément pour cette raison que la règle Referential Integrity de digna ignore les NULL.

Comment contrôler automatiquement les enregistrements orphelins après chaque chargement ?

Transformez l'anti-jointure en un contrôle planifié, avec des seuils et des résultats enregistrés. Dans digna, il s'agit d'une seule règle Referential Integrity dans Data Validation : choisissez les colonnes, choisissez la source de données dans laquelle elles doivent exister, définissez les seuils Info et Warn, enregistrez. La règle s'exécute dans votre base de données à chaque inspection.

✦ Généré avec l'intelligence artificielle

Partager sur X
Partager sur X
Partager sur Facebook
Partager sur Facebook
Partager sur LinkedIn
Partager sur LinkedIn

Rencontrez l'équipe derrière la plateforme

Une équipe viennoise d'experts en IA, en données et en logiciel, portée

par la rigueur académique et l'expérience de l'entreprise.

Rencontrez l'équipe derrière la plateforme

Une équipe viennoise d'experts en IA, en données et en logiciel, portée par la rigueur académique et l'expérience de l'entreprise.

Produit

Intégrations

Ressources

Société

INDEXED BYIndexerNow INDEXED BYIndexerNow