Pagina 1 di 2 1 2 ultimoultimo
Visualizzazione dei risultati da 1 a 10 su 13

Discussione: [mysql] view dinamica

  1. #1

    [mysql] view dinamica

    ciao a tutti, rieccomi a sottoporvi un interessante quesito per un nuovo database su cui devo mettere le mani per costruire delle view "dinamiche" e normalizzate per la visualizzazione dei dati presenti nelle mie tabelline delle lingue.

    la struttura di base da cui prelevare i dati è questa


    codice:
    delimiter $$
    
    CREATE TABLE `lingue` (
      `idlingue` int(11) NOT NULL AUTO_INCREMENT,
      `idbk_utenti` int(11) NOT NULL,
      `alfa3` varchar(3) DEFAULT NULL,
      `default` enum('on','off') DEFAULT 'off',
      `status` enum('on','off') DEFAULT 'on',
      `alfa2` varchar(2) DEFAULT NULL,
      PRIMARY KEY (`idlingue`),
      KEY `fk_lingue_bk_utenti1` (`idbk_utenti`),
      CONSTRAINT `fk_lingue_bk_utenti1` FOREIGN KEY (`idbk_utenti`) REFERENCES `bk_utenti` (`idbk_utenti`) ON DELETE NO ACTION ON UPDATE NO ACTION
    ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=big5$$
    
    
    
    delimiter $$
    
    CREATE TABLE `lingue_contenuti` (
      `idlingue_contenuti` int(11) NOT NULL AUTO_INCREMENT,
      `idlingue` int(11) NOT NULL,
      `idriferimento` int(11) DEFAULT NULL,
      `tabellariferimento` varchar(255) DEFAULT NULL,
      `testo` varchar(65000) DEFAULT NULL,
      `tipologia` enum('testo','etichetta') DEFAULT 'testo',
      `status` enum('on','off') DEFAULT 'on',
      PRIMARY KEY (`idlingue_contenuti`),
      KEY `fk_lingue_contenuti_lingue1` (`idlingue`),
      CONSTRAINT `fk_lingue_contenuti_lingue1` FOREIGN KEY (`idlingue`) REFERENCES `lingue` (`idlingue`) ON DELETE NO ACTION ON UPDATE NO ACTION
    ) ENGINE=InnoDB AUTO_INCREMENT=30 DEFAULT CHARSET=latin1$$

    nella tabella lingue vengono definite le lingue, mentre in lingue contenuti vengono definiti i nomi estesi delle lingue in ogni lingua.
    esempio:

    codice:
     tab lingue 
    
    idlingue | idbk_utenti | alfa3 | default | status | alfa2
    ------- |------------|------|--------|-------|-------
    1         | 1              | ita    | on       | on      | it
    2         | 1              | eng   | off       | on      | en
    
    
    tab lingue_contenuti 
    
    idlingue_contenuti | idlingue      | idriferimento | tabellariferimento| testo  | tipologia | status
    ------------------|------------|-------------|-----------------|--------|---------|-------
    1                        | 1              | 1               | lingue               | italiano | testo     | on
    2                        | 1              | 2               | lingue               | inglese  | testo     | on
    3                        | 2              | 1               | lingue               | italian   | testo     | on
    4                        | 2              | 2               | lingue               | english  | testo     | on
    lo scopo è di arrivare ad avere una vista normalizzata per la quale per ogni lingua definita ho tutti i dettagli della lingua

    esempio (con i dati di cui sopra):

    codice:
     view lingue 
    
    idlingue | idbk_utenti | alfa3 | default | status | alfa2 | testoITA | testoENG
                                                         (lingue)
    ------- |------------|------|--------|-------|-------|---------|------------
    1         | 1              | ita    | on       | on      | it       | italiano  | italian
    2         | 1              | eng   | off       | on      | en     | inglese   | english
    oltre a questo, essendo lingue e contenuti aggiornabili da parte dell'amministratore del sito la view dovrebbe aggiornarsi nel tempo per cui se vado ad aggiungere la lingua francese si aggiungerà non solo la riga per la nuova lingua ma anche la colonna del testoFRA nella view.

    a livello teorico dovrebbe essere possibile, però dopo anni di assoluta non curanza del codice, non so se
    1) sia davvero possibile farlo
    2) come farlo

    ergo chiedo una zampa a chi ha maggiore esperienza in questo campo per avere alemno qualche dritta in merito così da poter delegare a mysql tutto lo sforzo di gestione della view così da doverla poi solo interrogare (questo in vista del fatto che dovrò crearne altre per un sacco di altre parti del gestionale in costruzione)

    per ora grazie dell'interessamento e dell'aiuto!

    lamechian


    PS
    non ho postato la tabella utenti che al momento non è fondamentale in quanto per i fini della view da sviluppare potrebbe contenere anche il solo idbk_utenti.

  2. #2
    Utente di HTML.it L'avatar di nicola75ss
    Registrato dal
    Nov 2004
    Messaggi
    12,923
    Ti posto un esempio che grosso modo dovrebbe ricalcare il tuo problema sperando ti sia utile.

    codice:
    create table lingue (
    id int not null auto_increment primary key,
    lingua varchar(10)
    ) engine = innodb;
    
    create table articoli (
    id int not null auto_increment primary key,
    id_articolo int,
    id_lingua int,
    testo varchar(50),
    foreign key (id_lingua) references lingue(id) on delete cascade
    ) engine = innodb;
    
    insert into lingue (lingua) values ('ita'),('fra'),('eng');
    
    insert into articoli (id_articolo,id_lingua,testo)
    values
    (1,1,'testo1_ita'),
    (1,3,'testo1_eng'),
    (2,2,'testo2_fra'),
    (3,2,'testo3_fra'),
    (3,3,'testo3_eng');
    La query "statica" sarebbe questa:

    codice:
    select a.id_articolo,
    max(case when id_lingua = 1 then testo else '' end) as testo_ita,
    max(case when id_lingua = 2 then testo else '' end) as testo_fra,
    max(case when id_lingua = 3 then testo else '' end) as testo_eng
    from lingue as l
    left join articoli as a
    on l.id = a.id_articolo
    group by a.id_articolo;
    che produrrebbe questo risultato:

    codice:
    +-------------+------------+------------+------------+
    | id_articolo | testo_ita  | testo_fra  | testo_eng  |
    +-------------+------------+------------+------------+
    |           1 | testo1_ita |            | testo1_eng |
    |           2 |            | testo2_fra |            |
    |           3 |            | testo3_fra | testo3_eng |
    +-------------+------------+------------+------------+
    La stored procedure per rendere la query dinamica è così:

    codice:
    delimiter //
    drop procedure if exists query_dinamica//
    create procedure query_dinamica()
    begin
    declare finito int default 0;
    declare cid int;
    declare clingua varchar(10);
    declare str varchar(10000) default "select a.id_articolo,";
    declare cursore cursor for select id,lingua from lingue;
    declare continue handler for not found set finito = 1;
    open cursore;
    mio_loop:loop
    fetch cursore into cid,clingua;
    if finito = 1 then
    leave mio_loop;
    end if;
    set str = concat(str, "max(case when id_lingua = ",cid," then testo else '' end) as testo_",clingua,",");
    end loop;
    close cursore;
    set str = substr(str,1,char_length(str)-1);
    set @str = concat(str," from lingue as l
    		       left join articoli as a
    		       on l.id = a.id_articolo
    		       group by a.id_articolo");
    
    prepare stmt from @str;
    execute stmt;
    deallocate prepare stmt;
    -- select str;
    end;//
    delimiter ;
    che richiamata produce lo stesso output della query statica.
    Proviamo ad aggiungere una nuova lingua e un paio di record:

    codice:
    insert into lingue (lingua) values ('ted');
    insert into articoli (id_articolo,id_lingua,testo) values (4,1,'testo4_ita'),(4,4,'testo4_ted');
    e a richiamare la sp:
    codice:
    mysql> call query_dinamica;
    +-------------+------------+------------+------------+------------+
    | id_articolo | testo_ita  | testo_fra  | testo_eng  | testo_ted  |
    +-------------+------------+------------+------------+------------+
    |           1 | testo1_ita |            | testo1_eng |            |
    |           2 |            | testo2_fra |            |            |
    |           3 |            | testo3_fra | testo3_eng |            |
    |           4 | testo4_ita |            |            | testo4_ted |
    +-------------+------------+------------+------------+------------+
    Infine, proviamo a cancellare una lingua e, di conseguenza, i record annessi.

    codice:
    mysql> delete from lingue where lingua = 'fra';
    Query OK, 1 row affected (0.00 sec)
    
    mysql> call query_dinamica;
    +-------------+------------+------------+------------+
    | id_articolo | testo_ita  | testo_eng  | testo_ted  |
    +-------------+------------+------------+------------+
    |           1 | testo1_ita | testo1_eng |            |
    |           3 |            | testo3_eng |            |
    |           4 | testo4_ita |            | testo4_ted |
    +-------------+------------+------------+------------+
    Ciao.

  3. #3
    ciao, innanzitutto grazie dell'aiuto, però provando il tuo codice di esempio (soluzione interessante sulla quale misto docuemntando non avendo mai lavoratomolto con le routine) ottengo questo risultato invocando la procedura:

    codice:
    PROCEDURE test.query_dinamica can't return a result set in the given context
    sneceramente non saprei nemmeno dove sbattere la testa non avendo ne teoria (mi sto procurando un po di documentazione sullo sviluppo slq con procedure ecc) ne epserienza (è la prima volta chemi confronto con una cosa simile) in merito..

  4. #4
    Utente di HTML.it L'avatar di nicola75ss
    Registrato dal
    Nov 2004
    Messaggi
    12,923
    In che contesto ti viene restituito quell'errore?

  5. #5
    Originariamente inviato da nicola75ss
    In che contesto ti viene restituito quell'errore?
    l'errore è restituito da mysql_error() dopo l'esecuzione da script perchè testando da phpmyadmin non vedo errori e mi ributta sulla selezione del DB.. purtroppo non ho accesso alla console mysql per testare li e quindi devo un po arrangiarmi con i mezzi disponibili..

  6. #6
    Utente di HTML.it L'avatar di nicola75ss
    Registrato dal
    Nov 2004
    Messaggi
    12,923
    Pare un problema di versione di php.
    Prova a dare uno sguardo qui

    http://stackoverflow.com/questions/1...-given-context

  7. #7
    Originariamente inviato da lamechian
    l'errore è restituito da mysql_error() dopo l'esecuzione da script perchè testando da phpmyadmin non vedo errori e mi ributta sulla selezione del DB.. purtroppo non ho accesso alla console mysql per testare li e quindi devo un po arrangiarmi con i mezzi disponibili..
    ok, mentre attendo l'aggiornamento del server (attualmente con php 5.3.1, che verrà upgradato a php 5.3.5 o 5.3.6 non so bene) sto testando da mysqlworkbrench e invocando la procedura ottengo il risultato voluto.

    ora devo solo adattare il tuo esempio alla mia situazione e poi sperare che php collabori e dia un risultato nell'invocazione della procedura una volta definita :P

    per ora grazie 100000, casomai ti chiederò ancora qualche consiglio se mi inciabatto su qualcosa in fase realizzativa :P

  8. #8
    Utente di HTML.it L'avatar di nicola75ss
    Registrato dal
    Nov 2004
    Messaggi
    12,923
    Originariamente inviato da lamechian
    per ora grazie 100000, casomai ti chiederò ancora qualche consiglio se mi inciabatto su qualcosa in fase realizzativa :P
    Il grosso del lavoro è già fatto. Crea la query statica e poi rendi dinamico il max(case ... tramite la sp.
    Solo una precisazione sullla query. C'era un errore di base (svista mia ) nel caso ci fossero lingue a cui non corrisponde alcun articolo.

    codice:
    select a.id_articolo,
    max(case when id_lingua = 1 then testo else '' end) as testo_ita,
    max(case when id_lingua = 2 then testo else '' end) as testo_fra,
    max(case when id_lingua = 3 then testo else '' end) as testo_eng
    from lingue as l
    left join articoli as a
    on l.id = a.id_articolo
    where a.id_articolo is not null
    group by a.id_articolo;
    Integra la riga nella sp. Se hai problemi chiedi pure.

  9. #9
    primo piccolo passo verso il risultato finale:

    codice:
    SELECT 
    	l.idlingue,l.idbk_utenti,l.alfa3,l.`default`,
    	max(case when lc.idlingue = 1 then testo else '' end) as testo_ita,
    	max(case when lc.idlingue = 2 then testo else '' end) as testo_eng,
    	max(case when lc.idlingue = 3 then testo else '' end) as testo_fra
    FROM 
    	lingue l JOIN lingue_contenuti lc ON l.idlingue = lc.idlingue
    WHERE
    	lc.tabellariferimento = 'lingue' AND
    	l.status = 'on' AND
    	lc.status = 'on'
    GROUP BY
    	lc.idriferimento
    estrae i dati che mi servono come mi servono ora si passa alla SP per le lingue e poi a tutte le altre..

  10. #10
    ok, ora funziona davvero...

    codice:
    delimiter //
    	drop procedure if exists query_lingue//
    	create procedure query_lingue()
    	begin
    	
    		declare finito int default 0;
    		declare cidlingue int;
    		declare calfa3 varchar(3);
    		
    		declare str varchar(10000) default "SELECT 
    	l.idlingue,l.idbk_utenti,l.alfa3,l.`default`,";
    		
    		declare cursore cursor for select idlingue,alfa3 from lingue;
    		declare continue handler for not found set finito = 1;
    
    		open cursore;
    			mio_loop:loop
    				fetch cursore into cidlingue,calfa3;
    				if finito = 1 then
    					leave mio_loop;
    				end if;
    				set str = concat(str, "max(case when lc.idlingue = ",cidlingue," then testo else '' end) as testo_",calfa3,",");
    			end loop;
    		close cursore;
    		set str = substr(str,1,char_length(str)-1);
    		set @str = concat(str," FROM 
    				lingue l JOIN lingue_contenuti lc ON l.idlingue = lc.idriferimento
    			WHERE
    				lc.tabellariferimento = 'lingue' AND
    				l.status = 'on' AND
    				lc.status = 'on'
    			GROUP BY
    				lc.idriferimento");
    
    		prepare stmt from @str;
    		execute stmt;
    		deallocate prepare stmt;
    		-- select str;
    
    	end;//
    delimiter ;
    ora mi resta solo una domanda.. posso usarla per creare uan view da poter interrogare per selezionare una lingua specifica o robe simili?

    ri grazie!

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.