IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Développement SQL Server Discussion :

Simplification des test sur des NULL [2014]


Sujet :

Développement SQL Server

  1. #1
    Expert éminent
    Avatar de StringBuilder
    Homme Profil pro
    Chef de projets
    Inscrit en
    Février 2010
    Messages
    4 153
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Chef de projets
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2010
    Messages : 4 153
    Points : 7 403
    Points
    7 403
    Billets dans le blog
    1
    Par défaut Simplification des test sur des NULL
    Bonjour,

    Je suis en train de travailler sur l'alimentation d'un infocentre à partir d'une base de données relationnelle.

    Mon programme doit gérer des flux en différentiel.

    J'ai donc opté pour une base tampon dans laquelle j'archive, pour chaque export des données, l'ensemble des données "telles qu'elles devraient être" dans l'infocentre.

    Puis avec une vue, je filtre les lignes qui sont effectivement différentes d'une "version" à l'autre.

    Voici un exemple simplifié :
    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
     
    create table tampon.dbo.client
    (
        version tinyint not null,
        id int not null,
        nom varchar(30) null,
        prenom varchar(30) null,
        primary key (version, id)
    );
    go
     
    -- Avant d'alimenter un nouveau jeu de données, on augmente l'âge des données déjà présentes (ouais je sais, c'est mal, je met à jour la clé primaire)
    update tampon.dbo.client set version = version + 1;
     
    -- On récupère les données à synchroniser
    insert into tampon.dbo.client (version, id, nom, prenom)
    select 1, c.id, n.nom, p.prenom
    from client c
    left outer join nom n on n.id = c.nom_id and c.politiquementcorrect = 1
    left outer join prenom p on p.id = c.prenom_id and p.politiquementcorrect = 1
    where c.statut = 'ACTIF';

    Jusque là, tout va bien.
    J'ai donc à chaque fois la liste de tous mes clients actifs, avec leurs noms et prénoms à partir du moment où ils sont politiquement correct.

    Maintenant, on passe à la vue, dans la base "tampon" :
    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
     
    create view dbo.v_client
    with schemabinding
    as
    select 'NEW' statut, c1.id, c1.nom, c1.prenom
    from dbo.client c1
    where c1.version = 1
    and not exists (select null from dbo.client c2 where c2.version = 2 and c2.id = c1.id)
    union all
    select 'DEL' statut, c1.id, c1.nom, c1.prenom
    from dbo.client c1
    where c1.version = 2
    and not exists (select null from dbo.client c2 where c2.version = 1 and c2.id = c1.id)
    union all
    select 'UPD' statut, c1.id, c1.nom, c1.prenom
    from dbo.client c1
    inner join dbo.client c2 on c2.version = 2 and c2.id = c1.id
    where c1.version = 1
    and (
       c1.nom <> c2.nom
    or c1.prenom <> c2.prenom
    );

    Sauf que là, la partie "UPD" ne fonctionne pas, à cause des NULL

    Du coup, pour chaque colonne, je dois mettre ce code à ralonge :
    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    c1.val <> c2.val or (c1.val is null and c2.val is not null) or (c1.val is not null and c2.val is null)

    Seul souci :
    1/ C'est illisible
    2/ C'est ultra redondant
    3/ J'ai une dizaine de tables à synchroniser avec jusqu'à une cinquantaine de colonnes pour certaines
    4/ Je ne veux pas remplacer ce code par des "isnull(val, '')" et "isnull(val, 0)" car c'est pas spécialement plus lisible ni concis, mais en plus ça demande à se poser la question du type de chaque colonne, mais surtout si demain je place des index sur ces tables pour améliorer les performances de la vue, ça ne pourra pas utiliser les index

    Bref : comment faire ?

    Question subsidiaire : la méthode adoptée vous semble-t-elle adaptée au besoin ?
    On ne jouit bien que de ce qu’on partage.

  2. #2
    Expert éminent
    Avatar de StringBuilder
    Homme Profil pro
    Chef de projets
    Inscrit en
    Février 2010
    Messages
    4 153
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Chef de projets
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2010
    Messages : 4 153
    Points : 7 403
    Points
    7 403
    Billets dans le blog
    1
    Par défaut
    Avec une formule Excel, j'ai pu pondre "rapidement" cette abomination...
    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
     
       p1.espece <> p2.espece or (p1.espece is null and p2.espece is not null) or (p2.espece is null and p1.espece is not null)
    or p1.sous_espece <> p2.sous_espece or (p1.sous_espece is null and p2.sous_espece is not null) or (p2.sous_espece is null and p1.sous_espece is not null)
    or p1.segmentation_metier <> p2.segmentation_metier or (p1.segmentation_metier is null and p2.segmentation_metier is not null) or (p2.segmentation_metier is null and p1.segmentation_metier is not null)
    or p1.abattoir <> p2.abattoir or (p1.abattoir is null and p2.abattoir is not null) or (p2.abattoir is null and p1.abattoir is not null)
    or p1.fournisseur1 <> p2.fournisseur1 or (p1.fournisseur1 is null and p2.fournisseur1 is not null) or (p2.fournisseur1 is null and p1.fournisseur1 is not null)
    or p1.fournisseur2 <> p2.fournisseur2 or (p1.fournisseur2 is null and p2.fournisseur2 is not null) or (p2.fournisseur2 is null and p1.fournisseur2 is not null)
    or p1.fournisseur3 <> p2.fournisseur3 or (p1.fournisseur3 is null and p2.fournisseur3 is not null) or (p2.fournisseur3 is null and p1.fournisseur3 is not null)
    or p1.fournisseur4 <> p2.fournisseur4 or (p1.fournisseur4 is null and p2.fournisseur4 is not null) or (p2.fournisseur4 is null and p1.fournisseur4 is not null)
    or p1.groupement <> p2.groupement or (p1.groupement is null and p2.groupement is not null) or (p2.groupement is null and p1.groupement is not null)
    or p1.mode_reproduction_male <> p2.mode_reproduction_male or (p1.mode_reproduction_male is null and p2.mode_reproduction_male is not null) or (p2.mode_reproduction_male is null and p1.mode_reproduction_male is not null)
    or p1.mode_reproduction_femelle <> p2.mode_reproduction_femelle or (p1.mode_reproduction_femelle is null and p2.mode_reproduction_femelle is not null) or (p2.mode_reproduction_femelle is null and p1.mode_reproduction_femelle is not null)
    or p1.potentiel <> p2.potentiel or (p1.potentiel is null and p2.potentiel is not null) or (p2.potentiel is null and p1.potentiel is not null)
    or p1.veterinaire <> p2.veterinaire or (p1.veterinaire is null and p2.veterinaire is not null) or (p2.veterinaire is null and p1.veterinaire is not null)
    or p1.reference <> p2.reference or (p1.reference is null and p2.reference is not null) or (p2.reference is null and p1.reference is not null)
    or p1.laiterie <> p2.laiterie or (p1.laiterie is null and p2.laiterie is not null) or (p2.laiterie is null and p1.laiterie is not null)
    or p1.race <> p2.race or (p1.race is null and p2.race is not null) or (p2.race is null and p1.race is not null)
    or p1.type_complementation <> p2.type_complementation or (p1.type_complementation is null and p2.type_complementation is not null) or (p2.type_complementation is null and p1.type_complementation is not null)
    or p1.date_modification <> p2.date_modification or (p1.date_modification is null and p2.date_modification is not null) or (p2.date_modification is null and p1.date_modification is not null)
    or p1.cheptel <> p2.cheptel or (p1.cheptel is null and p2.cheptel is not null) or (p2.cheptel is null and p1.cheptel is not null)
    or p1.nombre_truies <> p2.nombre_truies or (p1.nombre_truies is null and p2.nombre_truies is not null) or (p2.nombre_truies is null and p1.nombre_truies is not null)
    or p1.place_ps <> p2.place_ps or (p1.place_ps is null and p2.place_ps is not null) or (p2.place_ps is null and p1.place_ps is not null)
    or p1.place_engraissement <> p2.place_engraissement or (p1.place_engraissement is null and p2.place_engraissement is not null) or (p2.place_engraissement is null and p1.place_engraissement is not null)
    or p1.surface <> p2.surface or (p1.surface is null and p2.surface is not null) or (p2.surface is null and p1.surface is not null)
    or p1.robot_traite <> p2.robot_traite or (p1.robot_traite is null and p2.robot_traite is not null) or (p2.robot_traite is null and p1.robot_traite is not null)
    or p1.code_client_erp <> p2.code_client_erp or (p1.code_client_erp is null and p2.code_client_erp is not null) or (p2.code_client_erp is null and p1.code_client_erp is not null)

    Mais mon dieu que c'est laid...
    On ne jouit bien que de ce qu’on partage.

  3. #3
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    21 768
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Expert bases de données / SQL / MS SQL Server / Postgresql
    Secteur : Conseil

    Informations forums :
    Inscription : Mai 2002
    Messages : 21 768
    Points : 52 719
    Points
    52 719
    Billets dans le blog
    5
    Par défaut
    Pour savoir si 2 requêtes donnent des résultats identiques, il suffit de faire :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    WITH
    TA AS (SELECT ...), --> première requête
    TB AS (SELECT ...)  --> seconde requête
    SELECT * FROM TA
    EXCEPT
    SELECT * FROM TB
    UNION ALL
    SELECT * FROM TB
    EXCEPT
    SELECT * FROM TA;
    Le résultat est l'ensemble vide si les deux résultats sont identique.

    À partir de là, vous devriez trouver !

    A +
    Frédéric Brouard - SQLpro - ARCHITECTE DE DONNÉES - expert SGBDR et langage SQL
    Le site sur les SGBD relationnels et le langage SQL: http://sqlpro.developpez.com/
    Blog SQL, SQL Server, SGBDR : http://blog.developpez.com/sqlpro
    Expert Microsoft SQL Server - M.V.P. (Most valuable Professional) MS Corp.
    Entreprise SQL SPOT : modélisation, conseils, audit, optimisation, formation...
    * * * * * Expertise SQL Server : http://mssqlserver.fr/ * * * * *

  4. #4
    Expert éminent
    Avatar de StringBuilder
    Homme Profil pro
    Chef de projets
    Inscrit en
    Février 2010
    Messages
    4 153
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Chef de projets
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2010
    Messages : 4 153
    Points : 7 403
    Points
    7 403
    Billets dans le blog
    1
    Par défaut
    En effet, cette approche me semble pas mal du tout

    Je vais voir comment l'adapter à mon cas (car j'ai besoin de savoir pour chaque ligne si c'est des NEW, UPD ou DEL).

    Mais ça me semble tout à fait jouable et moins usine à gaz
    On ne jouit bien que de ce qu’on partage.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [Débutant] Effectuer des tests sur des données
    Par Domino5731 dans le forum Signal
    Réponses: 5
    Dernier message: 02/05/2012, 10h33
  2. Réponses: 4
    Dernier message: 20/06/2011, 02h01
  3. [JUnit] Effectuer des tests sur des traitements de fichiers
    Par Baptiste Wicht dans le forum Tests et Performance
    Réponses: 3
    Dernier message: 12/03/2010, 18h10
  4. [A-03] Test sur des dates dans des textBox
    Par moilou2 dans le forum IHM
    Réponses: 3
    Dernier message: 27/10/2008, 13h39
  5. [XSD] comment faire des tests sur des éléments
    Par attila771 dans le forum Valider
    Réponses: 1
    Dernier message: 11/10/2007, 12h32

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo