mornaloce
Messages postés51Date d'inscriptionlundi 17 mars 2008StatutMembreDernière intervention21 mars 2014
-
16 janv. 2012 à 17:17
mornaloce
Messages postés51Date d'inscriptionlundi 17 mars 2008StatutMembreDernière intervention21 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.
cs_Jack
Messages postés14006Date d'inscriptionsamedi 29 décembre 2001StatutModérateurDernière intervention28 août 201578 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'
cs_Jack
Messages postés14006Date d'inscriptionsamedi 29 décembre 2001StatutModérateurDernière intervention28 août 201578 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)
mornaloce
Messages postés51Date d'inscriptionlundi 17 mars 2008StatutMembreDernière intervention21 mars 20142 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.
cs_Jack
Messages postés14006Date d'inscriptionsamedi 29 décembre 2001StatutModérateurDernière intervention28 août 201578 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
Vous n’avez pas trouvé la réponse que vous recherchez ?
mornaloce
Messages postés51Date d'inscriptionlundi 17 mars 2008StatutMembreDernière intervention21 mars 20142 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.
mornaloce
Messages postés51Date d'inscriptionlundi 17 mars 2008StatutMembreDernière intervention21 mars 20142 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
'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
mornaloce
Messages postés51Date d'inscriptionlundi 17 mars 2008StatutMembreDernière intervention21 mars 20142 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
mornaloce
Messages postés51Date d'inscriptionlundi 17 mars 2008StatutMembreDernière intervention21 mars 20142 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 ?
nabil1970
Messages postés5Date d'inscriptionmardi 24 janvier 2012StatutMembreDernière intervention19 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
mornaloce
Messages postés51Date d'inscriptionlundi 17 mars 2008StatutMembreDernière intervention21 mars 20142 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.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
'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