J'ai une interface qui me permet de modifier des données dans la BDD, mais aussi d'importer des données depuis un fichier Excel.
Il a été décidé de ne modifier que le fichier Excel et de le réimporter (2/3 fois par ans).
Le problème est que si une clés est dupliqué je fait un UPDATE avec les nouvelles valeurs, les données qui ont été supprimé dans le fichier excel resteront dans la BDD.
J'ai pensé faire un Delete avant réimportation, mais c'est pas possible pour cause d'intégrité.
L'idéal serait de trouver toutes les données qui ont été supprimer du tableau Excel est les mettre avec un champs 'Aucun' ou 'Non_Utilise' dans la BDD
Je ne vois pas trop comment faire, si cela est possible directement avec une requête ?
Même en passant par du code j'ai pas l'impression que c'est plus facile, (il me faudrait comparer les anciennes données aux nouvelles données) peut être c'est le fait que j'ai beaucoup de données qui me fait peur) ?
Je vois la chose comme cela : je prend l'élément 1 de l'ancienne table et je compare à toutes les nouvelles données pour voir si il existe, puis avec l'elément2 ... j'ai juste l'impression que c'est énorme. (déjà rien que l'importation des données du fichier Excel prend 5 minute
Pour l'instant je n'ai même pas une petite idée de par ou commencer
Je vous remercie de votre aide
EDIT : Sinon ne pas gérer l'intégrité (la gérer à partir de l'application uniquement, c'est possible) pour ajouter plus de souplesse dans cette partie... (du coup dans le modèle ça me ferait une Table relié à rien)
Comment définis-tu qu'une données est identique entre la BDD et le fichier Excel (structure de la table en question) ?
J'utilise un unique sur la colonne Reference puis je fait un ON DUPLICATE KEY UPDATE avec les nouvelle valeur :
Dim cmd As New MySqlCommand("INSERT INTO element(Reference, Designation, Cout) VALUES(@Reference, @Designation, @Cout) " _
& "ON DUPLICATE KEY UPDATE Reference = @Reference, Designation = @Designation, Cout = @Cout ", con2)
Benzouye a écrit:
Comment importes-tu ton fichier Excel ? Via une table intermédiaire ? De la même structure que la table en question ?
j'utilise :
- Input de type file
- OleDbConnection
- je lis les colonnes du fichier Excel qui m'intéresse
- J'importe directement dans la Base de Données
C'est peut être pas la meilleur endroit pour poster :
En VB ça donne ceci :
Dim sexcelconnectionstring As String = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + chemin + ";Extended Properties='Excel 12.0;IMEX=1;'"
Using conn As OleDbConnection = New OleDbConnection(sexcelconnectionstring)
conn.Open()
Dim dt As DataTable = conn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, Nothing)
'Dim sheetname As String = dt.Rows(0)("Raison").ToString()
Dim Query As String = "SELECT * FROM [Pieces$]"
Dim ocmd As OleDbCommand = New OleDbCommand(Query, conn)
Dim rdr As OleDbDataReader = ocmd.ExecuteReader()
con2.Open()
While (rdr.Read())
Try
Reference = rdr.Item("Référence").ToString
Designation = rdr.Item("Désignation").ToString
Cout = CDec(rdr.Item("Coût"))
Catch
End Try
'Cout = Replace(Cout, ",", ".")
cmd.Parameters("@Reference").Value = Reference
cmd.Parameters("@Designation").Value = Designation
cmd.Parameters("@Cout").Value = Cout
cmd.ExecuteNonQuery()
End While
con2.Close()
End Using
Sinon si j'enlève les intégrité de la Table en question, Est ce que ça peut être judicieux ? et le gérer uniquement à partir de l'application pour gagner en souplesse ? (Mauvaise idée ça risque de faire beaucoup de dégât) tant que je suis en test c'est pas trop un problème
L'idéal serait d'importer ton fichier Excel dans une table MySQL tampon (que j'appelerai ici element_excel), tu pourrais ainsi comparer "tranquillement" et faire ta mise en cohérence ...
Il faudrait également ajouter une colonne "archive" de type booléen dans ta table element, valant 0 par défaut.
Donc :
Tu importes ton Ecel dans la table element_excel
Tu exécutes INSERT ... SELECT * FROM element_excel ON DUPLICATE KEY ...
Une fois que tu as fais ton INSERT ... ON DUPLICATE ... tu peux simplement faire :
UPDATE element E
LEFT JOIN element_excel EE
ON E.Reference = EE.Reference
SET E.archive = 1
WHERE EE.Reference IS NULL
Pour mettre archive = 1 là où Reference n'existe pas dans l'import Excel.
Dans le reste de ton programme, tu rajoutes une condition E.archive = 0 partout où tu ne veux plus afficher les éléments qui n'existent plus dans le fichier Excel ...
A la fin il me faut supprimer les données dans la table Element_Excel
Je dirais plutôt au début, juste avant d'importer le nouveau fichier ... histoire de garder la mémoire de ce qui a été traité la dernière fois (surtout si ce n'est fait que 2 ou 3 fois par an). Comme cela, si tu relances "par erreur" le traitement de mise en cohérence, il n'y aura pas d'impact ... Alors que si tu relances "par erreur" le traitement avec une table tampon vide tu vas archiver tous tes éléments ... ce n'est pas très grave non plus, il suffit d'importer de nouveau, mais bon ...
DeveloSt a écrit:
j'aurai une table 'Element_Excel' avec aucune relation
Ah oui, il ne faut mettre aucune contrainte sur cette table ... Sinon tu ne pourras pas la travailler ...
Je dirais plutôt au début, juste avant d'importer le nouveau fichier ... histoire de garder la mémoire de ce qui a été traité la dernière fois (surtout si ce n'est fait que 2 ou 3 fois par an). Comme cela, si tu relances "par erreur" le traitement de mise en cohérence, il n'y aura pas d'impact ... Alors que si tu relances "par erreur" le traitement avec une table tampon vide tu vas archiver tous tes éléments ... ce n'est pas très grave non plus, il suffit d'importer de nouveau, mais bon ...
Je pensais faire le traitement uniquement à l'import d'un nouveaux fichier (dans l'interface je vérifie qu'il y a bien un fichier Excel de choisit).
Benzouye a écrit:
Il faudrait également ajouter une colonne "archive" de type booléen dans ta table element, valant 0 par défaut.
Pour revenir sur la colonne de l'archive :
j'ai une table SECTEUR avec une ligne aucun , ELEMENT_SECTEUR(id_element, id_secteur), ELEMENT
Avec cette méthode je pense qu'il m'est également possible de modifier la Table ELEMENT_SECTEUR et mettre l'id_secteur à aucun pour les éléments qui ont été supprimés.
Comme cela je n'ai pas de modification sur mes requêtes SELECT.
Je n'ai pas tester mais je pense que ça donne quelques chose comme cela :
UPDATE element_secteur ES
LEFT JOIN element E
ON ES.id_Element = E.id_Element
LEFT JOIN element_excel EE
ON E.Reference = EE.Reference
SET ES.secteur = -- id du secteur 'AUCUN'
WHERE EE.Reference IS NULL
Je ne sais pas si il vaut mieux indiquer l'id en dure dans le set
ou alors faire un SELECT id_secteur FROM secteur WHERE NomSecteur = 'AUCUN'
Je pencherai soit pour l'UPDATE, soit carrément pour un DELETE dans la table ES des secteurs archivés.
Je pensais supprimer la colonne archivés, et uniquement faire un UPDATE dans la table ES des elements qui ont été supprimés avec l'id du secteur 'AUCUN'
En réfléchissant bien cette table ES complique un peu les choses (car il ne me faut pas uniquement trouver quand un element à été supprimé, mais également si il a été juste supprimé d'un secteur)
Le fichier Excel ressemble à ça ( un x veut dire que l'élément est utilisé sur le secteur) :
Je peux peut être essayer de partir uniquement sur une table tampon Element_Secteur_Excel ?
Sinon il me faut bien faire 2 mêmes INSERT INTO ... ON DUPLICATE KEY...
- Une pour la Table Tampon Excel
- Une pour la Table utilisée
Pour récupérer les éléments qui ont été ajoutés ? (ça risque de prendre du temps, avec un fichier ça prend environs 5min) après même 10 minutes je pense pas que c'est un problème car ils le mettent uniquement à jours 2/3 fois par ans.
==> Il faut juste que je prévois peut-être une popup de chargement (ou un truc du genre), déjà il faut que je regarde comment faire ne VB (je vais voir si je trouve quelques chose sur google)
SELECT * FROM lds.element_secteur where id_secteur = '9';
j'obtient :
Ma table tampon :
SELECT * FROM lds.element_secteur_excel where id_secteur='9';
En faisant :
SELECT ES.* FROM lds.element_secteur ES
LEFT JOIN lds.element_secteur_excel ESE
ON ES.id_element = ESE.id_element
WHERE ESE.id_element is null;
j'obtient :
Je m'attendait a obtenir les id_element 70, 139, 243, 256 ?
Je ne sais pas ou je fait l'erreur dans la requête ?
Pour information les id_element 142, 143, 219 corresponde à des id qui sont absent dans les 2 tables.
EDIT : c'est Workbench il commence à déconner 😅(d'habitude pour trier j'appuis sur le nom de la colonne ça va plus vite que d'écrire un order by) du coup les id_element existe bien dans la table element_secteur mais pas dans element _secteur_excel.
Je ne comprend toujours pas pourquoi il ne trouve pas les id_element 70, 139, 243, 256 ?
En gros ça a fonctionné pour les id_element 142, 143, 219 mais il y n'a pas pris en compte les autres ?
SELECT ES.*
FROM
lds.element_secteur ES
LEFT JOIN lds.element_secteur_excel ESE
ON ES.id_element = ESE.id_element
AND ES.id_secteur = ESE.id_secteur
WHERE ESE.id_element IS NULL;
Là, la requête va te sortir tous les enregistrements de ES qui n'ont pas d'équivalent exact (sur les deux colonnes) dans ESE.
Au départ je pensais que la jointure permettait uniquement de joindre les valeurs dont l'id existe dans les 2 tables, mais du coup si l'id n'existe pas il la met en NULL
Pour la jointure sur les deux colonnes c'est parce que j'ai l'id 70 par exemple qui peut quand même être présent mais sur un autre secteur DONC j'ai quand même l'id 70 et il n'est pas null.
EDIT : CEPANDANT cela pose problème, si 2 secteur de l'element 70 viens à être supprimé j'aurais 2 elements avec le secteur aucun donc clés dupliqué 😅😥
Je pencherai soit pour l'UPDATE, soit carrément pour un DELETE dans la table ES des secteurs archivés.
Si un même élément est supprimé sur 2 secteur, alors cette élément aura 2 même ligne avec le secteur 'Aucun' ==> Problème de Duplicate Key Du coup je suis quand même obligé de passer par une colonne archivés ?
Ou est-ce qui y a moyen de faire facilement un UPDATE .... ON DUPLICATE KEY DELETE ? ou quelque chose de similaire ?
L'idée que j'ai serai :
1) Récupérer via un select les lignes supprimées
2) Faire un UPDATE individuel (FOR)
3) Si Duplicate KEY (TRY CATCH)
4) DELETE WHERE (lignes supprimées ET ligne avec id correspondante ET secteur <> de 'Aucun')
Mais ça me parait compliqué
Solution 2 (je vais essayer celle-ci en premier):
1) faire un UPDATE IGNORE
2) DELETE WHERE (lignes supprimées ET secteur <> de 'Aucun')
Machines qui sont regroupé par Lignes qui sont regroupé par secteur (relation : 11 - 1N / 2x)
Si je fait un ON DELETE CASCADE il me faut suppr toutes les données calculés d'une machines, toutes les machines des lignes sur laquelle les lignes sont sur le secteur avant de pouvoir supprimer le secteur.
J'ai fait le choix de créer un secteur 'Aucun' comme cela si une ligne n'est plus utilisé dans la configuration il y a juste à déplacer la Ligne sur le secteur 'Aucun' cela permet de garder toutes les données correspondante des lignes et machines qui n'existe plus (ne sont plus utilisées).
Donc au final un secteur est très rarement 'vraiment' supprimé ou alors il faut qu'aucune ligne du secteur ne soit plus utilisé pendant 1année pour q'un admin supprime manuellement (je n'offre pas la possibilité de le faire avec l'interface car je trouve cela trop dangereux )
La solution 2 à l'air de fonctionner (je ne sais pas si ça peut poser d'autres problèmes ? )
Si tu veux j'ai la structure suivante (qui n'est pas totalement à jour 😅😅) faut que je recharge un diagramme sur workbench :
- Edité par DeveloSt 8 décembre 2020 à 17:31:44
Site Internet : https://devst.go.yj.fr
MySQL MAJ des données
× Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
× Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
Site Internet : https://devst.go.yj.fr
Site Internet : https://devst.go.yj.fr
Site Internet : https://devst.go.yj.fr
Site Internet : https://devst.go.yj.fr
Site Internet : https://devst.go.yj.fr
Site Internet : https://devst.go.yj.fr
Site Internet : https://devst.go.yj.fr
Site Internet : https://devst.go.yj.fr
Site Internet : https://devst.go.yj.fr