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

MS SQL Server Discussion :

Insérer colonne de table A à la fin de table B


Sujet :

MS SQL Server

  1. #1
    Membre à l'essai
    Inscrit en
    Juin 2003
    Messages
    9
    Détails du profil
    Informations forums :
    Inscription : Juin 2003
    Messages : 9
    Points : 12
    Points
    12
    Par défaut Insérer colonne de table A à la fin de table B
    Mon problème à résoudre:
    Table A:
    colones a,b,c,d
    Table B:
    colones e,b,g,h

    Résultats souhaités :
    Table B:
    colones e,f,g,h,d

    Comme vous le constatez les deux tables ont pour commun la colonne b que je peux utiliser comme clef pour la jointure.

    Le travail demandé c'est de "updater" la table B avec la colonne d de la table A. Compris d'une autre facon c'est d'ajouter la colonne d de la table A a la table B.

    Bien évidement j'ai commencé par créer la colonne "d" sur la table B, maintenant il me reste à insérer les éléments de "d" de la table A dans la colonne d de la table B.

    J'ai essayé d'ecrire ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    update ...dbo.B
    set B.d = (
                  select 
                         d
                   from ...dbo.A 
                   where A.b=B.b
                )
    J'obtiens l'erreur suivante :
    Msg 512, Level 16, State 1, Line 1
    Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.
    The statement has been terminated.
    En fait l'erreur retournée était prévisible car je pense bien que j'essaie d’insérer le résultat de mon select (plusieurs lignes retournées) dans une seule ligne ce qui n'est pas possible.
    Dois-je utiliser un curseur ? Ou bien existe il une methode sans curseur. Si oui priere d’écrire l'esquisse de la procédure que se soit avec ou sans curseur.

    Je vous serai reconnaissant de recevoir de l'aide car mon stage en dépend.

    Merci bien.

  2. #2
    Expert éminent sénior
    Avatar de fsmrel
    Homme Profil pro
    Spécialiste en bases de données
    Inscrit en
    Septembre 2006
    Messages
    8 114
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Spécialiste en bases de données
    Secteur : Conseil

    Informations forums :
    Inscription : Septembre 2006
    Messages : 8 114
    Points : 31 602
    Points
    31 602
    Billets dans le blog
    16
    Par défaut
    Bonjour edmotets,


    Essayez d’être rigoureux. Dans sa 2e version, l’en-tête de votre table B est doté d’une colonne f dont on se demande ce qu’elle vient faire là. Plus important, définissez précisément les clés primaires de vos tables. Si la table B doit comporter le même nombre de lignes avant et après update, alors la colonne b utilisée pour la jointure devrait être clé.

    Pour voir à quoi ressemblera le contenu de la table B, créez une table C ayant la même structure d'en-tête (e, b, g, h, d) et valorisée en exécutant la requête :

    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    INSERT INTO C (e, b, g, h, d) 
           SELECT B.e, B.g, B.g, B.h, A.d
           FROM   B JOIN A ON B.b = A.b ;

    Maintenant, un DISTINCT pourra peut-être vous aider :

    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    INSERT INTO C (e, b, g, h, d) 
           SELECT DISTINCT B.e, B.g, B.g, B.h, A.d
           FROM   B JOIN A ON B.b = A.b ;

    Même chose en ce qui concerne votre UPDATE (s’il survit en l’état) quand le résultat de l’insert sera conforme à ce que vous attendez :

    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    UPDATE B
           SET d = (SELECT DISTINCT d 
                   FROM   A
                   WHERE  A.b = B.b) ;

    Et surtout, définissez très précisément les clés primaires de vos tables.

  3. #3
    Membre à l'essai
    Inscrit en
    Juin 2003
    Messages
    9
    Détails du profil
    Informations forums :
    Inscription : Juin 2003
    Messages : 9
    Points : 12
    Points
    12
    Par défaut
    fsmrel, merci de me repondre.
    Je vous mettrai au courant du resultat apres implementation.

    edmotets

  4. #4
    Modérateur

    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Janvier 2005
    Messages
    5 826
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Administrateur de base de données
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Janvier 2005
    Messages : 5 826
    Points : 12 371
    Points
    12 371
    Par défaut
    Bonjour,

    Typiquement l'UPDATE aurait pu s'écrire :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    UPDATE		dbo.B
    SET		d = A.d
    FROM		dbo.B AS B
    INNER JOIN	dbo.A AS A
    			ON A.b = B.b
    Cela étant s'il existe plusieurs valeurs de d pour le même b, vous êtes obligé d'utiliser la clause DISTINCT, qui, rappelons-le, n'est pas ensembliste.
    D'autre part le DISTINCT ne vous garantit en rien que les valeurs de b retournées pour un d sont uniques au sein de ce "groupe".

    Dois-je utiliser un curseur ? Ou bien existe il une methode sans curseur. Si oui priere d’écrire l'esquisse de la procédure que se soit avec ou sans curseur.
    Par pitié, bannissez les curseurs !
    D'autre part il n'y a aucunement besoin de curseurs dans votre cas, ni lorsque la base de données est proprement modélisée, et que le modèle répond au problème à résoudre.

    @++

  5. #5
    Expert éminent sénior
    Avatar de fsmrel
    Homme Profil pro
    Spécialiste en bases de données
    Inscrit en
    Septembre 2006
    Messages
    8 114
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Spécialiste en bases de données
    Secteur : Conseil

    Informations forums :
    Inscription : Septembre 2006
    Messages : 8 114
    Points : 31 602
    Points
    31 602
    Billets dans le blog
    16
    Par défaut
    Bonsoir,


    Citation Envoyé par elsuket Voir le message
    s'il existe plusieurs valeurs de d pour le même b, vous êtes obligé d'utiliser la clause DISTINCT, qui, rappelons-le, n'est pas ensembliste.
    Le rôle de DISTINCT n’est pas « d’être » ensembliste, mais de pallier le laxisme de SQL qui permet — hélas ! — d’opérer sur des sacs (bags) : en codant DISTINCT, nous demandons au coupable SQL de bien vouloir éliminer les doublons, ce qui nous permet au moins de manipuler des ensembles plutôt que de la dynamite.

  6. #6
    Modérateur

    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Janvier 2005
    Messages
    5 826
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Administrateur de base de données
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Janvier 2005
    Messages : 5 826
    Points : 12 371
    Points
    12 371
    Par défaut
    Bonjour fmsrel,

    Je ne comprend pas pourquoi tu dis que SQL est laxiste en ce qui concerne le DISTINCT, même si j'ai compris l'erreur de mon expression.

    Dans l'hypothèse où le modèle de données est correct et qu'il répond précisément au problème à résoudre, il n'est à mon sens pas nécessaire dans le cas qu'expose edmotets d'utiliser la clause DISTINCT.

    Malheureusement je constante bien souvent que DISTINCT est utilisé à tors et à travers pour "palier" à des erreurs de conception ...

    @++

  7. #7
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    21 917
    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 917
    Points : 51 693
    Points
    51 693
    Billets dans le blog
    6
    Par défaut
    François à raiosn,, dans le sens ou SQL permet de se retrouver avec des réponses contenant des doublons. Or l'algèbre relationnelle repose sur 2 concepts fondamentaux :
    1) une relation à toujours une clef => aucun doublon
    2) toutes les données d'une relation sont valuées (pas de NULL).

    Concernant le 1, cela est valable pour toute opération relationnelle puisque mathématiquement si j'ai les relation R1 et R2, alors toute opération O sur R1, R2 doit donner une nouvelle relation qui elle même est donc sans doublon car doté d'une clef, sinon cela ne serait pas une relation !

    Or SQL ne respecte pas ce principe relationnel dans le sens ou toute requête est susceptible de renvoyer des doublons...

    Exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    CREATE TABLE T (C INT PRIMARY KEY, D INT);
    INSERT INTO T VALUES (1, 10), (2, 10);
    SELECT D FROM T;
    DISTINCT n'est donc qu'un palliatif (d'ailleurs couteux) du fait que SQL ne sait pas opérer sur de véritables relations.....

    A +

  8. #8
    Expert éminent sénior
    Avatar de fsmrel
    Homme Profil pro
    Spécialiste en bases de données
    Inscrit en
    Septembre 2006
    Messages
    8 114
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Spécialiste en bases de données
    Secteur : Conseil

    Informations forums :
    Inscription : Septembre 2006
    Messages : 8 114
    Points : 31 602
    Points
    31 602
    Billets dans le blog
    16
    Par défaut
    Bonjour,


    Citation Envoyé par elsuket Voir le message
    Je ne comprend pas pourquoi tu dis que SQL est laxiste en ce qui concerne le DISTINCT, même si j'ai compris l'erreur de mon expression.
    Je n’ai pas dit que SQL est laxiste en ce qui concerne le DISTINCT, mais que SQL est laxiste parce qu'il produit des doublons sans que ça le gêne. Coder DISTINCT est le bistouri qui nous permet parfois de rattraper le coup, de palier les carences du Sorry Query Language quand le résultat nous parvient sous forme de sac (bag aka multiset) et non pas d’ensemble (set).

    Ainsi, quand on code :

    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    UPDATE B
           SET d = (SELECT d 
                    FROM   A
                    WHERE  A.b = B.b) ;

    Alors le résultat du SELECT emboîté :

    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    SELECT d 
    FROM   A
    WHERE  A.b = B.b

    N’est pas un ensemble, mais un sac.

    Exemple : prenons des structures du genre de celles proposées par edmotets :


    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
    CREATE TABLE A
    (
            a      char(4)       not null
          , b      char(4)       not null 
          , c      char(4)       not null 
          , d      char(4)       not null 
    ) ;
     
    CREATE TABLE B
    (
            e      char(4)       not null
          , b      char(4)       not null
          , g      char(4)       not null 
          , h      char(4)       not null 
          , d      char(4)       not null default ''
    ) ;

    Constituons un bout de jeu d’essai :

    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    INSERT INTO A (a, b, c, d) VALUES ('a2', 'b2', 'c2', 'd1') ;
    INSERT INTO A (a, b, c, d) VALUES ('a3', 'b2', 'c3', 'd1') ; 
     
    INSERT INTO B (e, b, g, h) VALUES ('e1', 'b2', 'g2', 'h2') ;

    Le résultat du SELECT emboîté n’est pas l’ensemble {d1}, mais le sac : (d1, d1) — notez l’emploi des accolades dans un cas et des parenthèses dans l’autre.

    Comme disait Ted Codd (RIP) : « If something is true, saying it twice doesn’t make it any more true ». En l’occurrence, SQL viole le principe de fermeture relationnelle⁽¹⁾ selon lequel le fruit du mariage de deux relations doit lui aussi être une relation. Si par hypothèse les valeurs prises par les variables A et B sont des relations, le fruit de leur union ne doit pas être le sac (d1, d1) et le bistouri DISTINCT permet de lui rendre la nature de ses parents. Maintenant, si par hypothèse A et B sont des sacs, alors le sac (d1, d1) est bien de même nature que ses parents, mais quant à l’algèbre correspondante on s’embarque pour des terrae algebricae incognitae et je vous renvoie en l’occurrence au chapitre 10 « Double Trouble, Double Trouble » de l’ouvrage de C.J. Date : Date on Database, Writings 2000-2006, et au chapitre 12 « The Theory of Bags » de son ouvrage Logic and Databases, The Roots of Relational Theory où l’auteur explore le sujet.

    SQL a un comportement bizarre, pour ne pas dire contradictoire, puisqu’il me permet de produire le sac (d1, d1) tandis qu’il m’interdit de m’en servir en tant qu'opérande sous la forme d'un sac emboîté, sauf à transformer moi-même celui-ci en ensemble, suite à quoi l’UPDATE que j’ai proposé fonctionne...


    A propos des clés :

    On ne sait pas si les tables utilisées chez lui par edmotets ont des clés, en l’état ce sont ici des sacs.

    En effet, quand il écrit :
    les deux tables ont pour commun la colonne b que je peux utiliser comme clef pour la jointure
    Je ne sais pas ce qu’il veut dire, car l’expression « clef pour la jointure » ne fait partie du langage. Quoi qu’il en soit, {B} n’est pas clé de la table A, car si c’était le cas, toute tentative d’insertion de doublons dans A aurait déjà été rejetée d’entrée et la situation vécue par edmotets n’aurait pas pu se produire.


    Remplaçons maintenant dans la table A la valeur <'a3', 'b2', 'c3', 'd1'> par <'a3', 'b2', 'c3', 'd3'>.

    Inserts correspondants :

    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    INSERT INTO A (a, b, c, d) VALUES ('a2', 'b2', 'c2', 'd1') ;
    INSERT INTO A (a, b, c, d) VALUES ('a3', 'b2', 'c3', 'd3') ;

    L’UPDATE que j’ai proposé ne fonctionne pas puisque le fruit (d1, d3) du mariage de A et B n’est pas un doublon : le bistouri DISTINCT a autant d’efficacité qu’un cautère sur une jambe de bois.

    Mais passons à votre requête :

    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    UPDATE       dbo.B
    SET          d = A.d
    FROM         dbo.B AS B
    INNER JOIN   dbo.A AS A
                          ON A.b = B.b

    En supposant que la table B ait la valeur initiale suivante :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    B    e    b    g    h    d
         ---------------------
         e1   b2   g2   h2
    Et la table A (conformément aux derniers inserts ci-dessus) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    A    a    b    c    d 
         -----------------
         a2   b2   c2   d1
         a3   b2   c3   d3
    Après exécution de votre UPDATE, au résultat on obtient :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    B    e    b    g    h    d
         ----------------------
         e1   b2   g2   h2   d1
    Quel rôle a joué la valeur 'd3' prise par la colonne d de la table A (2e ligne de la table) ?


    Et si on permute la séquence d’exécution des INSERT dans la table A :

    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    INSERT INTO A (a, b, c, d) VALUES ('a3', 'b2', 'c3', 'd3') ;
    INSERT INTO A (a, b, c, d) VALUES ('a2', 'b2', 'c2', 'd1') ;

    Au résultat on obtient :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    B    e    b    g    h    d
         ----------------------
         e1   b2   g2   h2   d3
    A son tour, qu’est-il advenu de 'd1' ?

    Quoi qu’il en soit, dans les deux cas le 2e INSERT est superbement ignoré par SQL. Je reste quant à la signification de la chose...
    Il y a certainement une explication rationnelle à ce comportement de SQL (sinon du SGBD), mais intuitivement je ne la trouve pas. Si quelqu’un peut m’éclairer...

    ________

    ⁽¹⁾Fermeture relationnelle

    Je cite et traduis C.J. Date (An Introduction to Database Systems, 8th edition, pages 175-176) :

    Le fait que le résultat de chaque opération relationnelle soit une autre relation correspond à ce qu’on appelle la propriété de fermeture relationnelle. En résumé, cela veut dire qu’on peut écrire des expressions relationnelles emboîtées, c'est-à-dire des expressions relationnelles dans lesquelles les opérandes sont eux-mêmes représentés par des expressions relationnelles de complexité quelconque. (Il y a une analogie évidente entre la possibilité d’emboîter des expressions relationnelles en algèbre relationnelle et la possibilité d’emboîter des expressions arithmétiques en arithmétique traditionnelle ; en effet, le fait que les relations soient fermées pour l’algèbre a autant d’importance et pour les mêmes raisons, que le fait que les nombres soient fermés en arithmétique traditionnelle).

    N.B. La fermeture dont il est question ici n’a pas le même sens que celle dont il est question avec les dépendances fonctionnelles.

  9. #9
    Modérateur
    Avatar de Waldar
    Homme Profil pro
    Sr. Specialist Solutions Architect @Databricks
    Inscrit en
    Septembre 2008
    Messages
    8 453
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Sr. Specialist Solutions Architect @Databricks
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2008
    Messages : 8 453
    Points : 18 394
    Points
    18 394
    Par défaut
    Citation Envoyé par fsmrel Voir le message
    Quoi qu’il en soit, dans les deux cas le 2e INSERT est superbement ignoré par SQL. Je reste quant à la signification de la chose...
    Il y a certainement une explication rationnelle à ce comportement de SQL (sinon du SGBD), mais intuitivement je ne la trouve pas. Si quelqu’un peut m’éclairer...
    Cela dépend bien des SGBD.
    J'ai cru en première lecture que SQL-Server avait mis à jour la ligne puis l'avait immédiatement écrasée derrière par l'autre donnée éligible.
    Hors l'ordre de mise à jour m'indique clairement :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    SELECT *
    FROM         dbo.B AS B
    INNER JOIN   dbo.A AS A ON A.b = B.b;
    -- (2 row(s) affected)
     
    UPDATE       B
    SET          B.d = A.d
    FROM         dbo.B AS B
    INNER JOIN   dbo.A AS A ON A.b = B.b;
    -- (1 row(s) affected)
    Son concurrent de toujours interdit cette mise à jour (la syntaxe des mises à jour de vue diffère légèrement) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    UPDATE (SELECT B.d as B_D
                 , A.d as A_d
              FROM B
        INNER JOIN A
                ON A.b = B.b)
       SET B_D = A_D;
     
    ORA-01779: impossible de modifier une colonne correspondant à une table non protégée par clé
    Sous ce message pas complètement compréhensible se cache l'obligation d'une déclaration de clef étrangère entre les deux tables, que je suis bien incapable de déclarer compte-tenu de la non-unicité de la colonne A.b.

    L'autre syntaxe basée sur un MERGE essaie bien de réaliser l'opération mais n'y parvient pas plus, avec un autre message d'erreur cette fois-ci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    merge into B
    using A
       on (B.b = A.b)
     when matched then update
      set B.d = A.b;
     
    ORA-30926: impossible d'obtenir un ensemble de lignes stables dans les tables source

    Pour revenir au besoin initial, pourquoi ne pas créer cette vue ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    CREATE VIEW v_B (e, b, g, h, d) AS
    SELECT B.e, B.b, B.g, B.h, A.d
      FROM B
           INNER JOIN A
             ON A.b = B.b;

  10. #10
    Expert éminent sénior
    Avatar de fsmrel
    Homme Profil pro
    Spécialiste en bases de données
    Inscrit en
    Septembre 2006
    Messages
    8 114
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Spécialiste en bases de données
    Secteur : Conseil

    Informations forums :
    Inscription : Septembre 2006
    Messages : 8 114
    Points : 31 602
    Points
    31 602
    Billets dans le blog
    16
    Par défaut
    Hello Waldar !

    C’est toujours un plaisir de vous lire.

    Vous écrivez que le concurrent de MS SQL Server interdit la mise à jour :

    Son concurrent de toujours interdit cette mise à jour (la syntaxe des mises à jour de vue diffère légèrement)
    Soit, mais vous cherchez à mettre à jour une vue de jointure alors qu’il s’agit seulement ici de mettre à jour une table de base. Qu’en est-il dans ce cas-là avec le rival ?


    Concernant le message ORA-01779 :

    Citation Envoyé par Le concurrent
    cannot modify a column which maps to a non key-preserved table
    Cause: An attempt was made to insert or update columns of a join view which map to a non-key-preserved table.
    Action: Modify the underlying base tables directly.
    Vous cherchez à mette à jour une expression qui est une jointure de A et B et du point de vue théorique, ça n’est possible que si les tables de base sont au moins dotées de clés candidates, ce qui n’est pas le cas ici, donc la réaction du SGBD est on ne peut plus normale. Je vous renvoie à ce sujet au chapitre 10 « Views » de l’ouvrage de Chris Date An Introduction to Database Systems, Eighth Edition (Addison Wesley).


    Citation Envoyé par Le concurrent
    ORA-30926: unable to get a stable set of rows in the source tables
    Cause: A stable set of rows could not be got because of large dml activity or a non-deterministic where clause.
    Action: Remove any non-deterministic where clauses and reissue the dml.
    Ça ressemble à de l’eau de boudin, c'est manifestement la variante fumeuse du message ORA-01779...


    Conclusion :

    Tant qu’edmotets n’aura pas fourni ses règles de gestion des données permettant de déterminer les clés candidates (que je lui ai déjà réclamées...), on ne pourra pas faire de travail sérieux.


    Citation Envoyé par Waldar Voir le message
    Pour revenir au besoin initial, pourquoi ne pas créer cette vue ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    CREATE VIEW v_B (e, b, g, h, d) AS
    SELECT B.e, B.b, B.g, B.h, A.d
      FROM B
           INNER JOIN A
             ON A.b = B.b;
    Pour la mettre à jour ?

  11. #11
    Modérateur

    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Janvier 2005
    Messages
    5 826
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Administrateur de base de données
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Janvier 2005
    Messages : 5 826
    Points : 12 371
    Points
    12 371
    Par défaut
    Merci à tous de vos commentaires et éclairages

    @++

  12. #12
    Expert éminent sénior
    Avatar de fsmrel
    Homme Profil pro
    Spécialiste en bases de données
    Inscrit en
    Septembre 2006
    Messages
    8 114
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Spécialiste en bases de données
    Secteur : Conseil

    Informations forums :
    Inscription : Septembre 2006
    Messages : 8 114
    Points : 31 602
    Points
    31 602
    Billets dans le blog
    16
    Par défaut
    Bonsoir elsuket,


    Je viens de lire ceci dans la doc MS SQL Server :

    Utilisation de l'instruction UPDATE avec la clause FROM

    Les résultats d'une instruction UPDATE ne sont pas définis si celle-ci comprend une clause FROM qui ne spécifie pas qu'une seule valeur doit être disponible pour chaque occurrence de colonne mise à jour ; à savoir, si l'instruction UPDATE n'est pas déterministe. Par exemple, étant donné l'instruction UPDATE dans le script suivant, les deux lignes dans Table1 correspondent aux qualifications de la clause FROM dans l'instruction UPDATE, mais il n'y a aucune précision quant à savoir quelle ligne de Table1 est utilisée pour mettre à jour la ligne de Table2.

    De fait, votre requête n'a pas l'air d'avoir un comportement bien déterministe... Est-elle conforme à la norme SQL ?

  13. #13
    Modérateur
    Avatar de Waldar
    Homme Profil pro
    Sr. Specialist Solutions Architect @Databricks
    Inscrit en
    Septembre 2008
    Messages
    8 453
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Sr. Specialist Solutions Architect @Databricks
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2008
    Messages : 8 453
    Points : 18 394
    Points
    18 394
    Par défaut
    Citation Envoyé par fsmrel Voir le message
    Pour la mettre à jour ?
    Je pensais plutôt à éviter de dupliquer physiquement les données !

  14. #14
    Expert éminent sénior
    Avatar de fsmrel
    Homme Profil pro
    Spécialiste en bases de données
    Inscrit en
    Septembre 2006
    Messages
    8 114
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Spécialiste en bases de données
    Secteur : Conseil

    Informations forums :
    Inscription : Septembre 2006
    Messages : 8 114
    Points : 31 602
    Points
    31 602
    Billets dans le blog
    16
    Par défaut
    Bonjour,


    Citation Envoyé par Waldar Voir le message
    Je pensais plutôt à éviter de dupliquer physiquement les données !
    ?? Je n’ai pas saisi.


    Je récapépète...

    Le besoin initial est de valoriser la nouvelle colonne d de la table B en y copiant les valeurs de la colonne d de la table A quand on vérifie l’égalité A.b = B.b.

    A mon sens, l’instruction habituelle suivante permet de réaliser l’opération :

    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    UPDATE B
           SET d = (SELECT DISTINCT d 
                   FROM   A
                   WHERE  A.b = B.b) ;
    Instruction qui provoque une erreur si le SELECT emboîté produit plus d’une valeur pour la colonne d. Sur ce point, le comportement de MS SQL Server est conforme, et les autres SGBD ne se comportent pas différemment, puisqu’à l’intersection d’une ligne et d’une colonne on ne peut pas avoir plus d'une valeur (respect de la première forme normale).

    A son tour, elsuket propose l’instruction suivante :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    UPDATE		dbo.B
    SET		d = A.d
    FROM		dbo.B AS B
    INNER JOIN	dbo.A AS A
    			ON A.b = B.b
    Instruction qui fait l’impasse sur le mot-clé « SELECT ». Conscient de l’entorse faite à la syntaxe et de son laxisme quant au résultat, dans sa documentation MS SQL Server met en garde, comme quoi sous cette forme particulière l’instruction UPDATE n’est pas déterministe (horresco referens !) et, au lieu de provoquer une erreur, produit donc soit des résultats justes (une seule valeur de remplacement), soit des résultats faux (plus d’une valeur de remplacement). Au cas où il y a plusieurs valeurs de remplacement et en n’en retenant qu’une seule, MS SQL Server se retranche manifestement derrière la première forme normale, mais comme l’ordre des valeurs qui se présentent n’est pas prévisible, on peut très bien affirmer que le choix résulte entre autres de l’action combinée du battement des ailes des papillons, de la vitesse du vent et de l’âge du capitaine (liste non exhaustive)...

    Je ne sache pas qu’un SGBD comme DB2 permette cette forme de l’instruction UPDATE, qui du reste n’est pas conforme à la norme SQL (sous réserve que SQLpro confirme).

    Ma question est la suivante : l’instruction proposée par elsuket est-elle syntaxiquement acceptée par Oracle ? J’en doute fort, mais si la réponse était positive, Oracle la rejette-t-il à l’exécution lorsque la jointure A.b = B.b produit plus d’une valeur pour la colonne d ?

  15. #15
    Modérateur
    Avatar de Waldar
    Homme Profil pro
    Sr. Specialist Solutions Architect @Databricks
    Inscrit en
    Septembre 2008
    Messages
    8 453
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Sr. Specialist Solutions Architect @Databricks
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2008
    Messages : 8 453
    Points : 18 394
    Points
    18 394
    Par défaut
    Citation Envoyé par fsmrel Voir le message
    ?? Je n’ai pas saisi.

    Le besoin initial est de valoriser la nouvelle colonne d de la table B en y copiant les valeurs de la colonne d de la table A quand on vérifie l’égalité A.b = B.b.
    Je détournais le besoin initial vers la création d'une vue en sélection afin d'éviter de dupliquer des données de A vers B, qui pose la question des mises à jour, des suppressions, de la gestion des cas où les règles sont mal établies... ces problèmes étant levés (ou partiellement levés) par la création de la vue.

    Citation Envoyé par fsmrel Voir le message
    Ma question est la suivante : l’instruction proposée par elsuket est-elle syntaxiquement acceptée par Oracle ? J’en doute fort, mais si la réponse était positive, Oracle la rejette-t-il à l’exécution lorsque la jointure A.b = B.b produit plus d’une valeur pour la colonne d ?
    Cette instruction est en effet complètement rejetée :
    ORA-00933: la commande SQL ne se termine pas correctement
    Les syntaxes que j'ai proposées plus haut étant celles qui s'en rapprochent le plus, même si le périmètre n'est pas tout-à-fait le même.

    J'aurai préféré que SQL-Server produise une erreur sur les jointures avec plusieurs candidats, conduisant à un comportement déterministe, car je trouve la syntaxe plutôt élégante en terme de facilité d'écriture.

  16. #16
    Expert éminent sénior
    Avatar de fsmrel
    Homme Profil pro
    Spécialiste en bases de données
    Inscrit en
    Septembre 2006
    Messages
    8 114
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Spécialiste en bases de données
    Secteur : Conseil

    Informations forums :
    Inscription : Septembre 2006
    Messages : 8 114
    Points : 31 602
    Points
    31 602
    Billets dans le blog
    16
    Par défaut
    Citation Envoyé par Waldar Voir le message
    J'aurai préféré que SQL-Server produise une erreur sur les jointures avec plusieurs candidats, conduisant à un comportement déterministe, car je trouve la syntaxe plutôt élégante en terme de facilité d'écriture.
    Je partage tout à fait votre point de vue (qui est manifestement aussi celui d’elsuket ) quant à l’élégance et à la facilité d’écriture, et il est dommage que cette histoire de comportement non déterministe vienne tout gâcher.


    Citation Envoyé par Waldar Voir le message
    Je détournais le besoin initial vers la création d'une vue en sélection afin d'éviter de dupliquer des données de A vers B, qui pose la question des mises à jour, des suppressions, de la gestion des cas où les règles sont mal établies... ces problèmes étant levés (ou partiellement levés) par la création de la vue.
    C’est une possibilité et edmotets peut effectivement s’en inspirer. Néanmoins il continuera à jouer avec le feu si les clés de ses tables ne sont pas correctement définies (et les tables normalisées en BCNF).


    Bonne journée à vous.

  17. #17
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    21 917
    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 917
    Points : 51 693
    Points
    51 693
    Billets dans le blog
    6
    Par défaut
    Citation Envoyé par fsmrel Voir le message
    De fait, votre requête n'a pas l'air d'avoir un comportement bien déterministe... Est-elle conforme à la norme SQL ?
    Non, la syntaxe de jointure dans l'UPDATE n'existe pas dans la norme SQL, mais plusieurs SGBDR s'y sont collés.... Elle réserve donc quelques surprises !!!!

    A +

  18. #18
    Membre expert

    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Juin 2012
    Messages
    612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Administrateur de base de données
    Secteur : Conseil

    Informations forums :
    Inscription : Juin 2012
    Messages : 612
    Points : 3 066
    Points
    3 066
    Par défaut
    Simplement pour vous remercier pour cet échange très intéressant et très instructif

  19. #19
    Modérateur

    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Janvier 2005
    Messages
    5 826
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Administrateur de base de données
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Janvier 2005
    Messages : 5 826
    Points : 12 371
    Points
    12 371
    Par défaut
    Citation Envoyé par fmsrel
    Je partage tout à fait votre point de vue (qui est manifestement aussi celui d’elsuket ) quant à l’élégance et à la facilité d’écriture, et il est dommage que cette histoire de comportement non déterministe vienne tout gâcher.
    Je ne peux pas être plus d'accord que cela

    Citation Envoyé par SQLPro
    Non, la syntaxe de jointure dans l'UPDATE n'existe pas dans la norme SQL
    Là par contre, j'ai un peu l'impression d'halluciner en lisant cela ... Pourquoi la norme SQL n'expose pas ce cas ?
    En est-il de même pour DELETE ?

    Norme ou pas norme, je crois tout de même que si l'intégrité référentielle avait été respectée, le problème ne se poserait même pas. En marge de cela, je reste toujours coi devant les DSI/CTO qui n'ont que faire des modèles de données pour les bases de données relationnelles SQL que les petites mains manipulent jour après jour. A l'évidence, ils ne se rendent pas compte du coût de maintenance que cela génère. Alors comme d'habitude, on change le matériel, on rajoute des CPUs, des téras de RAM, en négligeant au passage sous-système disque. Et on recommence un an plus tard. Et on se plaint toujours que c'est trop lent. Et on loue NoSQL sans vraiment savoir quel but cela sert, sans se dire que l'on a peut-être fait une mauvaise utilisation du logiciel.
    Le problème si situe souvent entre le clavier et le fauteuil. La voie est pavée d'or pour les consultants

    @++

Discussions similaires

  1. Réponses: 2
    Dernier message: 25/10/2010, 17h22
  2. Réponses: 2
    Dernier message: 16/04/2010, 12h04
  3. Insérer le contenue d'un memo dans une table mysql
    Par kijudr dans le forum Bases de données
    Réponses: 1
    Dernier message: 05/12/2005, 08h39
  4. pourquoi un 's' à la fin des tables ?
    Par Miksimus dans le forum Ruby on Rails
    Réponses: 2
    Dernier message: 07/07/2005, 09h04
  5. comment vider mes tables a la fin
    Par djouahra.karim1 dans le forum Bases de données
    Réponses: 9
    Dernier message: 14/05/2005, 11h33

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