Va bene SQLITE?

di il
9 risposte

Va bene SQLITE?

Buongiorno a tutti, premetto che non sono un programmatore ma mi sto cimentando da autodidatta nella creazione di un programmino che gestisce il magazzino di una azienda alimentare, lo faccio più che altro per imparare una cosa nuova. Sto sviluppando l'interfaccia con python (tkinter) ed i dati gli salverei in un database SQlite. Non chiedetemi il perché di queste scelte, sono perlopiù casuali o almeno basate su qualche tutorial reperito qua e là. In sostanza devo registrare le produzioni, i movimenti di magazzino e le consegne ai clienti al fine di gestire la tracciabilità, non mi interessa tutta la parte contabile, mi voglio concentrare solo sul mantenimento della tracciabilità di materie prime e prodotti. 

Ho una tabella produzioni in cui registro tutti i dati di ogni produzione, poi ho una tabella operazioni silos che dovrebbe registrare tutti i movimenti di magazzino, poi ho varie tabelle di scarico magazzino a seconda se il prodotto esce sfuso, confezionato ed altri casi particolari. E poi ho una tabella situazione silos che mi dovrebbe mostrare per ogni silos la quantità attualmente in giacenza.  Per il momento, seppur a fatica, sono riuscito a far funzionare tutto ma incomincio ad avere dei dubbi riguardo al metodo che sto utilizzando. Mi spiego meglio:

Quando inserisco una produzione, in automatico deve aggiornarsi anche la tabella operazioni silos e la tabella situazione silos. Ho aggiunto dei trigger che fanno questo. Lo stesso vale per gli scarichi, altri trigger. Poi devo considerare l'eventualità che un record aggiunto in produzioni o in qualche tabella di scarico, venga rimosso o modificato, ho gestito tutto sempre con i trigger ma per 2 tabelle (una produzione ed una di scarico) sono già a 12 trigger e manca ancora qualcosa. E' questo il metodo giusto o sono totalmente fuori strada?  Con SQlite, una volta impostato tutto il database, è possibile interrogarlo per tirare fuori i dati di tracciabilità di un prodotto?

Poi un'altra domanda, io sto navigando un po' a vista, faccio un po' di database, poi aggiungo qualche pezzetto d'interfaccia grafica così un po' a caso, talvolta mi appunto qualcosa su un foglio, ma via via mi sto lasciando dietro bug o cose incomplete che poi non ritroverò mai. Che metodo utilizzate per organizzare il lavoro?  

Concludo questo sproloquio con dei complimenti a voi altri… ci vuole 2 belle palle per fare questo mestiere…. 

9 Risposte

  • Re: Va bene SQLITE?

    20/02/2024 - Nicco46 ha scritto:


    Buongiorno a tutti, premetto che non sono un programmatore ma mi sto cimentando da autodidatta

    e cominci con python? uso le tue parole: complimenti a voi altri… ci vuole 2 belle palle per fare questo!

    20/02/2024 - Nicco46 ha scritto:


    Quando inserisco una produzione, in automatico deve aggiornarsi anche la tabella operazioni silos e la tabella situazione silos. Ho aggiunto dei trigger che fanno questo. Lo stesso vale per gli scarichi, altri trigger.

    in che senso? cosa fanno questi trigger?

    20/02/2024 - Nicco46 ha scritto:


    Poi un'altra domanda, io sto navigando un po' a vista, faccio un po' di database, poi aggiungo qualche pezzetto d'interfaccia grafica così un po' a caso, talvolta mi appunto qualcosa su un foglio, ma via via mi sto lasciando dietro bug o cose incomplete che poi non ritroverò mai. Che metodo utilizzate per organizzare il lavoro?  

    gli appunti sono sui libri… il programma o l'applicativo su un quadernone a fogli mobili. sezione dati, sezione interfaccia, sezione funzioni ecc…

    sqlite puo' andare bene.

  • Re: Va bene SQLITE?

    @nicco46 

    i metodi di lavoro si studiano e si applicano con la pratica. E ci vogliono anni. Spiegarlo in un post vuol dire concentrare anni di esperienza in una manciata di parole. Complicato.

    Sqlite: no. Non e' lo strumento giusto per questo tipo di applicazioni. Si usa MySQL, mariadb, postgresql, oppure per cose grosse (non e' il tuo caso) SQL server, oracle, db2.

    trigger: no. Al 99% dei casi i tuoi dati non sono ‘normalizzati'. I trigger sono utili MA se li devi usare GIA' in fase di inserimento dei dati, “”C'E' QUALCOSA DI MARCIO in Danimarca"". 
    OPPURE stai usando i trigger per fare qualcosa che puo' essere fatto in modo moooolto piu' semplice mediante una SELECT.

    Anche per questo si deve studiare: teoria relazione dei dati, forme normali, proprieta' ACID, SQL, … 

    Quindi, fondamentalmente: tutto sbagliato, tutto da rifare. 

    D'altra parte tutto dipende da quale e' il tuo obiettivo: pestare tasti per vedere che effetto che fa. In questo caso il tuo approccio non e' il massimo ma ci puo' stare

    oppure

    realizzare qualcosa di utile, nel qual caso ti mancano le basi, da quanto ho capito. 

    Diciamo che vorresti guidare una Tesla Plaid non sapendo nemmeno andare in triciclo. 
    In prima con il freno tirato lo potresti anche fare, ma sarebbe l'unico modo per non farsi male ;-) 

  • Re: Va bene SQLITE?

    @sishandrea: sqlite si e no.

    In effetti a questi livelli, non ci sarebbero grandi differenze. Comunque un MySQL permetterebbe di avere una visione piu' realistica di come si realizzano queste applicazioni. Dal punto di vista di Python non cambia un gran che. Se usa sqlalchemy molte cose vengono nascoste ed usare uno o l'altro non cambia molto.

    quindi? boh! 

  • Re: Va bene SQLITE?

    Grazie a tutti per le risposte, 

    20/02/2024 - sihsandrea ha scritto:


    in che senso? cosa fanno questi trigger?

    faccio prima ad incollarti quel poco che ho scritto cosi magari spiego meglio anche l'intento:

    --crea la tabella Produzione
    CREATE TABLE Produzione (
    id INTEGER PRIMARY KEY,
    data_produzione DATE,
    numero_giornaliero INTEGER,
    miscelaVARCHAR(200),
    prodotto VARCHAR(200),
    cella INTEGER,
    quantità DECIMAL(7,2),
    c_lav VARCHAR(2),
    cliente VARCHAR(200),
    numero_produzione INTEGER,
    numero_prodotto INTEGER,
    lotto VARCHAR (12)
    );
    
    -- crea la tabella operazioni_silos
    CREATE TABLE operazioni_silos (
    id_operazione INTEGER PRIMARY KEY AUTOINCREMENT,
    cella INTEGER,
    data DATE,
    prodotto VARCHAR(200),
    quantità DECIMAL,
    id_produzione INTEGER,
    id_travaso INTEGER,
    id_carico INTEGER,
    id_insacco INTEGER,
    id_rimanenze INTEGER,
    FOREIGN KEY (id_produzione) REFERENCES Produzione (id),
    FOREIGN KEY (id_carico) REFERENCES carico (id_carico)
    );
    
    -- crea la tabella carico
    CREATE TABLE carico (
    id_carico INTEGER PRIMARY KEY AUTOINCREMENT,
    data DATE,
    cliente VARCHAR (50),
    prodotto VARCHAR (200),
    cella_1 INTEGER,
    percentuale_1 INTEGER,
    quantità_1 DECIMAL,
    cella_2 INTEGER,
    percentuale_2 INTEGER,
    quantità_2 DECIMAL,
    cella_3 INTEGER,
    percentuale_3 INTEGER,
    quantità_3 DECIMAL,
    quantità_tot DECIMAL,
    trasporto VARCHAR (50),
    operatore VARCHAR (20),
    FOREIGN KEY (cella_1) REFERENCES operazioni_silos (cella),
    FOREIGN KEY (cella_2) REFERENCES operazioni_silos (cella),
    FOREIGN KEY (cella_3) REFERENCES operazioni_silos (cella)
    );
    
    --crea la tabella totali_celle
    CREATE TABLE totali_celle (
    id_cella INTEGER PRIMARY KEY,
    quantità DECIMAL DEFAULT 0,
    prodotto VARCHAR (200),
    FOREIGN KEY (id_cella) REFERENCES operazioni_silos (cella)
    ON UPDATE CASCADE
    ON DELETE CASCADE
    );
    
    -- inserisce righe vuote con il numero della cella in totali_celle
    INSERT INTO totali_celle (id_cella) VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10),
    (11), (12), (13), (14), (15), (16), (17), (18), (19),
    (20), (21), (22), (23), (24), (25), (26), (27), (28),
    (29), (30), (46), (47), (48), (49), (50), (51), (52), (53), (54);
    
    -- inserisce il trigger aggiungi da produzione alla tabella Produzione
    CREATE TRIGGER aggiungi_da_Produzione
    AFTER INSERT ON Produzione
    FOR EACH ROW
    WHEN NEW.id IS NOT NULL AND NOT EXISTS (SELECT 1 FROM operazioni_silos WHERE id_produzione = NEW.id)
    BEGIN
    INSERT INTO operazioni_silos (cella, data, prodotto, quantità, id_produzione)
    VALUES (NEW.cella, NEW.data_produzione, NEW.prodotto, NEW.quantità, NEW.id);
    END;
    
    -- inserisce il trigger aggiorna operazioni_silos
    CREATE TRIGGER aggiorna_da_Produzione
    AFTER UPDATE ON Produzione
    FOR EACH ROW
    BEGIN
    UPDATE operazioni_silos
    SET cella=NEW.cella, data=NEW.data_produzione, prodotto=NEW.prodotto, quantità=NEW.quantità
    WHERE id_produzione=NEW.id;
    END;
    
    -- inserisce il trigger rimuove operazione se rimosso da Produzione alla tabella Produzione
    CREATE TRIGGER rimuovi_da_Produzione
    AFTER DELETE ON Produzione
    FOR EACH ROW
    BEGIN
    DELETE FROM operazioni_silos
    WHERE id_produzione = OLD.id;
    END;
    
    -- inserisce il trigger aggiunge totali celle alla tabella operazioni_silos
    CREATE TRIGGER aggiungi_a_totali_celle
    AFTER INSERT ON operazioni_silos
    FOR EACH ROW
    WHEN NEW.id_produzione IS NOT NULL
    BEGIN
    UPDATE totali_celle
    SET quantità = quantità + NEW.quantità,
    prodotto = NEW.prodotto
    WHERE id_cella = NEW.cella;
    END;
    
    -- Aggiorna totali_celle se viene modificata una quantità in produzione
    CREATE TRIGGER aggiorna_totali_celle
    AFTER UPDATE ON operazioni_silos
    FOR EACH ROW
    WHEN NEW.id_produzione IS NOT NULL
    BEGIN
    -- Calcola la differenza di quantità e variala nella vecchia cella
    UPDATE totali_celle
    SET quantità = quantità - OLD.quantità
    WHERE id_cella = OLD.cella;
    -- Calcola la differenza di quantità e variala nella nuova cella
    UPDATE totali_celle
    SET quantità = quantità + NEW.quantità,
    prodotto = NEW.prodotto
    WHERE id_cella = NEW.cella;
    END;
    
    -- inserisce il trigger rimuovi da totali_celle se viene cancellata una operazione in operazioni_silos
    CREATE TRIGGER Rimuovi_totali_celle_da_Produzione
    AFTER DELETE ON operazioni_silos
    FOR EACH ROW
    WHEN OLD.id_produzione IS NOT NULL
    BEGIN
    UPDATE totali_celle
    SET quantità = quantità - OLD.quantità
    WHERE id_cella = OLD.cella;
    END;
    
    -- inserisce il trigger prodotto NULL se il totale cella è 0 in totali_celle
    CREATE TRIGGER prodotto_NULL
    AFTER UPDATE ON totali_celle
    FOR EACH ROW
    BEGIN
    UPDATE totali_celle
    SET prodotto = NULL
    WHERE quantità = 0;
    END;
    
    -- inserisce il trigger togli da carico alla tabella carico, inserisce una riga in operazioni silos per ogni cella compilata in carico
    CREATE TRIGGER togli_da_carico
    AFTER INSERT ON carico
    FOR EACH ROW
    BEGIN
    -- Prima inserzione
    INSERT INTO operazioni_silos (cella, data, prodotto, quantità, id_carico)
    VALUES (NEW.cella_1, NEW.data, NEW.prodotto, -NEW.quantità_1, NEW.id_carico);
    
    -- Seconda inserzione se cella_2 non è NULL
    INSERT INTO operazioni_silos (cella, data, prodotto, quantità, id_carico)
    SELECT NEW.cella_2, NEW.data, NEW.prodotto, -NEW.quantità_2, NEW.id_carico
    WHERE NEW.cella_2 IS NOT '';
    
    -- Terza inserzione se cella_3 non è NULL
    INSERT INTO operazioni_silos (cella, data, prodotto, quantità, id_carico)
    SELECT NEW.cella_3, NEW.data, NEW.prodotto, -NEW.quantità_3, NEW.id_carico
    WHERE NEW.cella_3 IS NOT '';
    END;
    
    -- inserisce il trigger toglie da totali celle se inserito un record in operazioni silos da carico
    CREATE TRIGGER togli_a_totali_celle_da_carico
    AFTER INSERT ON operazioni_silos
    FOR EACH ROW
    WHEN NEW.id_carico IS NOT NULL
    BEGIN
    UPDATE totali_celle
    SET quantità = quantità + NEW.quantità
    WHERE id_cella = NEW.cella;
    END;
    
    -- inserisce trigger che rimouve un record da operazioni silos se rimosso da carico
    CREATE TRIGGER rimuovi_da_operazioni_silos_se_rimosso_in_carico
    AFTER DELETE ON carico
    FOR EACH ROW
    BEGIN
    DELETE FROM operazioni_silos
    WHERE id_carico = OLD.id_carico;
    END;
    
    -- inserisce il trigger che aggiunge in totali celle se cancella un record in carico
    CREATE TRIGGER aggiunge_totali_celle_se_rimosso_carico
    AFTER DELETE ON operazioni_silos
    FOR EACH ROW
    WHEN OLD.id_carico IS NOT NULL
    BEGIN
    UPDATE totali_celle
    SET quantità = quantità - OLD.quantità
    WHERE id_cella = OLD.cella;
    END;
    
    -- inserisce il trigger che aggiorna operazioni silos se modifico carico
    CREATE TRIGGER aggiorna_operazioni_silos_se_modifica_carico
    AFTER UPDATE ON carico
    FOR EACH ROW
    BEGIN
    UPDATE operazioni_silos
    SET cella=NEW.cella_1, data=NEW.data, prodotto=NEW.prodotto, quantità=-NEW.quantità_1
    WHERE id_carico=NEW.id_carico AND cella=NEW.cella_1;
    UPDATE operazioni_silos
    SET cella=NEW.cella_2, data=NEW.data, prodotto=NEW.prodotto, quantità=-NEW.quantità_2
    WHERE id_carico=NEW.id_carico AND cella=NEW.cella_2;
    UPDATE operazioni_silos
    SET cella=NEW.cella_3, data=NEW.data, prodotto=NEW.prodotto, quantità=-NEW.quantità_3
    WHERE id_carico=NEW.id_carico AND cella=NEW.cella_3;
    END;
    

    20/02/2024 - migliorabile ha scritto:


    i metodi di lavoro si studiano e si applicano con la pratica. E ci vogliono anni. Spiegarlo in un post vuol dire concentrare anni di esperienza in una manciata di parole. Complicato.

    Sqlite: no. Non e' lo strumento giusto per questo tipo di applicazioni. Si usa MySQL, mariadb, postgresql, oppure per cose grosse (non e' il tuo caso) SQL server, oracle, db2.

    trigger: no. Al 99% dei casi i tuoi dati non sono ‘normalizzati'.

    Anche per questo si deve studiare: teoria relazione dei dati, forme normali, proprieta' ACID,… 

    quindi, fondamentalmente: tutto sbagliato, tutto da rifare. 

    D'altra parte tutto dipende da quale e' il tuo obbiettivo: pestare tasti per vedere che effetto che fa, in questo caso il tuo approccio non e' il massimo ma ci puo' stare

    oppure

    realizzare qualcosa di utile, nel qual caso ti mancano le basi, da quanto ho capito. 

    Ti ringrazio per queste parole, ti dico la verità, mi sarebbe sempre piaciuto poter studiare e imparare a programmare, da ragazzetto ho fatto altre scelte, ora ci sto provando con i mezzi ed il tempo a mia disposizione, purtroppo non conosco di persona nessuno che mi può aiutare e cerco di arrangiarmi, l'obbiettivo sarebbe quello di arrivare a qualcosa di utile, se non ci riesco, almeno avrò imparato qualcosa di nuovo… Sono pronto anche a studiare, il problema è anche capire dove indirizzare lo sforzo. Se mi dite che sono in un vicolo cieco, bene riparto da zero. Se mi dite che SQlite non va bene, proverò con quello che mi suggerite voi. Ma capite che nella mia situazione non è nemmeno facile capire se la strada imboccata sia quella giusta. 

    20/02/2024 - migliorabile ha scritto:


    Dal punto di vista di Python non cambia un gran che. Se usa sqlalchemy molte cose vengono nascoste ed usare uno o l'altro non cambia molto.

    Per scrivere il codice SQL sto utilizzando DBeaver, mentre l'inserimento dei dati avviene tramite python, vi metto qui un esempio di una pagina del programmino, se ne avete tempo e voglia create un database, modificate database_path, lanciate l'SQL e verificate il funzionamento del programmino.

    import customtkinter as ctk
    import tkinter as tk
    from tkinter import *
    from tkinter import ttk
    from CTkMessagebox import CTkMessagebox
    from PIL import Image, ImageTk
    import sqlite3
    from Gestione_DB.inserisci_nuovi_produzione import inserisci_nuovi
    from Gestione_DB.aggiorna_dati_produzione2 import aggiorna2
    import subprocess
    
    
    
    # Percorso del database SQLite
    database_path = 'PERCORSO DB'
    
    
    #abilita dark mode
    ctk.set_appearance_mode("Dark")
    
    
    def apri_main():
    #dimentica tutti i widget nel frame
    for widget in main_frame.winfo_children():
    widget.pack_forget()
    widget.grid_forget()
    
    
    #ripristina i pulsanti del main
    
    button3 = ctk.CTkButton(master=main_frame, text='CARICO', width=200, border_color='black', border_width=2, fg_color='#FFFFB3', hover_color='#FFEE80', text_color='#8B0000', command= apri_carico)
    button3.pack(expand='true',side= 'left', padx=20, pady=50)
    button3.configure(font= ('Lato', 16))
    
    
    def apri_carico():
    #dimentica tutti i widget nel frame
    for widget in main_frame.winfo_children():
    widget.pack_forget()
    
    
    
    main_frame.columnconfigure(0, weight=1)
    main_frame.rowconfigure(0, weight=1)
    main_frame.rowconfigure(1, weight=4)
    main_frame.rowconfigure(2, weight=2)
    main_frame.rowconfigure(3, weight=1)
    
    #crea frame top
    frame_top = ctk.CTkFrame(main_frame)
    frame_top.grid(column='0',row='0', padx=10, sticky=NSEW)
    
    
    #crea frame tabella
    frame_tabella = ctk.CTkFrame(main_frame)
    #frame_tabella.configure(fg_color='red')
    frame_tabella.grid(column='0', row='1', padx=10, sticky=NSEW)
    
    
    #crea frame pulsanti
    frame_pulsanti = ctk.CTkFrame(main_frame)
    #frame_pulsanti.configure(fg_color='green')
    frame_pulsanti.grid(column='0', row='2', padx=10, sticky=NSEW)
    
    
    frame_pulsanti.columnconfigure(0, weight=1)
    frame_pulsanti.columnconfigure(1, weight=1)
    
    
    #crea frame sinsitra all'interno di frame pulsanti
    frame_sinistra = ctk.CTkFrame(frame_pulsanti)
    #frame_sinistra.configure(fg_color='red')
    frame_sinistra.grid(column='0', row='1', sticky=NSEW)
    
    
    #crea frame destra all'interno di frame pulsanti
    frame_destra = ctk.CTkFrame(frame_pulsanti)
    #frame_destra.configure(fg_color='green')
    frame_destra.grid(column='1', row='1', sticky=NSEW)
    
    
    #crea frame bottom
    frame_bottom = ctk.CTkFrame(main_frame)
    #frame_bottom.configure(fg_color='white')
    frame_bottom.grid(column='0', row='3', padx=10, sticky=NSEW)
    
    # crea e inserisci l'etichetta CARICO nel frame_top
    label_carico = ctk.CTkLabel(frame_top, text="CARICO", text_color='#FFFFB3')
    label_carico.pack(side='top', pady=30)
    label_carico.configure(font=('Lato', 20, 'bold'))
    
    #Svuota la treeview
    def clear_treeview():
    tabella.delete(*tabella.get_children())
    
    
    #Aggiorna la treeviw dal database
    def aggiorna_treeview():
    clear_treeview()
    apri_database_carico()
    
    
    # MODIFICA CARICO
    
    
    # messaggio che chiede conferma
    def conferma_modifica(entry_id):
    msg = CTkMessagebox(title="Conferma modifica", width=450,fg_color='light grey', bg_color='black', font=('Lato', 15), text_color='black', border_width=2, border_color='black', button_color='#FFEE80', button_text_color='#8B0000', button_hover_color='#FFFFB3', message=f"Stai per modificare il carico ID {entry_id.get()} \n Vuoi continuare?",
    icon="question", option_1="SI", option_2="NO")
    risposta = msg.get()
    if risposta == 'SI':
    modifica_carico()
    
    def modifica_carico():
    
    ''' Questa parte di codice commentato serviva per aggiornare la treeview senza l'ausilio del database, ora aggiorna il database e refresha la treeview
    in base a cosa trova nel database aggiornato
    
    
    #prendi il numero del record
    selected = tabella.focus()
    #aggiorna record
    tabella.item(selected, text="",values= (entry_id.get(),
    entry_data.get(),
    entry_cliente.get(),
    entry_prodotto.get(),
    entry_cella_1.get(),
    entry_percentuale_1.get(),
    entry_quantità_1.get(),
    entry_cella_2.get(),
    entry_percentuale_2.get(),
    entry_quantità_2.get(),
    entry_cella_3.get(),
    entry_percentuale_3.get(),
    entry_quantità_3.get(),
    entry_quantità_tot.get(),
    entry_trasporto.get(),
    entry_operatore.get(),
    ))
    '''
    
    
    # aggiorna il database
    
    
    # Collegamento al DB TRACCIADB (tabella Produzione)
    conn = sqlite3.connect(database_path)
    
    # Crea un cursore
    c = conn.cursor()
    
    c.execute("""UPDATE carico SET
    data = :data,
    cliente = :cliente,
    prodotto = :prodotto,
    cella_1 = :cella_1,
    percentuale_1 = :percentuale_1,
    quantità_1 = :quantità_1,
    cella_2 = :cella_2,
    percentuale_2 = :percentuale_2,
    quantità_2 = :quantità_2,
    cella_3 = :cella_3,
    percentuale_3 = :percentuale_3,
    quantità_3 = :quantità_3,
    quantità_tot = :quantità_tot,
    trasporto = :trasporto,
    operatore = :operatore
    
    WHERE oid = :oid""",
    {
    'data': entry_data.get(),
    'cliente': entry_cliente.get(),
    'prodotto': entry_prodotto.get(),
    'cella_1': entry_cella_1.get(),
    'percentuale_1': entry_percentuale_1.get(),
    'quantità_1': entry_quantità_1.get(),
    'cella_2': entry_cella_2.get(),
    'percentuale_2': entry_percentuale_2.get(),
    'quantità_2': entry_quantità_2.get(),
    'cella_3': entry_cella_3.get(),
    'percentuale_3': entry_percentuale_3.get(),
    'quantità_3': entry_quantità_3.get(),
    'quantità_tot': entry_quantità_tot.get(),
    'trasporto': entry_trasporto.get(),
    'operatore': entry_operatore.get(),
    'oid': entry_id.get(),
    })
    
    
    # Commit cambiamenti
    conn.commit()
    
    #Chiudi
    conn.close()
    
    #clear entry
    clear_entry()
    #Questo comando sotto è necessario altrimenti da un errore quando chiama aggiorna tabella (non ho capito il perché ma è così)
    #c'ho bestemmiato tanto!!!!
    tabella.update()
    #aggiorna treeview
    aggiorna_treeview()
    
    
    
    
    # aggiungi un carico
    def aggiungi_carico():
    
    # Collegamento al DB TRACCIADB (tabella Produzione)
    conn = sqlite3.connect(database_path)
    
    # Crea un cursore
    c = conn.cursor()
    
    # Per inserire un nuovo record ha bisogno di inserire qualcosa in tutte le colonne, quindi vuole anche l'id, con questo escamotage leggo
    # l'ultimo id dal database e ci aggiungo 1, dopodiche assegno questa variabile all'inserimento di id
    c.execute('SELECT MAX(id_carico) FROM carico')
    ultimo_id_carico = c.fetchone()[0]
    nuovo_id = ultimo_id_carico+1
    
    
    
    #aggiunge un nuovo record
    c.execute("""INSERT INTO carico VALUES (
    :id,
    :data,
    :cliente,
    :prodotto,
    :cella_1,
    :percentuale_1,
    :quantità_1,
    :cella_2,
    :percentuale_2,
    :quantità_2,
    :cella_3,
    :percentuale_3,
    :quantità_3,
    :quantità_tot,
    :trasporto,
    :operatore)""",
    {
    'id': nuovo_id,
    'data': entry_data.get(),
    'cliente': entry_cliente.get(),
    'prodotto': entry_prodotto.get(),
    'cella_1': entry_cella_1.get(),
    'percentuale_1': entry_percentuale_1.get(),
    'quantità_1': entry_quantità_1.get(),
    'cella_2': entry_cella_2.get(),
    'percentuale_2': entry_percentuale_2.get(),
    'quantità_2': entry_quantità_2.get(),
    'cella_3': entry_cella_3.get(),
    'percentuale_3': entry_percentuale_3.get(),
    'quantità_3': entry_quantità_3.get(),
    'quantità_tot': entry_quantità_tot.get(),
    'trasporto': entry_trasporto.get(),
    'operatore': entry_operatore.get(),
    })
    
    
    # Commit cambiamenti
    conn.commit()
    
    #Chiudi
    conn.close()
    
    #clear entry boxes
    clear_entry()
    
    
    #aggiorna la treeview
    aggiorna_treeview()
    
    #Elimina un record
    
    # messaggio che chiede conferma
    def conferma_elimina(entry_id):
    msg = CTkMessagebox(title="Conferma eliminazione", message=f"Stai per eliminare il carico ID {entry_id.get()} \n Vuoi continuare?",
    icon="question", option_1="SI", option_2="NO")
    risposta = msg.get()
    if risposta == 'SI':
    elimina_carico()
    
    def elimina_carico():
    
    # Queste 2 righe commentate servivano per aggiornare la treeview senza l'ausilio del databse, ora elimina il record dal database ed aggiorna la
    # treeview in base a quello che trova nel database aggiornato
    #x = tabella.selection()[0]
    #tabella.delete(x)
    
    
    # Collegamento al DB TRACCIADB (tabella Produzione)
    conn = sqlite3.connect(database_path)
    
    # Crea un cursore
    c = conn.cursor()
    
    
    # cancella dal database
    c.execute("DELETE from carico WHERE oid =" + entry_id.get())
    
    # Commit cambiamenti
    conn.commit()
    
    #Chiudi
    conn.close()
    
    #Clear entry boxes
    clear_entry()
    
    
    #aggiorna treeview
    aggiorna_treeview()
    
    
    #Clear entry boxes
    def clear_entry():
    entry_id.delete(0, END)
    entry_data.delete(0, END)
    entry_cliente.delete(0, END)
    entry_prodotto.delete(0, END)
    entry_quantità_tot.delete(0, END)
    entry_trasporto.delete(0, END)
    entry_operatore.delete(0, END)
    entry_cella_1.delete(0, END)
    entry_percentuale_1.delete(0, END)
    entry_quantità_1.delete(0, END)
    entry_cella_2.delete(0, END)
    entry_percentuale_2.delete(0, END)
    entry_quantità_2.delete(0, END)
    entry_cella_3.delete(0, END)
    entry_percentuale_3.delete(0, END)
    entry_quantità_3.delete(0, END)
    
    
    
    # Collega al DATABASE
    def apri_database_carico():
    
    # Collegamento al DB TRACCIADB (tabella Produzione)
    conn = sqlite3.connect(database_path)
    
    # Crea un cursore
    c = conn.cursor()
    
    c.execute("SELECT rowid, * FROM carico ORDER BY id_carico DESC")
    records = c.fetchall()
    
    # Aggiunge i dati alla treeview
    global count
    count = 0
    
    for record in records:
    if count % 2 == 0:
    tabella.insert(parent='', index='end', iid=count, text='', values=(record[0],
    record[2],
    record[3],
    record[4],
    record[5],
    record[6],
    record[7],
    record[8],
    record[9],
    record[10],
    record[11],
    record[12],
    record[13],
    record[14],
    record[15],
    record[16]), tags=('evenrow',))
    else:
    tabella.insert(parent='', index='end', iid=count, text='', values=(record[0],
    record[2],
    record[3],
    record[4],
    record[5],
    record[6],
    record[7],
    record[8],
    record[9],
    record[10],
    record[11],
    record[12],
    record[13],
    record[14],
    record[15],
    record[16]), tags=('oddrow',))
    count +=1
    
    
    # Commit cambiamenti
    conn.commit()
    
    #Chiudi
    conn.close()
    
    
    # clear tabella
    #def clear_tabella():
    # tabella.delete(*tabella.get_children())
    
    
    style = ttk.Style()
    
    
    # configura i colori della treeview
    style.configure("Treeview",
    background="#FFEE80",
    foreground= "black",
    rowheight=25,
    fieldbackground= "#FFEE80")
    
    # Stile intestazione
    style.configure('Treeview.Heading', background="#FFD700", fieldbackground='#FFEE80', foreground='#8B0000')
    style.map('Treeview.Heading',
    background=[('active', '#FFEE80')])
    
    # cambia il colore della selezione
    style.map('Treeview',
    background=[('selected', "#8B0000")],
    text_color=[('selected', "#FFEE80")])
    
    # crea la scrollbar
    tabella_scroll = Scrollbar(frame_tabella)
    tabella_scroll.pack(side=RIGHT, fill=Y, padx=10, pady=20)
    
    
    #crea tabella
    tabella = ttk.Treeview(frame_tabella, yscrollcommand=tabella_scroll.set, selectmode="extended")
    
    
    # configura la scrollbar
    tabella_scroll.configure(background='#FFD700', activebackground='#FFEE80', troughcolor='#FFFFB3')
    tabella_scroll.config(command=tabella.yview)
    style.configure('Vertical.TScrollbar',background='blue', troughcolor="blue")
    
    # definisce le colonne
    tabella['columns'] = (
    "id_carico",
    "data",
    "cliente",
    "prodotto",
    "cella_1",
    "percentuale_1",
    "quantità_1",
    "cella_2",
    "percentuale_2",
    "quantità_2",
    "cella_3",
    "percentuale_3",
    "quantità_3",
    "quantità_tot",
    "trasporto",
    "operatore"
    )
    
    # formatta le colonne
    tabella.column("#0", width=0, stretch=NO) #colonna fantasma che treeview aggiunge da solo a sinistra, con stretch=NO la rendiamo invisibile
    tabella.column("id_carico", anchor=CENTER , width=10)
    tabella.column("data", anchor=CENTER , width=70)
    tabella.column("cliente", anchor=W , width=250)
    tabella.column("prodotto", anchor=W , width=300)
    tabella.column("cella_1", anchor=CENTER , width=40)
    tabella.column("percentuale_1", anchor=CENTER , width=40)
    tabella.column("quantità_1", anchor=CENTER , width=40)
    tabella.column("cella_2", anchor=CENTER , width=40)
    tabella.column("percentuale_2", anchor=CENTER , width=40)
    tabella.column("quantità_2", anchor=CENTER , width=40)
    tabella.column("cella_3", anchor=CENTER , width=40)
    tabella.column("percentuale_3", anchor=CENTER , width=40)
    tabella.column("quantità_3", anchor=CENTER , width=40)
    tabella.column("quantità_tot", anchor=CENTER , width=40)
    tabella.column("trasporto", anchor=W , width=100)
    tabella.column("operatore", anchor=W , width=60)
    
    
    # crea l'intestazione
    tabella.heading("#0")
    tabella.heading("id_carico", text="id", anchor=CENTER)
    tabella.heading("data", text="data", anchor=CENTER)
    tabella.heading("cliente", text="cliente", anchor=CENTER)
    tabella.heading("prodotto", text="prodotto", anchor=CENTER)
    tabella.heading("cella_1", text="cella_1", anchor=CENTER)
    tabella.heading("percentuale_1", text="%_1", anchor=CENTER)
    tabella.heading("quantità_1", text="Q.li_1", anchor=CENTER)
    tabella.heading("cella_2", text="cella_2", anchor=CENTER)
    tabella.heading("percentuale_2", text="%_2", anchor=CENTER)
    tabella.heading("quantità_2", text="Q.li_2", anchor=CENTER)
    tabella.heading("cella_3", text="cella_3", anchor=CENTER)
    tabella.heading("percentuale_3", text="%_3", anchor=CENTER)
    tabella.heading("quantità_3", text="Q.li_3", anchor=CENTER)
    tabella.heading("quantità_tot", text="Q.li_tot", anchor=CENTER)
    tabella.heading("trasporto", text="trasporto", anchor=CENTER)
    tabella.heading("operatore", text="operatore", anchor=CENTER)
    
    
    # crea i colori alternati delle righe
    tabella.tag_configure('oddrow', background="#FFFFB3")
    tabella.tag_configure('evenrow', background="#FFEE80")
    
    # packa la tabella
    tabella.pack(fill= 'both', expand='true', ipady=100, ipadx=200, padx=15, pady=20)
    
    #esegui apri database_carico
    apri_database_carico()
    
    #inserisce l'id nel frame sinistra
    label_id = ctk.CTkLabel(frame_sinistra, text="ID", text_color='#FFFFB3')
    label_id.grid(column=3, row=0, padx=10)
    label_id.configure(font=('Lato', 16))
    
    
    entry_id = ctk.CTkEntry(frame_sinistra, fg_color='#FFFFB3',text_color='black', width=70, border_color='#8B0000')
    entry_id.grid(column=4, row=0,pady=10, padx=10)
    entry_id.configure(font=('Lato', 16))
    
    
    #inserisce i campi di inserimento nel frame destra
    #inserisce tutte le etichette
    label_data = ctk.CTkLabel(frame_destra, text="Data", text_color='#FFFFB3')
    label_data.grid(column=0, row=0, padx=10)
    label_data.configure(font=('Lato', 16))
    
    label_cliente = ctk.CTkLabel(frame_destra, text="Cliente", text_color='#FFFFB3')
    label_cliente.grid(column=0, row=1, padx=10)
    label_cliente.configure(font=('Lato', 16))
    
    
    label_prodotto = ctk.CTkLabel(frame_destra, text="Prodotto", text_color='#FFFFB3')
    label_prodotto.grid(column=0, row=2, padx=10)
    label_prodotto.configure(font=('Lato', 16))
    
    
    label_quantità_tot = ctk.CTkLabel(frame_destra, text="Quantità", text_color='#FFFFB3')
    label_quantità_tot.grid(column=2, row=0, padx=10)
    label_quantità_tot.configure(font=('Lato', 16))
    
    
    label_trasporto = ctk.CTkLabel(frame_destra, text="Trasporto", text_color='#FFFFB3')
    label_trasporto.grid(column=2, row=1, padx=10)
    label_trasporto.configure(font=('Lato', 16))
    
    
    label_operatore = ctk.CTkLabel(frame_destra, text="Operatore", text_color='#FFFFB3')
    label_operatore.grid(column=2, row=2, padx=10)
    label_operatore.configure(font=('Lato', 16))
    
    
    label_cella_1 = ctk.CTkLabel(frame_destra, text="Cella 1", text_color='#FFFFB3')
    label_cella_1.grid(column=4, row=0, padx=10)
    label_cella_1.configure(font=('Lato', 16))
    
    
    label_percentuale_1 = ctk.CTkLabel(frame_destra, text="%", text_color='#FFFFB3')
    label_percentuale_1.grid(column=4, row=1, padx=10)
    label_percentuale_1.configure(font=('Lato', 16))
    
    
    label_quantità_1 = ctk.CTkLabel(frame_destra, text="Quantità", text_color='#FFFFB3')
    label_quantità_1.grid(column=4, row=2, padx=10)
    label_quantità_1.configure(font=('Lato', 16))
    
    
    label_cella_2 = ctk.CTkLabel(frame_destra, text="Cella 2", text_color='#FFFFB3')
    label_cella_2.grid(column=6, row=0, padx=10)
    label_cella_2.configure(font=('Lato', 16))
    
    
    label_percentuale_2 = ctk.CTkLabel(frame_destra, text="%", text_color='#FFFFB3')
    label_percentuale_2.grid(column=6, row=1, padx=10)
    label_percentuale_2.configure(font=('Lato', 16))
    
    
    label_quantità_2 = ctk.CTkLabel(frame_destra, text="Quantità", text_color='#FFFFB3')
    label_quantità_2.grid(column=6, row=2, padx=10)
    label_quantità_2.configure(font=('Lato', 16))
    
    
    label_cella_3 = ctk.CTkLabel(frame_destra, text="Cella 3", text_color='#FFFFB3')
    label_cella_3.grid(column=8, row=0, padx=10)
    label_cella_3.configure(font=('Lato', 16))
    
    
    label_percentuale_3 = ctk.CTkLabel(frame_destra, text="%", text_color='#FFFFB3')
    label_percentuale_3.grid(column=8, row=1, padx=10)
    label_percentuale_3.configure(font=('Lato', 16))
    
    
    label_quantità_3 = ctk.CTkLabel(frame_destra, text="Quantità", text_color='#FFFFB3')
    label_quantità_3.grid(column=8, row=2, padx=10)
    label_quantità_3.configure(font=('Lato', 16))
    
    
    #inserisce le entry boxes
    entry_data = ctk.CTkEntry(frame_destra, fg_color='#FFFFB3',text_color='black',border_color='#8B0000')
    entry_data.grid(column=1, row=0,pady=10, padx=10)
    entry_data.configure(font=('Lato', 16))
    
    entry_cliente = ctk.CTkEntry(frame_destra, fg_color='#FFFFB3',text_color='black',border_color='#8B0000')
    entry_cliente.grid(column=1, row=1, pady=10, padx=10)
    entry_cliente.configure(font=('Lato', 16))
    
    
    entry_prodotto = ctk.CTkEntry(frame_destra, fg_color='#FFFFB3',text_color='black',border_color='#8B0000')
    entry_prodotto.grid(column=1, row=2, pady=10, padx=10)
    entry_prodotto.configure(font=('Lato', 16))
    
    
    entry_quantità_tot = ctk.CTkEntry(frame_destra, fg_color='#FFFFB3',text_color='black',border_color='#8B0000')
    entry_quantità_tot.grid(column=3, row=0, pady=10, padx=10)
    entry_quantità_tot.configure(font=('Lato', 16))
    
    
    entry_trasporto = ctk.CTkEntry(frame_destra, fg_color='#FFFFB3',text_color='black',border_color='#8B0000')
    entry_trasporto.grid(column=3, row=1, pady=10, padx=10)
    entry_trasporto.configure(font=('Lato', 16))
    
    
    entry_operatore = ctk.CTkEntry(frame_destra, fg_color='#FFFFB3',text_color='black',border_color='#8B0000')
    entry_operatore.grid(column=3, row=2, pady=10, padx=10)
    entry_operatore.configure(font=('Lato', 16))
    
    
    entry_cella_1 = ctk.CTkEntry(frame_destra, fg_color='#FFFFB3',text_color='black',width=70, border_color='#8B0000')
    entry_cella_1.grid(column=5, row=0, pady=10, padx=10)
    entry_cella_1.configure(font=('Lato', 16))
    
    
    entry_percentuale_1 = ctk.CTkEntry(frame_destra, fg_color='#FFFFB3',text_color='black',width=70, border_color='#8B0000')
    entry_percentuale_1.grid(column=5, row=1, pady=10, padx=10)
    entry_percentuale_1.configure(font=('Lato', 16))
    
    
    entry_quantità_1 = ctk.CTkEntry(frame_destra, fg_color='#FFFFB3',text_color='black',width=70, border_color='#8B0000')
    entry_quantità_1.grid(column=5, row=2, pady=10, padx=10)
    entry_quantità_1.configure(font=('Lato', 16))
    
    
    entry_cella_2 = ctk.CTkEntry(frame_destra, fg_color='#FFFFB3',text_color='black',width=70, border_color='#8B0000')
    entry_cella_2.grid(column=7, row=0, pady=10, padx=10)
    entry_cella_2.configure(font=('Lato', 16))
    
    
    entry_percentuale_2 = ctk.CTkEntry(frame_destra, fg_color='#FFFFB3',text_color='black',width=70, border_color='#8B0000')
    entry_percentuale_2.grid(column=7, row=1, pady=10, padx=10)
    entry_percentuale_2.configure(font=('Lato', 16))
    
    
    entry_quantità_2 = ctk.CTkEntry(frame_destra, fg_color='#FFFFB3',text_color='black',width=70, border_color='#8B0000')
    entry_quantità_2.grid(column=7, row=2, pady=10, padx=10)
    entry_quantità_2.configure(font=('Lato', 16))
    
    
    entry_cella_3 = ctk.CTkEntry(frame_destra, fg_color='#FFFFB3',text_color='black',width=70, border_color='#8B0000')
    entry_cella_3.grid(column=9, row=0, pady=10, padx=10)
    entry_cella_3.configure(font=('Lato', 16))
    
    
    entry_percentuale_3 = ctk.CTkEntry(frame_destra, fg_color='#FFFFB3',text_color='black',width=70, border_color='#8B0000')
    entry_percentuale_3.grid(column=9, row=1, pady=10, padx=10)
    entry_percentuale_3.configure(font=('Lato', 16))
    
    
    entry_quantità_3 = ctk.CTkEntry(frame_destra, fg_color='#FFFFB3',text_color='black',width=70, border_color='#8B0000')
    entry_quantità_3.grid(column=9, row=2, pady=10, padx=10)
    entry_quantità_3.configure(font=('Lato', 16))
    
    # Aggiunge pulsanti nel frame_sinistra
    button23 = ctk.CTkButton(frame_sinistra, text='INSERISCI CARICO',width=180, border_color='black', border_width=2, fg_color='#FFFFB3', hover_color='#FFEE80', text_color='#8B0000', command= aggiungi_carico)
    button23.grid(column=0, row=0, padx=20, pady=20)
    button23.configure(font= ('Lato', 16))
    
    # il command deve essere una lambda function perché garantisce che la funzione conferma_modifica(entry_id) venga eseguita con l'attuale valore presente in entry_id al momento del clic,
    # evitando che venga valutato solo al momento della creazione del button.
    button24 = ctk.CTkButton(frame_sinistra, text='MODIFICA CARICO',width=180, border_color='black', border_width=2, fg_color='#FFFFB3', hover_color='#FFEE80', text_color='#8B0000', command=lambda: conferma_modifica(entry_id))
    button24.grid(column=0, row=1, padx=20, pady=20)
    button24.configure(font= ('Lato', 16))
    button25 = ctk.CTkButton(frame_sinistra, text='ELIMINA CARICO',width=180, border_color='black', border_width=2, fg_color='#FFFFB3', hover_color='#FFEE80', text_color='#8B0000', command=lambda: conferma_elimina(entry_id))
    button25.grid(column=0, row=2, padx=20, pady=20)
    button25.configure(font= ('Lato', 16))
    button26 = ctk.CTkButton(frame_sinistra, text='SVUOTA CAMPI',width=180, border_color='black', border_width=2, fg_color='#FFFFB3', hover_color='#FFEE80', text_color='#8B0000', command= clear_entry)
    button26.grid(column=2, row=0, padx=20, pady=20)
    button26.configure(font= ('Lato', 16))
    
    
    
    # Aggiunge i dati della riga selezionata alle entry boxes
    def select_record(e):
    # Clear entry_boxes
    entry_id.delete(0, END)
    entry_data.delete(0, END)
    entry_cliente.delete(0, END)
    entry_prodotto.delete(0, END)
    entry_quantità_tot.delete(0, END)
    entry_trasporto.delete(0, END)
    entry_operatore.delete(0, END)
    entry_cella_1.delete(0, END)
    entry_percentuale_1.delete(0, END)
    entry_quantità_1.delete(0, END)
    entry_cella_2.delete(0, END)
    entry_percentuale_2.delete(0, END)
    entry_quantità_2.delete(0, END)
    entry_cella_3.delete(0, END)
    entry_percentuale_3.delete(0, END)
    entry_quantità_3.delete(0, END)
    
    #prende il record Number
    selected = tabella.focus()
    
    # Ho dovuto mettere queste condizioni per verificare che ci fosse veramente una riga selezionata, altrimenti succedeva
    # (ad esempio quando si apriva una messagebox), che cercava di inseirre dei valori nelle entry senza avere una selezione attiva e dava errore
    if selected:
    # Prende il record values
    values = tabella.item(selected, 'values')
    
    
    # Controlla se ci sono valori e inserisci nelle entry boxes
    if values:
    
    #inserisce nelle entry boxes
    entry_id.insert(0, values[0])
    entry_data.insert(0, values[1])
    entry_cliente.insert(0, values[2])
    entry_prodotto.insert(0, values[3])
    entry_quantità_tot.insert(0, values[13])
    entry_trasporto.insert(0, values[14])
    entry_operatore.insert(0, values[15])
    entry_cella_1.insert(0, values[4])
    entry_percentuale_1.insert(0, values[5])
    entry_quantità_1.insert(0, values[6])
    entry_cella_2.insert(0, values[7])
    entry_percentuale_2.insert(0, values[8])
    entry_quantità_2.insert(0, values[9])
    entry_cella_3.insert(0, values[10])
    entry_percentuale_3.insert(0, values[11])
    entry_quantità_3.insert(0, values[12])
    
    
    #inserisce nelle entry quando selezioni una riga
    tabella.bind("<ButtonRelease-1>", select_record)
    
    #inserisce il tasto indietro
    button13 = ctk.CTkButton(frame_bottom, text='Indietro', border_color='black', border_width=2, fg_color='#FFFFB3', hover_color='#FFEE80', text_color='#8B0000', command= apri_main)
    button13.pack(side='right', padx=20, pady=20)
    button13.configure(font= ('Lato', 16))
    
    
    
    
    #crea la prima finestra con tre pulsanti
    root = ctk.CTk()
    root.title('Programmino')
    
    
    # apre la finestra al centro dello schermo
    window_height = 1000
    window_width = 1800
    screen_width = root.winfo_screenwidth()
    screen_height = root.winfo_screenheight()
    x_cordinate = int((screen_width/2) - (window_width/2))
    y_cordinate = int((screen_height/2) - (window_height/2))
    root.geometry("{}x{}+{}+{}".format(window_width, window_height, x_cordinate, y_cordinate))
    
    
    # Campo per pulsanti
    main_frame = ctk.CTkFrame(master=root)
    
    
    #Colora il frame di rosso, per rimettere normale cancella queste 3 righe sotto e togli il commento a quella sopra
    '''
    style = ctk.Style()
    style.configure("Custom.TFrame", background="red")
    main_frame = ctk.CTkFrame(master=root, style="Custom.TFrame")
    '''
    # Aggiungi i pulsanti al frame
    
    
    button3 = ctk.CTkButton(master=main_frame, text='CARICO', border_color='black', border_width=2, fg_color='#FFFFB3', hover_color='#FFEE80', text_color='#8B0000', width=200, command= apri_carico)
    button3.pack(expand='true', side='left', padx=20, pady=50)
    button3.configure(font= ('Lato', 16))
    
    
    # Imposta la posizione del frame al centro della finestra
    #main_frame.pack(expand=True, fill='both')
    #main_frame.configure(fg_color='yellow')
    main_frame.pack(fill= 'both', expand='true')
    
    
    root.mainloop()
  • Re: Va bene SQLITE?

    Continuo qui perché sopra non riesco più a scrivere… in sostanza confermate i miei dubbi, usare i trigger per aggiornare le tabelle non è la strada giusta? SQlite non va bene, devo studiarmi MySQL? potete darmi qualche dritta su come si realizza un database che soddisfi quello che voglio fare? Non pretendo la pappa scodellata, vorrei sapere cosa di preciso devo studiare, come si fanno varie tabelle che si aggiornano in base a quello che succede in una o nell'altra e come si tiene traccia di dati passati, ad esempio se volessi sapere in una certa data cosa c'era nella cella 20… come devo impostare un database per mantenere questi dati?  

    Grazie ancora

  • Re: Va bene SQLITE?

    Sono domande che non hanno senso! Nel senso 

    PRIMA STUDIA l'elenco degli argomenti che sono stati indicati precedentemente (basta leggere i post precedenti)

    POI ti accorgerai che il 99% delle tue domande hanno GIA' trovato risposta.

    Non ha senso che ti si spieghi qualcosa che trovi descritto DETTAGLIATTAMENTE in QUALUNQUE libro sull'argomento! 

    Oltre al fatto che NOI, del tuo database, NON SAPPIAMO ASSOLUTAMENTE NULLA!!!! 

    E' come chiedere al primo che passa per la strada

    “ma la topolona che prende il taxy alle 9:33 di lunedi mi potrebbe piacere??”

    ECCHENESAPPIAMONOI?

    .

    Alcuni libri

    Database System Concepts - 2020

    Fundamentals of Database Systems - 2015

    Database Systems - 2015

    Se non li vuoi in inglese, vai su Amazon e cerca titoli simili in Italiano.

    .

    Puoi ben immaginare che a guardare il tuo codice ci viene l' “”orticaria"" ;-)
    Ma d'altra parte, nessuno e' nato “imparato”, quindi il “pasticcio” ci puo' anche stare ;-)

    Anche qui' ci sarebbe PARECCHIO da fare: siamo nell'ordine di “tutto sbagliato, tutto da rifare” !

    Ci sono in circolazione diversi corsi “introduttivi” ai vari argomenti (programmazione python, creazione database).
    FORSE ti converrebbe investire un po'di “soldini” ANCHE in questi corsi (OLTRE che in libri!!!!)

    .
    Programmare NON E' FACILE, anche per le cose SEMPLICI.
    .

  • Re: Va bene SQLITE?

    20/02/2024 - migliorabile ha scritto:


    Database System Concepts - 2020

    Preso! 33 euri, c'è scritto indian edition ma la lingua dovrebbe essere inglese, speriamo bene ;), male male finisco a scammare la gente.

    20/02/2024 - migliorabile ha scritto:


    PRIMA STUDIA l'elenco degli argomenti che sono stati indicati precedentemente (basta leggere i post precedenti)

    Sono andato a leggere cosa vuol dire normalizzazione dei dati e per quanto posso aver capito con una rapida lettura online, anche se non conoscevo affatto l'argomento, ho provato a strutturare le tabelle per evitare ridondanza dei dati o un numero di tabelle assurdo. Sicuramente la mia soluzione non è quella più giusta. Ho cercato informazioni anche su cosa siano le proprietà ACID e le forme normali. Grazie per le dritte, approfondirò!

    20/02/2024 - migliorabile ha scritto:


    @nicco46 

    trigger: no. Al 99% dei casi i tuoi dati non sono ‘normalizzati'. I trigger sono utili MA se li devi usare GIA' in fase di inserimento dei dati, “”C'E' QUALCOSA DI MARCIO in Danimarca"". 
    OPPURE stai usando i trigger per fare qualcosa che puo' essere fatto in modo moooolto piu' semplice mediante una SELECT.

    Tornando ai trigger, per evitare di usarli potrei modificare le query d'inserimento/modifica/eliminazione direttamente all'interno del programmino, cosi che eseguano tutte le modifiche in ogni tabella che deve essere aggiornata. E' più corretto così?

  • Re: Va bene SQLITE?

    Scusate di nuovo il doppio post ma stavo rispondendo prima che migliorabile modificasse la sua risposta…

    20/02/2024 - migliorabile ha scritto:


    Puoi ben immaginare che a guardare il tuo codice ci viene l' “”orticaria"" ;-)
    Ma d'altra parte, nessuno e' nato “imparato”, quindi il “pasticcio” ci puo' anche stare ;-)

    ahahahahaha immaginavo. Abbiate pietà, fino ad una settimana fa non avevo mai scritto una riga di codice.

     Domanda stupida… ti riferisci all'SQL o al python? Scommetto ad entrambi…

    20/02/2024 - migliorabile ha scritto:


    Anche qui' ci sarebbe PARECCHIO da fare: siamo nell'ordine di “tutto sbagliato, tutto da rifare” !

    annamo bene! Quindi se funziona non vuol dire che va bene (sarcasmo).. 

  • Re: Va bene SQLITE?

    20/02/2024 - Nicco46 ha scritto:


    faccio prima ad incollarti quel poco che ho scritto cosi magari spiego meglio anche l'intento:

    Io mi fermo a create table…

    Non ti serve un trigger ma un corso.

    Magari a fine corso ci ridi su anche tu.

    Segui almeno qualche corso gratuito, giusto per iniziare. Questo è un consiglio serio se vuoi intraprendere questa strada. 

    Ti hanno consigliato mysql, io non volevo scrivere questo o quel database, ma almeno con mysql trovi dei corsi base (quelli aggratis insegnano solo la base della base).

    Poi un corso su un linguaggio. Anche li ti danno le basi, il resto, visto che sei autodidatta, potresti studiarlo da solo.

    Hai bisogno di una guida che abbia tempo da dedicarti.

Devi accedere o registrarti per scrivere nel forum
9 risposte