Comparaison de plusieurs tables avec plusieurs base de donnée

Résolu/Fermé
rasielblas Messages postés 140 Date d'inscription jeudi 20 mars 2014 Statut Membre Dernière intervention 12 mai 2021 - 9 oct. 2019 à 08:23
jee pee Messages postés 39637 Date d'inscription mercredi 2 mai 2007 Statut Modérateur Dernière intervention 25 avril 2024 - 16 oct. 2019 à 14:16
Bonjour,

J'ai un code qui permet de relié plusieurs base de donnée et de faire la comparaison de tous ces bases.
Mon problème c'est que chaque base ne contient qu'un seul table fournisseurs chacun, et j'aimerais insérer un autre table client. Alors comment modifier la requête sql de façons à ce qu'elle puissent faire la comparaison de plusieurs tables et non un seul table.
Voici mon code:
import sqlite3

def create_table(db_name, values):
    con = sqlite3.connect("./databases/%s.db" % db_name)
    cur = con.cursor()
    cur.execute(
        '''CREATE TABLE fournisseurs(
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            nom TEXT
        )'''
    )
    s = ','.join(('(?)',) * len(values))
    cur.execute('INSERT INTO fournisseurs(nom) VALUES %s' % s, values)
    con.commit()
    con.close()


def tables_dif(main_db_name, *db_names):
    con = sqlite3.connect(":memory:")
    con.execute("ATTACH DATABASE './databases/%s.db' AS main_db" % main_db_name)
    cur = con.cursor()
    res = {}
    for db_name in db_names:
        con.execute("ATTACH DATABASE './databases/%s.db' AS db" % db_name)
        sql = '''
        SELECT t2.id, t2.nom
        FROM db.fournisseurs as t2
        LEFT JOIN main_db.fournisseurs as t
        USING(nom)
        WHERE t.nom IS NULL
        '''
        cur.execute(sql)
        res[db_name] = cur.fetchall()
        con.execute("DETACH DATABASE db")
    con.close()
    return res


try:
    create_table('main', ('jojo', 'mimi', 'riri'))
    create_table('base1', ('jojo', 'riri', 'vévé'))
    create_table('base2', ('riri', 'lulu'))
except:
    pass

print(tables_dif('main', 'base1', 'base2'))


Cordialement!

1 réponse

yg_be Messages postés 22724 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 25 avril 2024 1 476
9 oct. 2019 à 15:34
bonjour,
tu pourrais par exemple modifier la requête SQL ainsi:
SELECT "fournisseurs", t2.id, t2.nom
        FROM db.fournisseurs as t2
        LEFT JOIN main_db.fournisseurs as t
        USING(nom)
        WHERE t.nom IS NULL
UNION
SELECT "client", t2.id, t2.nom
        FROM db.client as t2
        LEFT JOIN main_db.client as t
        USING(nom)
        WHERE t.nom IS NULL
1
rasielblas Messages postés 140 Date d'inscription jeudi 20 mars 2014 Statut Membre Dernière intervention 12 mai 2021 9
11 oct. 2019 à 07:49
Merci de votre réponse, ça marche bien, mais le problème c'est qu'avec UNION si le nombre de champ sélectionné de la premier table est différent de la deuxième table alors ça ne marche pas!
Par exemple si je fais quelque chose du genre:
SELECT *
        FROM db.fournisseurs as t2
        LEFT JOIN main_db.fournisseurs as t
        USING(nom)
        WHERE t.nom IS NULL
UNION
SELECT*
        FROM db.client as t2
        LEFT JOIN main_db.client as t
        USING(nom)
        WHERE t.nom IS NULL


Est que dans le table client il y a 3 champs mais que dans la table fournisseur il n'y a que deux champs alors cela ne fonctionne pas avec UNION.
En plus si je possède plusieurs tables par exemple 20 alors le requête devient très long, y a t'il d'autre option à part l'utilisation de "UNION"?
Cordialement!
0
yg_be Messages postés 22724 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 25 avril 2024 1 476 > rasielblas Messages postés 140 Date d'inscription jeudi 20 mars 2014 Statut Membre Dernière intervention 12 mai 2021
11 oct. 2019 à 10:46
peux-tu essayer de donner toutes les informations dés le départ, plutôt que d'en rajouter quand nous te proposons une solution?
0
rasielblas Messages postés 140 Date d'inscription jeudi 20 mars 2014 Statut Membre Dernière intervention 12 mai 2021 9
Modifié le 11 oct. 2019 à 12:00
Ok! je résume, j'ai trois base de donnée, base1 qui contient l'ensemble d'enregistrement de la base 2 et base3, mon code permet de comparer l'enregistrement de ses bases.

Si le contenu de la base 2 et 3 ne se trouve pas dans base 1 alors on affiche le contenu manquant.

Le problème c'est que j'ai plusieurs tables dans chacun des bases et avec la requete UNION je peut fusionner les tables.

Mais le problème c'est qu'avec la requête UNION pour que ça fonctionne il faut que le champ de la table soit le même alors que le nombre de chacun des tables est différent.

En plus si j'ai plusieurs tables 20 par exemple je suis obligé de faire UNION pour chaque tables et la requête de vient très long, et j'aimerais savoir s'il existe un autre moyen de sélectionner les tables d'une autre manière. Voici mon code:

import sqlite3

def create_table(db_name, values):
    con = sqlite3.connect("./databases/%s.db" % db_name)
    cur = con.cursor()
    cur.execute(
        '''CREATE TABLE fournisseurs(
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            nom TEXT
        )'''
    )
    s = ','.join(('(?)',) * len(values))
    cur.execute('INSERT INTO fournisseurs(nom) VALUES %s' % s, values)
    con.commit()
    con.close()


def tables_dif(main_db_name, *db_names):
    con = sqlite3.connect(":memory:")
    con.execute("ATTACH DATABASE './databases/%s.db' AS main_db" % main_db_name)
    cur = con.cursor()
    res = {}
    for db_name in db_names:
        con.execute("ATTACH DATABASE './databases/%s.db' AS db" % db_name)
        sql = '''
        SELECT "fournisseurs", t2.id, t2.nom
        FROM db.fournisseurs as t2
        LEFT JOIN main_db.fournisseurs as t
        USING(nom)
        WHERE t.nom IS NULL
UNION
SELECT "client", t2.id, t2.nom
        FROM db.client as t2
        LEFT JOIN main_db.client as t
        USING(nom)
        WHERE t.nom IS NULL
        '''
        cur.execute(sql)
        res[db_name] = cur.fetchall()
        con.execute("DETACH DATABASE db")
    con.close()
    return res


try:
    create_table('main', ('jojo', 'mimi', 'riri'))
    create_table('base1', ('jojo', 'riri', 'vévé'))
    create_table('base2', ('riri', 'lulu'))
except:
    pass

print(tables_dif('main', 'base1', 'base2'))
0
yg_be Messages postés 22724 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 25 avril 2024 1 476 > rasielblas Messages postés 140 Date d'inscription jeudi 20 mars 2014 Statut Membre Dernière intervention 12 mai 2021
11 oct. 2019 à 12:13
une autre possibilité serait d'appeler plusieurs fois la fonction tables_dif, en lui passant des paramètres supplémentaires, le nom de la table et les noms des champs.
qu'en penses-tu?
0
jee pee Messages postés 39637 Date d'inscription mercredi 2 mai 2007 Statut Modérateur Dernière intervention 25 avril 2024 9 235 > rasielblas Messages postés 140 Date d'inscription jeudi 20 mars 2014 Statut Membre Dernière intervention 12 mai 2021
11 oct. 2019 à 12:14
Bonjour,

La logique serait alors que tu rajoutes un niveau au dessus de ton code où tu paramètres les tables à traiter, du style
FOR T in ('client','fournisseur','commande', ....)


ou même générer la boucle à partir du dictionnaire de données de la base, je ne sais pas si cela existe dans sqlite, comme
"select table_name from dictionnary"
0