Page 1 sur 2

nom de table dynamique dans requete

Posté : 01 sept. 2009, 16:19
par Invité
Bonjour à tous,
Je suis sur mysql 5.
Je souhaite savoir si dans une requete select (avec jointure), il est possible de composer dynamiquement le nom d'une table à partir d'une valeur de champ fournie dans la même requete.
par exemple, pour récupérer tous les champs d'une table 'users', je fais:

Code : Tout sélectionner

select * from users
dans la table users, j'ai un champ nommé 'profil' qui peut prendre 3 valeurs: toto, tata, titi
toto, tata et titi correspondent aux 3 noms de 3 autres tables se trouvant dans la même bdd.

Comment récupérer les données dans la bonne table (toto, tata ou titi), en fonction de la valeur de 'profil' dans la table 'users'(toto, tata ou titi)?

Schématiquement, ça devrait donner un truc dans le genre:

Code : Tout sélectionner

select users.*, (nomDeTable).* FROM users, (nomDeTable) WHERE (nomDeTable) = users.profil
Cela est il possible?
Merci pour vos réponses.

Re: nom de table dynamique dans requete

Posté : 01 sept. 2009, 17:16
par dunbar
Salut,

Avec un Tabeau peut-être :?:
Exemple :
$Sql_table = "SELECT profil FROM users";
$Resultat_profil = mysql_query($Sql_table) or die('Erreur SQL !'.$Sql_table.'<br>'.mysql_error());

while ($row = mysql_fetch_assoc($Resultat_profil))
		 {
           $Table = array('valeur1' => 'Table1',
                          'valeur2' => 'Table2',
                          'Valeur3' => 'Table3');

           echo $Table[$row['profil']];
         }
L'idée est la suivante, suivant la valeur du champs profil tu y associe le nom d'une table :wink:

Re: nom de table dynamique dans requete

Posté : 01 sept. 2009, 17:18
par Invité
je vais poser ma question plus simplement.

J'ai une table 'news' contenant des news, et l'id du créateur.
Les créateurs sont de 3 types 'admin', 'editor', 'user'
J'ai 3 autres tables 'admin', 'editor', 'user' contenant l'info sur les créateurs (id, nom,...)

Comment faire pour afficher le nom du créateur dans la liste des news?
La difficulté: il existe un enregistrement admin avec id = 1, un enregistrement editor avec, id = 1 et un enregistrement user avec, id = 1

Comment savoir si l'id de créateur de la news est un admin, un editor ou un user?

Je crois que c'est un pb de conception des tables...

Re: nom de table dynamique dans requete

Posté : 01 sept. 2009, 17:31
par dunbar
Dans la table new il y à bien un champ qui te permet de savoir qui la déposer :?:
Parce que sans cela moi je voie pas comment savoir que telle ou telle new appartient a telle ou telle users 8-|

Re: nom de table dynamique dans requete

Posté : 01 sept. 2009, 17:44
par Invité
ben actuellement j'ai l'id du créateur dans la table news...

Re: nom de table dynamique dans requete

Posté : 01 sept. 2009, 18:01
par Invité
Je reformule encore:

est-il possible dans une requete select, de créer dynamiquement le nom d'une table a partir de la VALEUR d'un enregistrement?

Re: nom de table dynamique dans requete

Posté : 01 sept. 2009, 18:03
par dunbar
Et bin l'idée reste la même
$Sql_news = "SELECT news, id FROM news";//--> récupération des news.


            $Resultat_news = mysql_query($Sql_news) or die('Erreur SQL !'.$Sql_news.'<br>'.mysql_error());

			while ($row = mysql_fetch_assoc($Resultat_profil))
			                 {
			           //-->Tu crée un Tableau qui reprend les différente id et leur table associée
			           $Table = array('id_admin' => 'admin',
			                          'id_editor' => 'editor',
			                          'id_user' => 'user');

			           $Table[$row['profil']];

			              $Sql_profil = "SELECT * FROM '".$Table[$row['profil']]."'"; //-->Récup des données du users
                          $Resultat_profil = mysql_query($Sql_profil) or die('Erreur SQL !'.$Sql_profil.'<br>'.mysql_error());
                          
                          $data_users = mysql_fetch_array($Resultat_profil);

			         }
Donc tu récupére les new et l'id, comme l'id correspond au users tu sélectionne une table suivant l'user.
Bon j'ai fait ça en 5 minutes c'est horrible mais cela dois fonctionner il y moyen de faire mieux, mais tu a une piste, (comme refaire tes tables) :wink:

Re: nom de table dynamique dans requete

Posté : 01 sept. 2009, 18:05
par zeus
Bonjour,

Tout d'abord, quand je lis
Les créateurs sont de 3 types 'admin', 'editor', 'user'
J'ai 3 autres tables 'admin', 'editor', 'user' contenant l'info sur les créateurs (id, nom,...)
Je te confirme que oui, c'est
[...]un pb de conception des tables...
parce que, comme tu le dit au début, tu as des créateurs qui ont un type, donc une seule table, pas 3.

Sinon, je ne pense pas que tu puisses faire ça en une seule requête. Tout simplement parce qu'il faut aller chercher des données dans une table pour savoir dans quelle autre table aller voir.
Du coup, tu vas devoir faire une requête pour récupérer le type du créateur, puis une requête pour récupérer les informations du créateur.

Comme quoi, une mauvaise modélisation peut poser pas mal de soucis ;)

Re: nom de table dynamique dans requete

Posté : 01 sept. 2009, 18:06
par Invité
Si dans ma requete select users, le champ 'profil' a pour valeur 'admin', puis-je dans la meme requete aller chercher des éléments dans la table admin?

Sachant que le champ profil peut prendre les valeurs 'admin', 'user' ou 'editor', il faudrait que dans la requete, un nom de table dépende de la valeur d'un champ.
C'est pour ça que je parle de nom de table dynamique
je ne sais pas si c'est plus clair?

Re: nom de table dynamique dans requete

Posté : 01 sept. 2009, 18:15
par dunbar
Comprend tu l'exemple donner plus haut :?:

Re: nom de table dynamique dans requete

Posté : 01 sept. 2009, 18:55
par Invité
Comprend tu l'exemple donner plus haut :?:
merci, je vais étudier ça...mais si j'ai un pb de conception, je préfère arranger ça dès maintenant pour ne pas faire de nuits blanches quand l'appli deviendra complexe.
Est-ce vraiment un pb de conception?

J'aurais bien voulu mettre tous mes users dans une seule table mais ils n'ont pas les mêmes champs.
Pour 'admin', 'user' et 'editor', certains champs sont communs mais d'autres sont différents.

Que suis-je sensé faire dans ce cas là?

Re: nom de table dynamique dans requete

Posté : 01 sept. 2009, 19:03
par dunbar
.
Est-ce vraiment un pb de conception?
Oui

Re: nom de table dynamique dans requete

Posté : 01 sept. 2009, 20:14
par furiouslol
Salut

Montre nous tes tables telles qu'elles sont actuellement

Re: nom de table dynamique dans requete

Posté : 01 sept. 2009, 21:07
par zeus
Si dans ma requete select users, le champ 'profil' a pour valeur 'admin', puis-je dans la meme requete aller chercher des éléments dans la table admin?
non.
Quand tu exécutes une requête SQL, le SGBD (mysql dans ton cas) analyse la syntaxe, la valide en, entre autres, s'assurant que les noms des tables existent, puis l'exécutes et récupère les résultats.
Dans le cas d'une jointure simple, par exemple, ça ne pose pas de soucis puisque le SGBD remonte les données dans la 1ère table, puis dans la seconde, et fait la jointure sur ce résultat (en très simplifié, c'est ça)

Dans ton cas, il faudrait que le SGBD analyse une partie de la requête, l'exécute, modifie son corps et exécute la fin. Et ça, c'est strictement impossible.

Il doit bien exister une solution, en faisant une jointure forcée sur les 3 tables, et en croisant les résultats, mais je t'encourage fortement en reconsidérer ton modèle pour que les 3 tables admin, editor et user soient une unique table "profil" avec un champ "statut" qui contient 'admin', 'editor' ou 'user'.
En gros, pour savoir si tu t'es planté dans ta conception, regarde la structure de tes tables. Si elles sont strictement identiques, c'est que tu t'es trompé.

Re: nom de table dynamique dans requete

Posté : 02 sept. 2009, 08:42
par Invité
Tout d'abord merci à tous pour vos conseils.

Alors voilà: dans mon modèle réel, j'ai types 3 d'utilisateurs, se trouvant dans 3 tables différentes:
CREATE TABLE `jos_abonnes` (
  `id` int(10) NOT NULL auto_increment,
  `userId` int(10) NOT NULL,
  `profil` int(10) NOT NULL,
  `societeId` int(10) NOT NULL,
  `prenom` varchar(255) NOT NULL,
  `adresse` text NOT NULL,
  `cp` int(5) NOT NULL,
  `ville` varchar(255) NOT NULL,
  `tel` varchar(10) NOT NULL,
  `fax` varchar(10) NOT NULL,
  `published` tinyint(1) NOT NULL,
  PRIMARY KEY  (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 AUTO_INCREMENT=2 ;

CREATE TABLE `jos_agences` (
  `id` int(10) NOT NULL auto_increment,
  `userId` int(10) NOT NULL,
  `profil` int(10) NOT NULL,
  `adresse` text NOT NULL,
  `cp` int(5) NOT NULL,
  `ville` varchar(255) NOT NULL,
  `tel` varchar(10) NOT NULL,
  `fax` varchar(10) NOT NULL,
  `published` tinyint(1) NOT NULL,
  PRIMARY KEY  (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;

CREATE TABLE `jos_prestataires` (
  `id` int(10) NOT NULL auto_increment,
  `userId` int(10) NOT NULL,
  `profil` int(10) NOT NULL,
  `agenceId` int(10) NOT NULL,
  `socprestationId` int(10) NOT NULL,
  `expertise` varchar(255) NOT NULL,
  `prenom` varchar(255) NOT NULL,
  `adresse` text NOT NULL,
  `cp` int(5) NOT NULL,
  `ville` varchar(255) NOT NULL,
  `tel` varchar(10) NOT NULL,
  `fax` varchar(10) NOT NULL,
  `published` tinyint(1) NOT NULL,
  PRIMARY KEY  (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;


Chaque table d'utilisateur a un champ 'userId' qui renvoie vers un id dans la table jos_users
CREATE TABLE `jos_users` (
  `id` int(11) NOT NULL auto_increment,
  `name` varchar(255) NOT NULL default '',
  `username` varchar(150) NOT NULL default '',
  `email` varchar(100) NOT NULL default '',
  `password` varchar(100) NOT NULL default '',
  `usertype` varchar(25) NOT NULL default '',
  `block` tinyint(4) NOT NULL default '0',
  `sendEmail` tinyint(4) default '0',
  `gid` tinyint(3) unsigned NOT NULL default '1',
  `registerDate` datetime NOT NULL default '0000-00-00 00:00:00',
  `lastvisitDate` datetime NOT NULL default '0000-00-00 00:00:00',
  `activation` varchar(100) NOT NULL default '',
  `params` text NOT NULL,
  PRIMARY KEY  (`id`),
  KEY `usertype` (`usertype`),
  KEY `idx_name` (`name`),
  KEY `gid_block` (`gid`,`block`),
  KEY `username` (`username`),
  KEY `email` (`email`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=64 ;

Il faut savoir que je ne peux pas modifier cette table users car elle fait partie d'une application plus large qui serait chamboulée. Je ne peux qu'organiser mes autres tables en fonction de cette table jos_users existante.

Ma question: sachant que chaque type d'utilisateur a des champs communs et des champs différents par rapport aux autres profils utilisateurs, quelle serait l'organisation optimale des données pour ne pas souffrir plus tard. Notamment, je galère déjà car quand je veux récupérer des données sur un utilisateur, impossible de dire dans la requete sql dans quelle table il faut aller.

Merci à tous pour votre aide.