Exportation importation de bdd respectant les relations entre tables

Soyez le premier à donner votre avis sur cette source.

Snippet vu 8 127 fois - Téléchargée 20 fois

Contenu du snippet

Avez vous jamais eu ce problème? il faut exporter des données de plusieurs tables mais tout en respectant l'id auto incrément de chaque table qui est repris dans une autre table... Evidemment il serait si simple de copier/coller les fichiers table, mais impossible si l'on souhaite ajouter des données à la suite en conservant les données déjà existantes!

voici le cas concret:
1 table mat_questionnaire (clé primaire: que_id)
==> liée à la table mat_rubrique (clé primaire: rub_id) par la jointure mat_questionnaire.que_id = mat_rubrique.que_id
==> liée à la table mat_question (clé primaire: qes_id) par la jointure mat_rubrique.rub_id = mat_question.rub_id
==> liée à la table mat_reponse (clé primaire: rep_id) par la jointure mat_question.qes_id = mat_reponse.qes_id

processus réccursif: exporter 1 ligne de mat_questionnaire; récupérer le LAST_INSERT_ID, insérer les lignes correspondantes dans mat_rubrique pour cet ID, puis les questions pour chaque ID de mat_rubrique, puis les réponses de chaque question... la définition de l'array permet de s'adapter à quasiment tout type de structure, la récursivité de la fonction fait le reste.
Comme il n'est pas forcément possible d'insérer directement dans 1 autre table (qui peut être une autre BDD...) j'ai choisis d'afficher les requetes qu'il faut ensuite copier/coller par exemple dans phpmyadmin. (on aurait pu aussi les exporter dans un ficher). Le script utilise la capacité de mySQL de déclarer des variables.

Source / Exemple :


<?php

// Information de connexion à la base de données locale
$database_local_addr = "localhost";
$database_local_name = "";
$database_local_user = "root";
$database_local_password = "";

if (!($link = @mysql_connect($database_local_addr,$database_local_user,$database_local_password)) 
	OR (!@mysql_select_db($database_local_name)))
  die("La base de données est indisponible.");

// exporter les données suivant leurs relations
$config = array('tbl' => 'mat_questionnaire', 'pk' => 'que_id', 
	'que_id' => array( 'tbl' => 'mat_rubrique', 'pk' => 'rub_id', 'fk' => 'que_id', 
		'rub_id' => array( 'tbl' => 'mat_question', 'pk' => 'qes_id', 'fk' => 'rub_id', 
			'qes_id' => array( 'tbl' => 'mat_reponse', 'pk' => 'rep_id', 'fk' => 'qes_id')
) ) );

echo '<pre>';
recurseexport( $config, 'que_id=2');
echo '</pre>';

// fonction récursive selon la définition de l'arg $array
// possibilité de filtrer sur la 1ere table définie par l'$array
function recurseexport($array, $filter='', $keyvalue= false ) {
	// récupérer le last_id si besoin
	if ($keyvalue) {
		$keyname = '@id_'.$array['tbl'];
		echo "SET $keyname := LAST_INSERT_ID();\n";
	}
	$sql = 'SELECT * FROM '.$array['tbl'];
	if ($filter) $sql.=' WHERE '.$filter;
	$result = mysql_query($sql) or die ('ERREUR '.$sql.' '.mysql_error());  
	while ($row = mysql_fetch_assoc($result)) {
		// exporter la ligne:
		if ($keyvalue)
			echo 'INSERT INTO '.$array['tbl'].' '.export ($row, $array['pk'], $array['fk'], $keyname)."\n";
		else
			echo 'INSERT INTO '.$array['tbl'].' '.export ($row, $array['pk'])."\n";
		
		// si la clé a une relation, exporter les dépendances:
		if (isset($array[$array['pk']])) {
			// 
			$tbl = $array[$array['pk']];
			$fk = $tbl['fk'];
			recurseexport( $tbl, $fk.'='.$row[$array['pk']], true);
		}
	}
}

// génere un INSERT (champs...) VALUES (valeurs...)
function export(&$row, $pkfield, $fkfield='', $fkname='') {
	$listvalues = '';
	$listfields = '';
	foreach ($row as $field => $value) {
		if ($field <> $pkfield) {
			$listfields .= ', '.$field;
			if ($field == $fkfield)
				$listvalues.=", $fkname";
			elseif (is_null($value))
				$listvalues.=', NULL';
			else
				$listvalues.=", '".mysql_escape_string($value)."'";
		}
	}
	return '('.substr($listfields, 1).') VALUES ('.substr($listvalues, 1).');';
}

Conclusion :


les champs 'pk' (clé primaire) sont supposé être en auto-incrément, leur valeur n'est donc pas exportée puisqu'elle sera récupéree dans une variable mySQL.. Les champs 'fk' sont la relation (clé étrangère) avec le champs 'pk' de la table liée. Pas testé dans le cas de relation d'1 table avec plusieurs ou bien de relations sur plusieurs champs...

A voir également

Ajouter un commentaire

Commentaires

mitch73
Messages postés
3
Date d'inscription
lundi 24 septembre 2007
Statut
Membre
Dernière intervention
29 avril 2009
-
Merci pour ton aide :D

je vais tester ça

je t'ai déjà mis une bonne note pour ton code ;)
c'est la moindre des choses
pifou25
Messages postés
150
Date d'inscription
lundi 13 octobre 2003
Statut
Membre
Dernière intervention
21 décembre 2014
-
normal, dans ta boucle la variable $_xml est écrasée à chaque nouvelle valeur de la base ( = enregistrement = ligne de ta table). utilise .= au lieu de = :
$_xml .= "blabla";

sinon, ici c'est les commentaires pour mon code :p les demandes d'aide pour un pb qu'a rien à voir, c'est sur les forums du site :D pour la peine tu peux au moins me mettre une bonne note ;)
mitch73
Messages postés
3
Date d'inscription
lundi 24 septembre 2007
Statut
Membre
Dernière intervention
29 avril 2009
-
Merci de ta réponse Pifou

J'ai effectivement trouvé un code qui répond presque (haaaarg) à mon problème
le voici
<?php

$db_name = "toto";
$link = mysql_connect("localhost", "root", "") or die("Connexion impossible.");
$table_name = 'users';
$db = mysql_select_db($db_name, $link);
$query = "select * from " . $table_name;
$result = mysql_query($query) or die("Impossible d'interroger la base de données");
$num = mysql_num_rows($result);

if ($num != 0) { $file= fopen("account.php", "w");
while ($row = mysql_fetch_array($result))
$_xml ="<?\$password = array ("" . $row['name'] . "" => "" . $row['pass'] . "");?>\r\n";
//while ($row = mysql_fetch_array($result))
fwrite($file, $_xml);
fclose($file); echo "Le fichier est créé Show source :)."; }
else { echo "erreur"; }
?>

en fait avec while soit ça incrémente des valeur vide
soit j'ai la bonne valeur mais la dernière de la base (non incrémenté)

qu'est ce qui manque ??? je bloque :(
pifou25
Messages postés
150
Date d'inscription
lundi 13 octobre 2003
Statut
Membre
Dernière intervention
21 décembre 2014
-
Mitch > en effet ton problème n'a aucun rapport avec ce code. pour toi il suffit de faire un SELECT sur ta table, puis une boucle sur le résultat et écrire tes fichiers je suppose.
mitch73
Messages postés
3
Date d'inscription
lundi 24 septembre 2007
Statut
Membre
Dernière intervention
29 avril 2009
-
Bonjour

Je trouve bien ton code mais cela n'a pas résolu mon problème
voila
j'ai une base Mysql de ce type :
base TOTO
CREATE TABLE IF NOT EXISTS `users` (
`id` int(11) NOT NULL auto_increment,
`name` varchar(63) NOT NULL,
`pass` varchar(8) NOT NULL,
`mail` varchar(255) NOT NULL,
PRIMARY KEY (`id`),
KEY `ID_2` (`id`)
);

et je voudrai créer un fichier php
sous ce format (a partir des information de la base)
<? /* ***** PASSWORDS ***** */
$passwords = array (
"name" => "pass",
"name2" => "pass2",
);
/* ***** MAIL-ADDRESSES ***** */
$mail_addresses = array (
"name" => "mail@nowhere.org",
"name2" => "someone@world.net"
); ?>

Merci

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.