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

Requêtes MySQL Discussion :

Contrainte unique en plus d'un index


Sujet :

Requêtes MySQL

  1. #1
    Rédacteur
    Avatar de Bakura
    Homme Profil pro
    Étudiant
    Inscrit en
    Septembre 2005
    Messages
    1 386
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Septembre 2005
    Messages : 1 386
    Points : 2 640
    Points
    2 640
    Par défaut Contrainte unique en plus d'un index
    Bonjour à tous ,

    J'essaye d'apporter le plus grand soin possible à l'architecture de ma base de données (je sais que je ne le regretterai pas quand je ferai évoluer mon architecture, et que c'est la clé pour quelque chose de robuste). Toutefois je me pose une petite question.

    J'utilise l'ORM Doctrine 2, pour lequel je spécifie mes relations via des annotations, et qui me génère le code SQL correspond. Dans une de mes tables, je dispose de deux relations ManyToOne, et Doctrine me génère deux index ces deux clés étrangères. Or, ce couple (fk_1, fk_2) est garantit comme unique dans mon schéma, et j'ai donc ajouté une annotation au niveau de l'ORM pour qu'il génère une contrainte unique au niveau de ces deux clés étrangères.

    Je dispose donc de quatre clés :

    - la clé primaire.
    - une contrainte unique composée de fk_1 et fk_2
    - un index sur fk_1
    - un index sur fk_2

    Ma question est justement de savoir si ajouter la contrainte unique est utile sachant que je dispose déjà de ces index sur les deux clés étrangères (sachant qu'il est impossible de supprimer ces index au niveau de l'ORM, pour ne garder que la contrainte d'unicité).

    Merci

  2. #2
    Expert confirmé
    Profil pro
    Inscrit en
    Août 2008
    Messages
    2 947
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2008
    Messages : 2 947
    Points : 5 846
    Points
    5 846
    Par défaut
    Une contrainte d'unicité c'est différent d'un index, si le couple (fk1, fk2) doit être unique il faut le valider via une contrainte.
    Techniquement les SGBDs s'appuient sur des indexs (déjà existant ou créés automatiquement lors de la création de la contrainte) pour gérer les contraintes.

    Dans l'état actuel l'index sur fk1 (la 1ere colonne de la contrainte d'unicité) n'est pas obligatoire, le SGBD devant être capable d'utiliser l'index généré pour assurer la contrainte. Il est également préférable de ne pas avoir une PK autoincrémenté qui ne sert à rien (si effectivement elle ne sert à rien), et de créer la PK sur le couple (fk1, fk2).

    Après si doctrine impose une PK autoincrémenté et la création des index la situation actuelle est bonne.
    Dans tous les cas la contrainte d'unicité DOIT être implémentée au niveau SGBD.

  3. #3
    Rédacteur
    Avatar de Bakura
    Homme Profil pro
    Étudiant
    Inscrit en
    Septembre 2005
    Messages
    1 386
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Septembre 2005
    Messages : 1 386
    Points : 2 640
    Points
    2 640
    Par défaut
    Merci de ta réponse, je vais donc créer cette contrainte d'unicité.

    Après si doctrine impose une PK autoincrémenté et la création des index la situation actuelle est bonne.
    C'est ça. Doctrine recommande d'éviter les clés primaires composées.

  4. #4
    Modérateur

    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 799
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur d'études en informatique
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2006
    Messages : 16 799
    Points : 34 031
    Points
    34 031
    Billets dans le blog
    14
    Par défaut
    Ça commence bien...
    Citation Envoyé par Bakura Voir le message
    J'essaye d'apporter le plus grand soin possible à l'architecture de ma base de données (je sais que je ne le regretterai pas quand je ferai évoluer mon architecture, et que c'est la clé pour quelque chose de robuste).
    Mais ça continue mal !

    J'utilise l'ORM Doctrine 2, pour lequel je spécifie mes relations via des annotations, et qui me génère le code SQL correspond.
    Ce n'est pas au programme de décider comment doit être le modèle de données.
    On modélise d'abord les données puis on crée des vues nécessaires au programme et ce sont ces vues qui sont requêtées par le programme, éventuellement..., si tu y tiens vraiment... mais faut pas te sentir obligé d'utiliser ce genre de machin... ou alors si on te l'impose... à l'aide d'une saloperie d'ORM.

    Dans une de mes tables, je dispose de deux relations ManyToOne, et Doctrine me génère deux index ces deux clés étrangères. Or, ce couple (fk_1, fk_2) est garantit comme unique dans mon schéma, et j'ai donc ajouté une annotation au niveau de l'ORM pour qu'il génère une contrainte unique au niveau de ces deux clés étrangères.
    Et voilà ! Ce n'est pas au programme de spécifier une contrainte unique à la BDD. C'est la BDD qui doit imposer son modèle au programme ! L'unicité d'une colonne ou d'un ensemble de colonnes tient du modèle de données, lequel est issu de règles de gestion qui spécifient cette contrainte d'unicité, ou bien cette contrainte est déterminée par le processus de modélisation des données, comme dans le cas qui semble te concerner des tables associatives.

    Je dispose donc de quatre clés :

    - la clé primaire.
    - une contrainte unique composée de fk_1 et fk_2
    - un index sur fk_1
    - un index sur fk_2
    S'il s'agit bien d'une table associative, la clé primaire doit être composée des colonnes portant les deux clés étrangères. Si c'est le couple {fk_1, fk_2} qui est clé primaire, alors ce couple est indexé et, par voie de conséquence, la colonne portant fk_1 est aussi indexée individuellement mais pas la colonne portant fk_2 et il faut donc l'indexer individuellement. Si l'ordre des colonnes est inversé dans la déclaration de la clé primaire, c'est le contraire.

    (sachant qu'il est impossible de supprimer ces index au niveau de l'ORM, pour ne garder que la contrainte d'unicité).
    Jette l'ORM !

    C'est ça. Doctrine recommande d'éviter les clés primaires composées.
    Jette l'ORM !
    Philippe Leménager. Ingénieur d'étude à l'École Nationale Supérieure de Formation de l'Enseignement Agricole. Autoentrepreneur.
    Mon ancien blog sur la conception des BDD, le langage SQL, le PHP... et mon nouveau blog sur les mêmes sujets.
    « Ce que l'on conçoit bien s'énonce clairement, et les mots pour le dire arrivent aisément ». (Nicolas Boileau)
    À la maison comme au bureau, j'utilise la suite Linux Mageïa !

  5. #5
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    21 772
    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 772
    Points : 52 732
    Points
    52 732
    Billets dans le blog
    5
    Par défaut
    Ma rigolade de la journée : MySQL qui est le moins performant des SGBDR plus un ORM qui enflera encore les temps de réponse entre 5 et 25 fois au bas mot !!!
    A lire sur cet ersatz de SGBDR q'est MySQL : http://blog.developpez.com/sqlpro/p9...udre-aux-yeux/
    A lire sur les performances comparatives de MySQl, PostGreSQL et MS SQL Server : http://blog.developpez.com/sqlpro/p9...lles-en-sql-1/
    A lire sur les méfaits des ORM : http://sqlpro.developpez.com/cours/b...s-epaisses.pdf
    A lire sur les performances de Doctrine, qui semble bien être le plus pourrit des ORM : http://ljouanneau.com/blog/post/2007...es-des-orm-php
    http://www.incapable.fr/conseil-mysql-19
    http://sourceforge.net/apps/trac/php...ne%20benchmark

    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/ * * * * *

  6. #6
    Rédacteur
    Avatar de Bakura
    Homme Profil pro
    Étudiant
    Inscrit en
    Septembre 2005
    Messages
    1 386
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Septembre 2005
    Messages : 1 386
    Points : 2 640
    Points
    2 640
    Par défaut
    Ma rigolade de la journée : MySQL qui est le moins performant des SGBDR plus un ORM qui enflera encore les temps de réponse entre 5 et 25 fois au bas mot !!!
    On se calme SQLPro ;-).

    A lire sur les performances de Doctrine, qui semble bien être le plus pourrit des ORM :
    Doctrine a connu une version majeure depuis la date de l'article que tu mets en lien (la version 2), qui améliore pas mal les choses.

    S'il s'agit bien d'une table associative, la clé primaire doit être composée des colonnes portant les deux clés étrangères. Si c'est le couple {fk_1, fk_2} qui est clé primaire, alors ce couple est indexé et, par voie de conséquence, la colonne portant fk_1 est aussi indexée individuellement mais pas la colonne portant fk_2 et il faut donc l'indexer individuellement. Si l'ordre des colonnes est inversé dans la déclaration de la clé primaire, c'est le contraire.
    Merci de la précision, je ne savais pas pour le fait que la deuxième clé étrangère n'est pas indexée par défaut... Mais apparemment Doctrine indexe les deux de lui même.


    SQLPro, je ne cherche pas à lancer un débat sur l'utilité des ORM puisque visiblement beaucoup ne les portent pas dans leur coeur ici (^_^). Comme je l'ai dit sur un autre fil de discussion, Doctrine me rend bien des services lors d'une conception orientée objet et me facilite bien la vie. En étant seul et unique développeur, c'est le genre de choses qui me permettent de gagner un temps précieux et qui me laissent du temps pour bosser sur d'autres aspects du projet (communication, juridique...).

    EDIT : Je lis ton papier (très intéressant au demeurant), je sens que je vais me faire allumer après avoir lu le : "et pour les développeurs de rester dans le concept objet sans jamais aller voir du côté de la base de données, les enfonçant ainsi encore un peu plus dans leur ignorance."

    Si un jour je m'aperçois dès que le site commencera à marcher que l'ORM est effectivement le goulot d'étranglement, je n'hésiterai pas à revoir ma position et à le lâcher. Je pense qu'un ORM relativement bien utilisé (l'ORM ne créé pas le schéma magique tout seul, ça reste de ma responsabilité) ne me pénalisera pas TANT QUE CA. Reste à voir en pratique.

    Pour MySQL, je note et je vais réfléchir à passer sur PostgreSQL.

  7. #7
    Modérateur

    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 799
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur d'études en informatique
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2006
    Messages : 16 799
    Points : 34 031
    Points
    34 031
    Billets dans le blog
    14
    Par défaut
    Merci de la précision, je ne savais pas pour le fait que la deuxième clé étrangère n'est pas indexée par défaut... Mais apparemment Doctrine indexe les deux de lui même.
    Ce n'est pas exactement ce que j'ai voulu dire.
    Il semble désormais commun que le SGBD, notamment MySQL, indexe automatiquement les colonnes lors de la déclaration de la clé étrangère. En tout cas, quand on réalise un schéma E/R sur MySQL Workbench et qu'on génère le code SQL ou directement la BDD en se connectant Workbench au serveur MySQL, Workbench prévoit automatiquement l'indexations des colonnes figurant dans les contraintes de clé étrangère.

    Ce que je voulais dire, c'est qu'avec un index multi-colonnes, seule la première est indexée individuellement. Démonstration...

    Soit un index placé sur le couple de colonnes {A / B}, il sera trié ainsi :
    A / B
    1 / 1
    1 / 2
    1 / 5
    1 / 10
    2 / 1
    2 / 3
    2 / 6
    2 / 8
    3 / 4
    3 / 5

    => On voit très bien que la colonne B n'est pas triée, il n'y a pas d'index individuel sur la colonne B alors qu'elle fait partie de l'index sur {A / B}.

    Si on doit interroger souvent B et si B comporte un grand nombre de valeurs, alors il faut indexer B en plus du couple {A / B}. Par contre, inutile d'indexer individuellement A qui est déjà indexé par l'index sur le couple {A / B}.

    Par ailleurs, je maintiens que les ORM sont une perte de temps !
    Il est largement plus rapide d'écrire une requête en SQL pur qu'avec le pseudo-SQL ddes ORM. J'ai souffert avec Hibernate, ça m'a ôté toute envie d'en essayer un autre !

    Voir cette discussion et celle-ci
    Philippe Leménager. Ingénieur d'étude à l'École Nationale Supérieure de Formation de l'Enseignement Agricole. Autoentrepreneur.
    Mon ancien blog sur la conception des BDD, le langage SQL, le PHP... et mon nouveau blog sur les mêmes sujets.
    « Ce que l'on conçoit bien s'énonce clairement, et les mots pour le dire arrivent aisément ». (Nicolas Boileau)
    À la maison comme au bureau, j'utilise la suite Linux Mageïa !

  8. #8
    Rédacteur
    Avatar de Bakura
    Homme Profil pro
    Étudiant
    Inscrit en
    Septembre 2005
    Messages
    1 386
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Septembre 2005
    Messages : 1 386
    Points : 2 640
    Points
    2 640
    Par défaut
    J'ai bien compris la subtilité des index composées. Merci de cette précision :jap:.

    Par ailleurs, je maintiens que les ORM sont une perte de temps !
    Il est largement plus rapide d'écrire une requête en SQL pur qu'avec le pseudo-SQL ddes ORM. J'ai souffert avec Hibernate, ça m'a ôté toute envie d'en essayer un autre !
    Je veux bien te croire, je ne dis pas le contraire et c'est en lisant les tutoriaux de SQLPro (et les tiens, ta page sur quand utiliser une table associative est dans mes favoris et je m'y réfère chaque fois pour voir si l'ORM m'a pas généré un truc foireux ) que je me rends compte qu'effectivement, l'ORM reste vachement haut niveau et "empêche" l'utilisation des spécificités de chaque SGBDR (même si on peut écrire du code SQL natif sous Doctrine, en fait). N'empêche que mon application n'a pas des besoins énormes en terme de base de données (je n'ai aucune requête faisant intervenir 6 ou 7 tables par exemple), et encore une fois, la propreté qu'offre l'ORM dans un contexte 100% objet est quand même appréciable. Par contre, je me rends finalement compte que la fonctionnalité de lazy-loading m'est finalement assez peu utile puisque je fais les jointures dès que je réalise la requête, du coup c'est un des avantages de l'ORM que j'avais noté qui n'en est finalement pas vraiment un.

    Maintenant, comme je l'ai dit plus haut, si j'ai une application plus exigeante du côté base de données, je penserai à vous.

    Sinon par pure curiosité, tu gères ça comment dans une conception orientée objet avec du simple SQL ?

    PS : pour utiliser NHibernate en stage (Hibernate adapté au C#) et pour avoir pas mal utilisé Entity Framework dans le cadre d'une application Windows Phone, Doctrine 2 est DE LOIN l'ORM le plus agréable avec lequel j'ai travaillé ;-).

  9. #9
    Modérateur

    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 799
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur d'études en informatique
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2006
    Messages : 16 799
    Points : 34 031
    Points
    34 031
    Billets dans le blog
    14
    Par défaut
    Sinon par pure curiosité, tu gères ça comment dans une conception orientée objet avec du simple SQL ?
    Je n'en ai pas souvent eu l'occasion, seulement avec Zend Framework 1.11.

    Grosso modo, quand mon code fait appel à une partie du modèle de données, je crée une Zend_Db_Table_Abstract et j'y colle le juste nécessaire à mon application :
    Des requêtes en SQL pur dans des fonctions qui me ramènent exactement ce que je veux. J'utilise ensuite ces fonctions dans mes contrôleurs et formulaires.

    Voilà un exemple un peu gros et peut-être pas très orthodoxe vis à vis du paradigme objet mais les grosses requêtes qu'il contient, j'ai dû mettre moins de 5 minutes à les écrire alors qu'avec le pseudo SQL de Zend_Db ça aurait été très galère !
    Code PHP : 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
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    <?php
     
    class Application_Model_DbTable_Etudiant extends Zend_Db_Table_Abstract
    {
     
        protected $_name = 'th_etudiant_etu';
        protected $_primary = 'etu_id_candidat';
     
        /**
         * Récupère toutes les infos relatives à un étudiant
         * @param Integer $iduser : Identifiant de l'étudiant
         */
        public function infosEtudiant($iduser)
        {
        	$sql = "
        		SELECT p.prs_nom, p.prs_prenom, p.prs_adrel, p.prs_telephone, 
    				e.etu_date_naissance, e.etu_adresse, e.etu_code_postal, 
    				c.cmn_id AS id_commune_residence, 
    				c.cmn_nom AS commune_residence, 
    				etb.etb_id, etb.etb_nom, etb.etb_adresse, etb.etb_code_postal, etb.etb_telephone, 
    				c1.cmn_id AS id_commune_etablissement, 
    				c1.cmn_nom AS nom_commune_etablissement, 
    				c1.cmn_nom AS commune_etablissement, 
    				te.te_id, te.te_libelle, 
    				ccr.ccr_libelle,
    				dsc.dsc_nom
    			FROM th_etudiant_etu AS e 
    			INNER JOIN te_personne_prs AS p ON p.prs_id = e.etu_id_candidat 
    			INNER JOIN te_concours_ccr AS ccr ON ccr.ccr_id = e.etu_id_concours 
    				INNER JOIN te_discipline_dsc AS dsc ON dsc.dsc_id = ccr.ccr_id_discipline 
    			LEFT OUTER JOIN tr_commune_cmn AS c ON c.cmn_id = e.etu_id_commune_residence 
    			LEFT OUTER JOIN te_etablissement_etb As etb ON etb.etb_id = e.etu_id_etablissement_origine 
    				LEFT OUTER JOIN tr_commune_cmn AS c1 ON c1.cmn_id = etb.etb_id_commune 
    				LEFT OUTER JOIN tr_type_etablissement_te AS te ON te.te_id = etb.etb_id_type_etablissement
    			WHERE e.etu_id_candidat = ? 
    		";
        	return $this->_db->fetchRow($sql, (int) $iduser);
        } // Fin public function infosEtudiant($login)
     
        /**
         * Donne le stage auquel est éventuellement inscrit l'étudiant
         * @param String $iduser : Identifiant de l'étudiant connecté
         * @return Zend_Db_Table_Row_Abstract : Le stage ou NULL
         */
        public function inscritStage($iduser)
        {
        	$sql = "
        		SELECT p.prs_nom, p.prs_prenom,
        			ssn.ssn_id, ssn_code, ssn.ssn_libelle, 
        			DATE_FORMAT(ssn.ssn_date_debut, '%d/%m/%Y') AS ssn_date_debut, 
        			DATE_FORMAT(ssn.ssn_date_fin, '%d/%m/%Y') AS ssn_date_fin,
      				e.etb_nom, c.cmn_nom, d.dpt_numero
    			FROM te_personne_prs AS p 
    			LEFT OUTER JOIN tj_cnd_inscrire_ssn_cis AS cis ON cis_id_candidat = p.prs_id
      				LEFT OUTER JOIN te_session_ssn AS ssn ON ssn.ssn_id = cis.cis_id_session
        				LEFT JOIN th_stage_stg AS stg ON stg.stg_id_session = ssn.ssn_id
          					LEFT JOIN te_etablissement_etb AS e ON e.etb_id = stg.stg_id_etablissement
    							LEFT JOIN tr_commune_cmn AS c ON c.cmn_id = e.etb_id_commune
    	  							LEFT JOIN tr_departement_dpt AS d ON d.dpt_id = c.cmn_id_departement
    			WHERE p.prs_id = ?
    		";
     
        	return $this->_db->fetchRow($sql, (int) $iduser);
        } // Fin public function inscritStage($login)
     
        /**
         * Vérifie si un étudiant existe dans la BDD
         * @param String $nom
         * @param String $prenom
         * @param Date $datenaissance
         */
        public function identifierEtudiant($nom, $prenom, $datenaissance)
        {
        	$sql = "
        		SELECT u.uti_login 
        		FROM th_etudiant_etu AS e 
        		INNER JOIN th_utilisateur_uti AS u ON u.uti_id_personne = e.etu_id_candidat 
        			INNER JOIN te_personne_prs AS p ON p.prs_id = u.uti_id_personne 
        		WHERE p.prs_nom = :nom 
        			AND p.prs_prenom = :prenom 
        			AND e.etu_date_naissance = :datenaissance 
        	";
        	return $this->_db->fetchRow($sql, 
        		array(	'nom'=>$nom, 
        				'prenom'=>$prenom, 
        				'datenaissance'=>$datenaissance
        			)
        	);
        } // Fin public function identifierEtudiant($nom, $prenom, $datenaissance)
     
        /**
         * Inscrit un étudiant à un stage
         * @param Integer $iduser : Identifiant de l'étudiant
         * @param integer $idsession : Identifiant de la session de stage
         */
        public function inscrire($iduser, $idsession)
        {
        	$sql = "
        		INSERT INTO tj_cnd_inscrire_ssn_cis (cis_id_candidat, cis_id_session) 
        		VALUES 
        		(
        			:iduser, 
        			:session 
        		)
        	";
     
        	$stmt = $this->_db->query($sql, array(	'iduser' => (int) $iduser,
        											'session' => (int) $idsession
        										)
        							);
        }
     
        /**
         * Supprime l'inscription d'un étudiant à un stage
         * @param $iduser : Identifiant de l'étudiant
         */
        public function desinscrire($iduser)
        {
        	$sql = "
        		DELETE c
        		FROM tj_cnd_inscrire_ssn_cis AS c
        		WHERE cis_id_candidat = :iduser 
        	";
        	$stmt = $this->_db->query($sql, array('iduser' => (int) $iduser));
     
        }
     
        public function listeEtudiants()
        {
        	$sql = "
        		SELECT p.prs_id, p.prs_nom, p.prs_prenom, p.prs_adrel, p.prs_telephone, 
        			e.etu_adresse, e.etu_code_postal, 
        			c.cmn_nom, 
        			cr.ccr_libelle 
        		FROM te_personne_prs p 
        		INNER JOIN th_etudiant_etu e ON e.etu_id_candidat = p.prs_id 
        			LEFT OUTER JOIN tr_commune_cmn c ON c.cmn_id = e.etu_id_commune_residence 
        			INNER JOIN te_concours_ccr cr ON cr.ccr_id = e.etu_id_concours 
        	";
        	return $this->_db->fetchAll($sql);
        }
     
        public function ajouterEtudiant($data)
        {
        	// Ajout dans la table des personnes
        	$data_personne = array();
        	$data_personne['prs_nom'] = $data['prs_nom'];
        	$data_personne['prs_prenom'] = $data['prs_prenom'];
     
        	if(isset($data_personne['prs_adrel']))
        	{
        		$data_personne['prs_adrel'] = $data['prs_adrel'];
        	}
     
        	if(isset($data_personne['prs_telephone']))
        	{
        		$data_personne['prs_telephone'] = $data['prs_telephone'];
        	}
     
        	$personne = new Application_Model_DbTable_Personne();
        	$id_personne = $personne->ajouterPersonne($data_personne);
     
        	// Ajout dans la table des utilisateurs 
    		$date = Date('dmY');
     
    		$data_utilisateur = array();
    		$data_utilisateur['uti_id_personne'] = (int)$id_personne;
    		$data_utilisateur['uti_id_type_utilisateur'] = 3;
    		$data_utilisateur['uti_login'] = substr($data['prs_prenom'], 0, 1).$data['prs_nom'];
    		$data_utilisateur['uti_mot_passe'] = substr($data['prs_prenom'], 0, 1).substr($date, 0, 4).substr($date, 6, 2).substr($data['prs_nom'],0,1);
     
    		$utilisateur = new Application_Model_DbTable_Utilisateur;
    		$utilisateur->ajouterUtilisateur($data_utilisateur);
     
    		// Ajout dans la table des candidats
    		$sql = "
    			INSERT INTO th_candidat_cnd(cnd_id_utilisateur) 
    			VALUES(:id)
    		";
    		$this->_db->query($sql, array('id' => (int) $id_personne));
     
    		// Ajout dans la table des étudiants
    		$data_etudiant = array();
    		$data_etudiant['etu_id_candidat'] = (int)$id_personne;
    		$data_etudiant['etu_id_concours'] = (int)$data['etu_id_concours'];
    		$data_etudiant['etu_date_naissance'] = $data['etu_date_naissance'];
     
    		if(isset($data_etudiant['etu_id_etablissement_origine']))
    		{
    			$data_etudiant['etu_id_etablissement_origine'] = (int)$data['etu_id_etablissement_origine'];
    		}
     
    		if(isset($data_etudiant['etu_id_commune_residence']))
    		{
    			$data_etudiant['etu_id_commune_residence'] = (int)$data['etu_id_commune_residence'];
    		}
     
    		if(isset($data_etudiant['etu_adresse']))
    		{
    			$data_etudiant['etu_adresse'] = $data['etu_adresse'];
    		}
     
    		if(isset($data_etudiant['etu_code_postal']))
    		{
    			$data_etudiant['etu_code_postal'] = $data['etu_code_postal'];
    		}
     
    		$this->insert($data_etudiant);
        }
     
    	public function obtenirEtudiant($id)
    	{
    		$sql = "
    			SELECT p.prs_nom, p.prs_prenom, p.prs_adrel, p.prs_telephone, 
    				e.etu_id_candidat, e.etu_id_concours, e.etu_id_etablissement_origine, 
    				e.etu_id_commune_residence, e.etu_adresse, e.etu_code_postal, e.etu_date_naissance, 
    				ccr.ccr_id, c.cmn_nom, etb.etb_nom 
    			FROM th_etudiant_etu e 
    			INNER JOIN te_personne_prs p ON p.prs_id = e.etu_id_candidat 
    			LEFT OUTER JOIN te_concours_ccr ccr ON ccr.ccr_id = e.etu_id_concours 
    			LEFT OUTER JOIN tr_commune_cmn c ON c.cmn_id = e.etu_id_commune_residence 
    			LEFT OUTER JOIN te_etablissement_etb etb ON etb.etb_id = e.etu_id_etablissement_origine 
    			WHERE e.etu_id_candidat = :id 
    		";
    		$row = $this->_db->fetchRow($sql, array('id' => (int)$id)); 
            if (!$row) 
            {
                throw new Exception("Impossible de trouver l'étudiant $id !");
            }
            return $row;
    	}
    }
    Philippe Leménager. Ingénieur d'étude à l'École Nationale Supérieure de Formation de l'Enseignement Agricole. Autoentrepreneur.
    Mon ancien blog sur la conception des BDD, le langage SQL, le PHP... et mon nouveau blog sur les mêmes sujets.
    « Ce que l'on conçoit bien s'énonce clairement, et les mots pour le dire arrivent aisément ». (Nicolas Boileau)
    À la maison comme au bureau, j'utilise la suite Linux Mageïa !

  10. #10
    Rédacteur
    Avatar de Bakura
    Homme Profil pro
    Étudiant
    Inscrit en
    Septembre 2005
    Messages
    1 386
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Septembre 2005
    Messages : 1 386
    Points : 2 640
    Points
    2 640
    Par défaut
    C'est grosso modo ce que je faisais quand j'ai commencé Zend. Mais finalement on nous rabâche tellement les oreilles qu'il faut éviter le couplage entre le modèle en base de données et le modèle objet (parce que finalement ton objet Row est à la fois un modèle et à la fois très lié à la persistance), que finalement on te dit qu'il faut créer des mappers... et au final un mapper correct c'est long et chiant à écrire... et au final du final on en vient à utiliser un ORM .

    C'est vrai que j'ai peut-être été trop influencé par ces "sois-disantes" bonnes pratiques qui t'imposent finalement à toujours utiliser plus de frameworks. On verra de toute façon, je le verrai bien vite si Doctrine s'avère être le goulot de mon application .

Discussions similaires

  1. [Conception] Index et contrainte unique
    Par JmL40 dans le forum Développement
    Réponses: 4
    Dernier message: 18/04/2011, 11h39
  2. Index implicite sur contrainte UNIQUE ?
    Par CinePhil dans le forum Débuter
    Réponses: 1
    Dernier message: 17/10/2009, 16h22
  3. [Hibernate] Surrogate key et contraintes unique
    Par mauvais_karma dans le forum Hibernate
    Réponses: 2
    Dernier message: 22/11/2005, 16h41
  4. Suppression de la contrainte unique
    Par mika dans le forum SQL
    Réponses: 3
    Dernier message: 20/02/2003, 17h56

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