Pagina 1 di 3 1 2 3 ultimoultimo
Visualizzazione dei risultati da 1 a 10 su 21
  1. #1

    [MySQL] Campi personalizzabili dall'utente

    E' una casistica abbastanza comune in molte applicazioni web.
    Supponiamo di avere una certa entità, per esempio un "prodotto", che avrà la sua tabella mysql con tutti gli attributi predefiniti: id, nome, descrizione, etc. etc.

    Si vuole poter dare la possibilità all'utente - amministratore dell'applicazione di personalizzare i prodotti aggiungendo campi a sua scelta. Quindi magari se il prodotto che lui tratta sono libri vorrà aggiungere il campo "ISBN" e il campo "numero_pagine", il primo stringa e il secondo numerico, se vende dildo vorrà aggiungere la misura (valutata in GM secondo lo standard internazionale) etc. etc. con tutti gli altri esempi possibili che la fantasia può suggerire.

    Ora, esistono che io sappia (ma sono qua per questo, per saperne di più), due scuole di pensiero per gestire questa situazione:
    1) effettuare "a runtime" l'ALTER TABLE sulla tabella prodotti (o su una tabella di appoggio in relazione 1:1 con prodotti) per aggiungere / modificare / rimuovere i campi personalizzati.

    2) usare una tabella campi personalizzati fatta circa in questo modo:
    id_prodotto | nome_campo | valore_campo
    Dove valore_campo è un campo stringa molto grande (un LONGTEXT per esempio).
    (fanno così Wordpress e phplist per esempio)

    Il primo approccio, quello dell'ALTER TABLE è potenzialmente molto pesante e rischioso. Pesante perché per farlo il mysql crea ogni volta una copia dell'intera tabella, ci salva le modifiche, poi rinomina la tabella originale, rinomina la copia modificata con il nome originale e infine cancella la tabella originale. Per tabelle molto grandi questa operazione può essere quindi lentissima, e oltrettutto richiede il doppio dello spazio su disco per contenere la tabella e la sua copia provvisoria.
    E' inoltre rischioso perché l'operazione non è ATOMICA, può quindi in caso di problemi essere interrotta a metà (per esempio nel punto in cui la tabella originale è stata rinominata ma la copia non ancora) lasciando quindi il database inutilizzabile. Per riparare questa situazione è necessario inoltre l'accesso al filesystem dove sono memorizzati fisicamente i file delle tabelle, cosa che non si ha quasi mai in hosting.

    Il secondo approccio non ha gli svantaggi del precedente ma ne ha di suoi:
    Intanto la struttura non sarebbe più normalizzata correttamente,
    ci sarebbe quindi la necessità di effettuare sempre una query aggiuntiva per leggere i campi aggiuntivi del prodotto e mostrarli all'applicazione php che li usa come se fossero campi "standard", il formato del campo valore sarebbe sempre "stringa" per qualsiasi tipo di informazione, con conseguente spreco di spazio, e inoltre, se io volessi per esempio indicizzare il campo personalizzato ISBN per effettuare velocemente ricerche ma non il campo numero_pagine non potrei farlo, sarei obbligato a indicizzare totalmente il campo "valore_campo" o a non indicizzarlo per niente.

    Insomma, entrambi i metodi secondo me hanno più controindicazioni che vantaggi, e quindi chiedo a voi qualche idea alternativa per dare una soluzione al problema iniziale, tenendo presente che ho a disposizione MySQL5.

    Grazie (e scusate la lunghezza del post )

  2. #2

  3. #3

    .............

    Ciao.
    Non ho certo con questa reply la pretesa
    di risolvere il tuo problema ma siccome
    la cosa mi interessa mi introfulo.
    Il progetto di Db che dovrei fare è strutturato
    per un gioco/test on line e la grossa difficoltà
    che sto incontrando è appunto una cosa simile
    al tuo post.
    Vorrei dare all'admin la possibilità di scegliere
    il gioco/test (ad esempio se voglio implementare
    un gioco di tipo schedina(games_category) avrò
    13 (questions) (è questo il dato ballerino) se metti
    devo fare un test per un concorso di questions ne avrò
    100 e via dicendo).
    Da parte mia avrei buttato giù questo primo pseudo abozzo
    di E/R.

    --GAMES_CATEGORY(game_category_id,game_category_titl e-PK game_category_id)(Esempio schedina)
    --GAMES(game_category_id,game_id,game_title-FK (game_category_id),PK (game_id))(Esempio 1°Giornata)
    --GAME_LEGEND(game_legend_id,game_category_id,game_l egend_flag-FK (game_category_id),PK(game_category_id,game_legend _id))(Esempio 1,X,2)
    --QUESTIONS (game_id,question_id,question_content,answer_flag-FK (game_id),PK (game_id question_id))(Esempio Atalanta-Genoa X)
    --SHOW_GAME(game_category_id,game_id)(da gestire con UPDATE)
    In questo modo ad una prima occhiata mi sembra
    di aver risolto il mio problema.


    Fammi sapere.


    Ah se non c'entra niente col tuo problema
    scusa l'intromissione.





    Without faith, nothing is possible. With it, nothing is impossible
    http://ilwebdifabio.it

  4. #4

    Re: .............

    Originariamente inviato da whisher
    Ah se non c'entra niente col tuo problema
    scusa l'intromissione.
    Non saprei, non ho ben chiaro il funzionamento della tua struttura e quindi non ci vedo il nesso, ma magari c'è.

  5. #5

    ........

    Ciao.
    Tanto per essere + chiari e sparare
    la prima della giornata:
    --PRODUCTS_CATEGORY(product_category_id,product_cate gory_name-PK product_category_id)(Esempio LIBRO)
    --PRODUCTS(product_id,product_category_id,product_sp ecial_purpose-FK (product_category_id),PK (product_id,product_category_id))(Esempio in product_special_purpose ISBN)
    --PRODUCTS_PRODUCT(product_product_id,product_produc t_title,product_product_description--FK (product_id,product_category_id),PK(product_produc t_id))
    Praticamente estendi la tabella (sommando le varie proprietà specifiche)
    un po come in OOP.
    Ecco l'ho detta

    Without faith, nothing is possible. With it, nothing is impossible
    http://ilwebdifabio.it

  6. #6
    Utente di HTML.it L'avatar di luca200
    Registrato dal
    Apr 2002
    Messaggi
    4,120

    Re: [MySQL] Campi personalizzabili dall'utente

    Originariamente inviato da skidx
    Io ho realizzato un'applicazione che faceva una cosa del genere.
    Visto che ci sono svantaggi in entrambe le soluzioni, io ho pensato bene di adottarle entrambe
    Ovvero: tengo il campo nella tabella, per cui effettuo l'ALTER TABLE nel momento in cui viene creato; allo stesso tempo però mantengo una tabella a parte con una riga per campo. Questo mi era reso indispensabile dal fatto che dovevo gestire una sorta di browsing ridotto sui record che mostrasse solo alcuni campi, e dovevo dare all'utente la possibilità di scegliere questi campi. Quindi non potevo fare a meno di una tabella campi, ma allo stesso momento non ritenevo accettabile utilizzare una tabella generica 'campo'-'valore' per i valori (a questo proposito però si potrebbe considerare l'alternativa di una tabella per ogni campo, sebbene questo reintroduca in qualche modo il problema di effettuare delle CREATE TABLE a livello applicativo)

    Per quanto riguarda le tue obiezioni sull'ALTER TABLE, ti faccio notare che in ogni caso a livello applicativo è un'operazione che verrà eseguita molto raramente. L'utente non cambia i campi ogni tre per due.

    Spero che si sia capito qualcosa...


  7. #7
    Sì, luca, ho capito perfettamente.

    Il problema non è tanto un CREATE TABLE, che al limite aggiunge ma non leva nulla, il problema è proprio l'ALTER TABLE, che è rischioso in quanto c'è un momento in cui entrambe le tabelle (la vecchia e la nuova) vengono rinominate con nomi provvisori.

    Non dovrà essere eseguito spesso, ma se lo devi eseguire una volta su una tabella da qualche centinaia di migliaia di record e quella volta va male, l'hai già presa nel baugigi a sufficienza

    Comunque ho pensato una soluzione alternativa, ora la elaboro per bene e poi la posto.

  8. #8
    dunque, anche se non ancora raffinata la posto, così magari potete darmi dei pareri.

    Il problema del ALTER TABLE, come già detto, è la possibilità di restare appiedati (senza tabella funzionante) a metà dell'opera, oltre alla possibile eccessiva lentezza dell'operazione (la tabella iniziale può restare in LOCK molto a lungo)
    Dunque io ho pensato questa variante:
    1) tenere i campi custom in un'altra tabella in relazione 1:1 con la principale.
    2) all'aggiunta di un campo custom avviene questo:

    - viene CREATA un'altra tabella per campi custom uguale alla precedente ma con l'aggiunta del nuovo campo. Se l'azione fallisce non succede niente, l'altra tabella non è stata toccata.

    - per evitare la copia dell'intera tabella tutta assieme (che potrebbe essere molto lunga), si copiano i dati dalla vecchia custom alla nuova a gruppi di N elementi, ogni copia di gruppo dentro una propria transazione, e contestualmente si segna i record della vecchia tabella (in un apposito flag obsolete) come obsoleti.

    - nel frattempo per accedere sempre ai dati più recenti si può usare una query del tipo
    (SELECT campo1, campo2, campoN from custom1 WHERE obsolete = 0) UNION (SELECT campo1, campo2, campoN from custom2 WHERE obsolete = 0)
    ottenendo così il record della vecchia tabella se ancora non è staco copiato sulla nuova, o della nuova se è già stato copiato.

    - A fine copia, si cancella la vecchia tabella.

    Il tutto per funzionare necessita di un meccanismo (per esempio un record di appoggio) dove tener traccia del nome "dinamico" della tabella custom e delle varie fasi dell'operazione sopra descritta.

    E' un po' macchinoso, ma mi sembra che risolva i problemi del metodo ALTER TABLE, che ne pensate?

  9. #9
    Utente di HTML.it L'avatar di luca200
    Registrato dal
    Apr 2002
    Messaggi
    4,120
    Mi sembra NOTEVOLMENTE macchinoso il marchingegno delle query con UNION sulle tabelle dinamiche... anche perché se non sbaglio dovresti utilizzarlo ad ogni accesso. Probabilmente mi sfugge qualcosa... come fai ad accorgerti quando è in corso un "travaso"?

  10. #10
    Originariamente inviato da luca200
    Mi sembra NOTEVOLMENTE macchinoso il marchingegno delle query con UNION sulle tabelle dinamiche... anche perché se non sbaglio dovresti utilizzarlo ad ogni accesso. Probabilmente mi sfugge qualcosa... come fai ad accorgerti quando è in corso un "travaso"?
    E' quello a cui mi riferivo quando ho detto che serve un record di appoggio.
    In pratica a inizio operazione bisogna segnare da qualche parte "sto modificando la tabella custom, la vecchia si chiama custom455 e la nuova custom456".

    A fine operazione poi si aggiornerebbe tale record con il nome della nuova tabella.

    Questo accesso macchinoso sarebbe comunque necessario solo se voglio permettere agli altri client connessi in quel momento di poter continuare a scrivere su quei record.
    Se i miei dati sono prevalentemente in lettura posso anche fare la scelta di bloccare la tabella in sola lettura per tutto il corso dell'operazione, senza bisogno di usare union e flag vari.

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.