Transfert de base de données

Résolu
mornaloce Messages postés 51 Date d'inscription lundi 17 mars 2008 Statut Membre Dernière intervention 21 mars 2014 - 16 janv. 2012 à 17:17
mornaloce Messages postés 51 Date d'inscription lundi 17 mars 2008 Statut Membre Dernière intervention 21 mars 2014 - 7 févr. 2012 à 15:37
Bonjour à tous,

Voilà j'ai un problème. Je vous explique :
Dans l'entreprise ou je travail il y a une bdd sur le serveur principal (en PostGreSQL) et j'ai une base en local sur mon PC (en Access). Mon boss souhaite que je créé un programme qui fasse la mise à jour de la base principal via la base en local.
Pour cette mise à jour il y a deux étapes :
1 - Les deux bases étant exactement les même on commence par supprimer toutes les données des tables de la base principal. (Jusque là pas de problème)
2 - Ensuite je vais copier toutes les données de ma base en local dans la base principal et ceci table par table (via un INSERT INTO... SELECT * FROM...)

Bon ces deux étapes je peux pas faire autrement. Mon problème viens du fait que je fais mon programme en VB.Net sous visual studio et qu'il m'est impossible de faire la deuxième étapes vu que mes 2 bases sont sur des serveurs différents. J'ai chercher pendant un bout de temps sur google mais les quelques rares solutions proposées ne m'ont pas parut satisfaisantes. Quelqu'un aurait-il une idée pour m'aider à faire mon INSERT ?

Voilà. J'espère avoir été suffisamment clair dans mes explications.
Merci d'avance.

11 réponses

cs_Jack Messages postés 14006 Date d'inscription samedi 29 décembre 2001 Statut Modérateur Dernière intervention 28 août 2015 78
17 janv. 2012 à 15:45
Non, tu ne pourrais faire tout d'un seul coup si les deux DB étaient des bases Access locales (*), mais là, ce n'est pas possible.

Reprenons.
Si tu as deux bases de donnes, il te faudra deux connexions.
n°1 pour Access local
n°2 pour PostGreSQL distant

Pour transférer les données de 1 vers 2, il te faudra :
- remplir un RecordSet (objet ADODB recommandé) avec les données de la connexion 1. Un simple Select suffit, ou même charger toute la table dans le RecordSet.
- puis injecter les données de ce RecordSet vers la connexion 2 au travers d'une boucle de "Insert Into" pour chaque item de ce RecordSet, agrémenté optionnellement d'une gestion de transaction si tu veux être plus rapide.
Dans un premier temps, pour la mise ou point, ne t'occupe pas des transactions - cela peut se rajouter sans difficulté plus tard.

Refaire la même chose pour chaque table.

(*) avec une syntaxe ressemblant à cela :
Insert Into maTableAccess1
      (Champ1, Champ2, ..., ChampX)
Select Champ1, Champ2, ..., ChampX
  From maTableAccess2 In 'C:\mon répertoire\maBase2.MDB'
3
cs_Jack Messages postés 14006 Date d'inscription samedi 29 décembre 2001 Statut Modérateur Dernière intervention 28 août 2015 78
16 janv. 2012 à 18:24
Salut

"Mon problème viens du fait que je fais mon programme en VB.Net sous visual studio et qu'il m'est impossible de faire la deuxième étapes vu que mes 2 bases sont sur des serveurs différents"
Pourquoi problème ?
Tu n'as pas de cable/liaison entre ces deux serveurs ?
Parce que se connecter à des bases distantes n'est pas un problème en lui-même.

Je ne connais pas PostGreSQL, mais si ce gestionnaire a des outils (d'après ce que j'ai lu, oui) et vu qu'il ne s'agit que d'une migration/manipulation unique, je regarderai comment exporter les données depuis Access dans un format que PostGreSQL accepterait, genre CSV.
Faire de la programmation pour ça me parait une perte de temps.

Vala
Jack, MVP VB
NB : Je ne répondrai pas aux messages privés

Le savoir est la seule matière qui s'accroit quand on la partage (Socrate)
0
mornaloce Messages postés 51 Date d'inscription lundi 17 mars 2008 Statut Membre Dernière intervention 21 mars 2014 2
17 janv. 2012 à 09:48
Bonjour jack. Je suis plutôt d'accord avec toi il n'y a pas de vrai raisons de programmer mais ce n'est pas moi qui décide. ^^ Jusqu'à maintenant mon boss passait justement par Access mais il ne trouve pas ça très propre de faire des maccro pour maitre à jour la base principal. Du coup je dois programmer un truc. Mais jusqu'à maintenant j'ai eu beaucoup de mal à trouver comment faire.
0
cs_Jack Messages postés 14006 Date d'inscription samedi 29 décembre 2001 Statut Modérateur Dernière intervention 28 août 2015 78
17 janv. 2012 à 11:43
Je repose ma question :
"qu'il m'est impossible de faire la deuxième étapes vu que mes 2 bases sont sur des serveurs différents"
Pourquoi ?
C'est matériel ou bien tu ne sais pas le faire ?

Se connecter à une base distante n'est qu'une affaire de paramétrage de la connexion, ensuite, l'accès aux tables, au SQL, tout ça est identique (si le moteur est au standard SQL).
Voir <ce site de référence> en matière de connexion.

Si tu utilises ADO et que tu trouves que les Insert Into ligne à ligne est lent, regarde du côté des transactions (voir l'aide) :
-1- pour initier la transaction : maConnexion.BeginTrans
-2- tu fais une centaine d'insertion qui vont rester buffurisées
-3- Pour déclencher le transfert : maConnexion.CommitTrans
ou, pour annuler les actions buffurisées : maConnexion.RollbackTrans
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
mornaloce Messages postés 51 Date d'inscription lundi 17 mars 2008 Statut Membre Dernière intervention 21 mars 2014 2
17 janv. 2012 à 14:04
Hé bien ça m'était impossible car il faut faire un :
requeteSqlInsert = "INSERT INTO table1SQL SELECT * FROM table1Access;"
commandSql.CommandText = requeteSqlInsert
commandSql.Connection = connexionSQL

hors ça ne me connecte qu'à SQL. Le programme ne trouvera pas la table1Access de cette manière.

J'ai voulu faire d'abord un select de mes données de table1Access que je stockait dans un tableau et que j'inserrai dans ma table1SQL via un INSERT INTO mais c'est trop long. Surtout que j'ai une dizaine de table à transférer.

Du coup pour bien répondre à ta question : oui je ne sais pas faire.
0
mornaloce Messages postés 51 Date d'inscription lundi 17 mars 2008 Statut Membre Dernière intervention 21 mars 2014 2
17 janv. 2012 à 20:45
Merci beaucoup pour ton aide jack. J’essaierais ça lundi et je te tiendrais au courant !

Encore merci !
0
mornaloce Messages postés 51 Date d'inscription lundi 17 mars 2008 Statut Membre Dernière intervention 21 mars 2014 2
23 janv. 2012 à 15:46
Bonjour,

Bon jack j'ai essayé ta méthode mais j'ai du mal à comprendre comment fonctionne le RecordSet du coup ça ne fonctionne pas.
Je t'envoie mon conde pour que tu puisse m'aider à comprendre ce qui ne fonctionne pas.

Dim connexionSQL As New NpgsqlConnection
Dim commandSQL As New NpgsqlCommand
Dim requeteSqlDelete As String = ""
Dim requeteSqlInsert As String = ""
Dim listeTablesMaj As ArrayList = New ArrayList
Dim i As Integer = 0

listeTablesMaj.Add("table1")
...

'Connexion à la base de donnée SQL
connexionSQL.ConnectionString = "Server=server;Port=port;Database=database;User ID=user;Password=pwd;"

Try
connexionSQL.Open()

'Exécution de la requête de vidage des tables
For Each table In listeTablesMaj
requeteSqlDelete = "DELETE FROM " + table + ";"

commandSQL.CommandText = requeteSqlDelete 'pour interroger la table (connexion au préalable).
commandSQL.Connection = connexionSQL
commandSQL.ExecuteNonQuery()

Next

connexionSQL.Close()

Dim connectionAccess As New ADODB.Connection
Dim recordSet As New ADODB.Recordset

connectionAccess.ConnectionString = "provider=provider;data source=" + Me.TextBox_Parcourir.Text + ";"

connectionAccess.Open()
listeTablesMaj.Reverse()
connexionSQL.Open()

'Exécution de la requête de remplissage des tables
For Each tableMaj In listeTablesMaj
recordSet.Open("SELECT * FROM " + tableMaj + ";", connectionAccess)

While Not recordSet.EOF
requeteSqlDelete = "INSERT INTO " + tableMaj -> LA JE SAIS PAS TROP QUOI METTRE
'requeteSqlDelete = "INSERT INTO " + tableMaj + "(id, statut) VALUES(" + recordSet.Fields(0).Value + ", """ + recordSet.Fields(1).Value + """;"

commandSQL.CommandText = requeteSqlDelete 'pour interroger la table (connexion au préalable).
commandSQL.Connection = connexionSQL
commandSQL.ExecuteNonQuery()
End While

recordSet.Close()

Next

connectionAccess.Close()
connexionSQL.Close()

Catch ex As Exception
Me.Label1.Text = ex.Message
Exit Sub
End Try
0
mornaloce Messages postés 51 Date d'inscription lundi 17 mars 2008 Statut Membre Dernière intervention 21 mars 2014 2
24 janv. 2012 à 09:57
Finalement j'ai trouvé une methode. Je ne sais pas si c'est la meilleur mais elle marche apparemment. Si quelqu'un en a une meilleure à proposer je prend ^^

Voilà mon code :

For Each tableMaj In listeTablesMaj
recordSet.Open("SELECT * FROM " + tableMaj + ";", connectionAccess)

For i = 0 To recordSet.Fields.Count - 1 Step 1
If (i = 0) Then
champsName = recordSet.Fields(i).Name
Else
champsName = champsName + ", " + recordSet.Fields(i).Name
End If
Next

While Not recordSet.EOF
For i = 0 To recordSet.Fields.Count - 1 Step 1
If (i = 0) Then
champsValue = recordSet.Fields(i).Value.ToString()
Else
champsValue = champsValue + ", " + recordSet.Fields(i).Value.ToString()
End If
Next

requeteSqlInsert = "INSERT INTO " + tableMaj + " (" + champsName + ") VALUES(" + champsValue + ");"

commandSQL.CommandText = requeteSqlInsert 'pour interroger la table (connexion au préalable).
commandSQL.Connection = connexionSQL
commandSQL.ExecuteNonQuery()

recordSet.MoveNext()
End While

recordSet.Close()
Next

Il ne me reste qu'à testé sur toute les tables et éventuellement utiliser les transactions.
0
mornaloce Messages postés 51 Date d'inscription lundi 17 mars 2008 Statut Membre Dernière intervention 21 mars 2014 2
24 janv. 2012 à 15:35
Bon j'ai testé. Ca fonctionne mais je me suis aperçut que j'ai des tables qui ont des colonnes en plus dans Access. Du coup ma méthode est pas adaptée. Qulqu'un à une idée s'il vous plaît ?
0
nabil1970 Messages postés 5 Date d'inscription mardi 24 janvier 2012 Statut Membre Dernière intervention 19 juin 2013
24 janv. 2012 à 18:57
Je dois donc récupérer la base de données DBF existant sur excel mais je n arrive pas 1 j'ai converti en dbf bref je n arrive à l importer vers windev 14 .... svp comment faire pour surmonter ces erreurs je travail sur windev14
0
mornaloce Messages postés 51 Date d'inscription lundi 17 mars 2008 Statut Membre Dernière intervention 21 mars 2014 2
7 févr. 2012 à 15:37
Bon j'ai finalement réussi tout fonctionne ! Là où le transfert se faisait en 4 ou 5h avec une ancienne appli en windev, je met 2min35 avec la mienne ^^

Voilà mon code pour ceux que ça pourrait aider :

'Liste des tables à mettre à jour
listeTablesMaj.Add("table1")
listeTablesMaj.Add("table2")
...

'Connexion à la base de donnée SQL
connexionSQL.ConnectionString = "Server=server;Port=port;Database=db;User ID=user;Password=pass;"

Try
connexionSQL.Open()

'Exécution de la requête de vidage des tables
For Each table In listeTablesMaj
requeteSqlDelete = "DELETE FROM " + table + ";"

commandSQL.CommandText = requeteSqlDelete 'pour interroger la table (connexion au préalable).
commandSQL.Connection = connexionSQL 'connexion à la bdd
commandSQL.ExecuteNonQuery() 'execution de la requête SQL

Next

connexionSQL.Close()

Dim connectionAccess As New ADODB.Connection 'OleDbConnection
Dim recordSet As New ADODB.Recordset
Dim champsName As String = ""
Dim champsValue As String = ""
Dim champsValueModif As String = ""

connectionAccess.ConnectionString = "provider=microsoft.jet.oledb.4.0;data source=" + Me.TextBox_Parcourir.Text + ";"

connectionAccess.Open()
listeTablesMaj.Reverse() 'On inverse l'odre des tables dans la liste pour eviter les problèmes de dépendance
connexionSQL.Open()

Me.Label1.Text = "Début du transfert"

'///////Exécution de la requête de remplissage des tables////////

'Pour chaque table
For Each tableMaj In listeTablesMaj
recordSet.Open("SELECT * FROM " + tableMaj + ";", connectionAccess) 'Remplissage du recordSet avec toutes
les données de la table en cours dans Access

champsName = ""
champsValue = ""
champsValueModif = ""

Me.Label1.Text = tableMaj

'Récupération du nom des colonnes
For i = 0 To recordSet.Fields.Count - 1 Step 1
If i = 0 Then
champsName = recordSet.Fields(i).Name
Else
champsName = champsName + ", " + recordSet.Fields(i).Name
End If
Next

While Not recordSet.EOF

'Récupération des valeurs de la ligne en cours
For i = 0 To recordSet.Fields.Count - 1 Step 1
If i = 0 Then 'Si c'est la première valeur
If recordSet.Fields(i).Value.ToString = "" Then 'Si valeur null
champsValue = champsValue + ", NULL" 'on envoie NULL dans la requête d'insertion PostGreSQL
ElseIf Not IsNumeric(recordSet.Fields(i).Value) Then 'Si la valeur n'est pas un nombre
If recordSet.Fields(i).Value.ToString().Contains("'") Then 'Si la valeur text contient des (')
champsValueModif = Replace(recordSet.Fields(i).Value.ToString(), "'", "''") 'on double les apostrophe pour les "échapper" dans la requête
champsValue = "'" + champsValueModif + "'" 'et on ajoute des (') de chaque coté de la valeur dans la requête
Else
champsValue = "'" + recordSet.Fields(i).Value.ToString() + "'" 'Sinon on ajoute des (') de chaque coté de la valeur dans la requête
End If
Else
champsValue = recordSet.Fields(i).Value.ToString() 'Sinon on ajoute le nombre telquel dans la requete
End If
Else
If recordSet.Fields(i).Value.ToString = "" Then
champsValue = champsValue + ", NULL"
ElseIf IsDate(recordSet.Fields(i).Value) Then
champsValueModif = Format(recordSet.Fields(i).Value, "yyyy-MM-dd")
champsValue = champsValue + ", '" + champsValueModif + "'"
ElseIf Not IsNumeric(recordSet.Fields(i).Value) Then
If recordSet.Fields(i).Value.ToString().Contains("'") Then
champsValueModif = Replace(recordSet.Fields(i).Value.ToString(), "'", "''")
champsValue = champsValue + ", '" + champsValueModif + "'"
Else
champsValue = champsValue + ", '" + recordSet.Fields(i).Value.ToString() + "'"
End If
Else
champsValue = champsValue + ", " + recordSet.Fields(i).Value.ToString()
End If
End If
Next

requeteSqlInsert = "INSERT INTO " + tableMaj + " (" + champsName + ") VALUES(" + champsValue + ");" 'La requete SQL qui va servir à remplir la table dans PostGreSQL

commandSQL.CommandText = requeteSqlInsert 'pour interroger la table (connexion au préalable).
commandSQL.Connection = connexionSQL
commandSQL.ExecuteNonQuery()

recordSet.MoveNext() 'Positionnement su la ligne suivante du recordSet
End While

recordSet.Close()

Next
Me.Label1.Text = "Transfert terminé !"

connectionAccess.Close()
connexionSQL.Close()

Catch ex As Exception
MsgBox(ex.Message)
End Try
0
Rejoignez-nous