Autore Topic: [Risolto] rinominare tabella SQlite3 da programma  (Letto 3741 volte)

Offline leo72

  • Amministratore
  • Senatore Gambero
  • *****
  • Post: 2.163
    • Mostra profilo
    • http://www.leonardomiliani.com
Re: rinominare tabella SQlite3 da programma
« Risposta #15 il: 31 Marzo 2010, 23:49:56 »
Replico solo perché alle volte uno sterile messaggio di testo non riporta bene il concetto che uno vorrebbe esprimere, non per fare sterile polemica.

fsurfing ha espresso molto meglio di me ciò che è successo e cioè che io pensavo ti fossi arenato di fronte al classico errore banalissimo che, proprio perché banale, è l'ultimo della lista degli indiziati.

Con questo anch'io chiudo perché questa comunità è bella proprio perché siamo molto uniti e legati, avendo fatto un percorso comune che, nel giro di 2 anni, ci ha portato ad essere forse il gruppo organizzato di utenti Gambas più numeroso, competente ed organizzato che c'è.

Archivio questa discussione come il classico "attrito" che c'è anche nelle migliori famiglie ma che, come nelle migliori famiglie, si chiarisce sempre discutendo schiettamente.
Visita il mio sito personale: http://www.leonardomiliani.com

Offline Picavbg

  • Senatore Gambero
  • ******
  • Post: 1.620
    • Mostra profilo
Re: rinominare tabella SQlite3 da programma
« Risposta #16 il: 01 Aprile 2010, 00:10:14 »
facci sapere quando risolvi ciao ciao
Per la verità, praticamente ho superato l'ostacolo seguendo il tuo consiglio, cioè:
Codice: [Seleziona]
$_TbRiord2 = "TabellaTransito" 
CreTabDb = NEW CreaTabDb($_TbRiord2)       'classe di creazione di tutte le tabelle del DB o singolarmente in base al nome contenuto in $_TbRiord2
RecTab = DB_Connection.Edit("TabellaOriginaria")     
RecTab = DB_Connection.Exec("SELECT * FROM TabellaOriginaria ORDER BY NumVoce")
i_id = 0
  FOR EACH RecTab
      i_id += 1
      DB_Connection.EXEC("INSERT INTO TabellaTransito VALUES(" & i_id & ", '" & RecTab!NumVoce & "', '" & RecTab!NomeVoce & "', '" & RecTab!ContrPartSiNo & "', '" & RecTab!DtPrimoUso & "')")
  NEXT
DB_Connection.Commit
  DB_Connection.Close
  WITH
      DB_Connection
      .Type = "sqlite3"
      .Host = VarGlob.$_DbPath
      .Name = VarGlob.$_DbNome
      .OPEN    'Apro il DB
  END WITH
 DB_Connection.EXEC("DELETE FROM TabellaOriginaria")        'Cancellazione del contenuto della "TabellaOriginaria"
    DB_Connection.Commit
    DB_Connection.Close
    WITH
      DB_Connection
      .Type = "sqlite3"
      .Host = VarGlob.$_DbPath
      .Name = VarGlob.$_DbNome
      .OPEN    'Apro il DB
    END WITH
    RecTab = DB_Connection.Edit("TabellaTransito")
    RecTab = DB_Connection.Exec("SELECT * FROM TabellaTransito ORDER BY NumVoce")
    i_id = 0
    FOR EACH RecTab
      i_id += 1
      TRY DB_Connection.EXEC("INSERT INTO TabellaOriginaria VALUES(" & i_id & ", '" & RecTab!NumVoce & "', '" & RecTab!NomeVoce & "', '" & RecTab!ContrPartSiNo & "', '" & RecTab!DtPrimoUso & "')")
    NEXT
    DB_Connection.Commit
    DB_Connection.Close
 WITH
      DB_Connection
      .Type = "sqlite3"
      .Host = VarGlob.$_DbPath
      .Name = VarGlob.$_DbNome
      .OPEN    'Apro il DB
    END WITH
 DB_Connection.EXEC("DROP TABLE TabellaTransito")
Certo il tempo di esecuzione si raddoppia, e si nota, ma funziona benissimo. Ho adottato la soluzione ancora prima di leggere il primo suggerimento di milio, poi ho voluto riprendere la prova perchè speravo che l'istruzione
Codice: [Seleziona]
Sql = "CREATE TABLE TabellaTransito AS SELECT * FROM TabellaOriginaria ORDER BY NumVoce;"
DB_Connection.Exec(Sql)
, molto accattivante, di milio potesse aiutarmi a ritornare alla prima soluzione (ALTER TABLE). Purtroppo la prova non sembra funzionare.

@ milio:
Nella mia tabella, la colonna indicata dopo l'ORDER BY è NumVoce, solo che nel ripetere il codice da allegare al mio messaggio ho dimenticato di sostituire il tuo nome campo col mio; però tutto sommato, penso che abbia poca importanza (i miei nomi campo non sono molto facili da ricordare, mi rendo conto).
Ho colto il tuo invito. Domani, spero di trovare il tempo di fare la prova che dici e che già avevo capito di fare leggendo il tuo esempio  di partenza, ma che avevo sostituito con la "print RecTab.Max" perchè in debug avevo notato che la "CREATE TABLE ... ORDER BY" aveva, almeno apparentemente, creato una tabella vuota (da Sqliteman).

@ Leo:
Proprio come dici tu; Il bello di una famiglia aperta al dialogo è il ritorno del sereno dopo la tempesta.

Ciao a tutti.
« Ultima modifica: 01 Aprile 2010, 00:16:42 da Picavbg »
:ciao:

Offline Picavbg

  • Senatore Gambero
  • ******
  • Post: 1.620
    • Mostra profilo
Re: rinominare tabella SQlite3 da programma
« Risposta #17 il: 01 Aprile 2010, 09:55:25 »
@ milio:
Ho eseguito la prova come mi hai proposto, ma relativamente ad una tabella di soli tre record; per la print non ho usato una textarea, ma una semplice FOR EACH, print. Purtroppo non ha funzionato.
Codice: [Seleziona]
Sql = "CREATE TABLE causalifreq2 AS SELECT * FROM causalifreq ORDER BY id;"
  DB_Connection.Exec(Sql)
  DB_Connection.Commit
  DB_Connection.Close
  WITH
      DB_Connection
      .Type = "sqlite3"
      .Host = VarGlob.$_DbPath
      .Name = VarGlob.$_DbNome
      .OPEN    'Apro il DB
  END WITH
  IF DB_Connection.Tables.Exist("causalifreq2") THEN
    Sql = "SELECT * FROM causalifreq2;"
    RecTab = DB_Connection.Exec(Sql)
    FOR i_id = 0 TO RecTab.Max
    NEXT
   PRINT i_id
 ENDIF
 ' cancello la tabella di origine
 Sql = "DROP TABLE causalifreq"
 DB_Connection.Exec(Sql)
 ' Rinomino la tabella di transito
 Sql = "ALTER TABLE 'causalifreq2' RENAME TO 'causalifreq';"
 DB_Connection.Exec(Sql)
 DB_Connection.Commit
 DB_Connection.Close
  WITH
      DB_Connection
      .Type = "sqlite3"
      .Host = VarGlob.$_DbPath
      .Name = VarGlob.$_DbNome
      .OPEN    'Apro il DB
  END WITH
  IF DB_Connection.Tables.Exist("causalifreq") THEN
    Sql = "SELECT * FROM causalifreq;"
    RecTab = DB_Connection.Exec(Sql)
    FOR i_id = 0 TO RecTab.Max
     
    NEXT
    PRINT i_id
    RecTab = DB_Connection.Edit("causalifreq")
    FOR EACH RecTab
       PRINT "id= " & RecTab!id, "RecTab!DescrCausFreq= " & RecTab!DescrCausFreq, "RecTab!DtUltCausFreq= " & RecTab!DtUltCausFreq
    NEXT
  ELSE
    PRINT "La Tabella 'causalifreq' non esiste"
  ENDIF

l'istruzione
Codice: [Seleziona]
 RecTab = DB_Connection.Edit("causalifreq")
produce l'errore
"Table 'caualifreq' has no priimary key
Penso proprio che per me e per il mio ambiente la strada "ALTER TABLE" non sia percorribile.
Ciao.
:ciao:

Offline milio

  • Senatore Gambero
  • ******
  • Post: 1.273
  • Chi parla poco dice tanto...
    • Mostra profilo
Re: rinominare tabella SQlite3 da programma
« Risposta #18 il: 01 Aprile 2010, 16:39:48 »
e se fai in questo modo?

Codice: [Seleziona]
    Sql = "CREATE TABLE nometabellatransito AS SELECT id, cassa, entrate, uscite FROM nometabellaorigine ORDER BY cassa;"
  conn.Exec(Sql)

  Sql = "DROP TABLE nometabellaorigine"
  conn.Exec(Sql)

  Sql = "CREATE TABLE nometabellaorigine AS SELECT id, cassa, entrate, uscite FROM nometabellatransito;"
  conn.Exec(Sql)

  Sql = "DROP TABLE nometabellatransito"
  conn.Exec(Sql)

devi specificare ogni singolo campo nella select perche' ho visto che se metti * rinomina il campo in nometabella.nomecampo

Offline Picavbg

  • Senatore Gambero
  • ******
  • Post: 1.620
    • Mostra profilo
Re: rinominare tabella SQlite3 da programma
« Risposta #19 il: 01 Aprile 2010, 23:46:58 »
e se fai in questo modo?
Codice: [Seleziona]
    Sql = "CREATE TABLE nometabellatransito AS SELECT id, cassa, entrate, uscite FROM nometabellaorigine ORDER BY cassa;"
  conn.Exec(Sql)
  Sql = "DROP TABLE nometabellaorigine"
  conn.Exec(Sql)
  Sql = "CREATE TABLE nometabellaorigine AS SELECT id, cassa, entrate, uscite FROM nometabellatransito;"
  conn.Exec(Sql)
  Sql = "DROP TABLE nometabellatransito"
  conn.Exec(Sql)
devi specificare ogni singolo campo nella select perche' ho visto che se metti * rinomina il campo in nometabella.nomecampo
Grazie per il suggerimento. Ma dove hai letto tutto qello che hai imparato? Ho visto che usi istruzioni che io non ho mai incontrato prima. Complimenti !!! :D
Allora; quasi non ci credo, ma penso proprio che mi hai acceso la lampadina giusta.  Solo che dell'ultimo codice da te suggerito, a causa della mia testardaggine, ho modificato ho preso solo una parte, lasciando per il resto quello usato nella prova precedente. Riporto qui di seguiito solo le istruzioni salienti, trascurando tutti i passi di Open, Commit  e Close.
Codice: [Seleziona]
Sql = "CREATE TABLE nometabellatransito AS SELECT id, Campo1, Campo2 FROM nometabellaorigine ORDER BY Campo1;"
 DB_Connection.Exec(Sql)

  IF DB_Connection.Tables.Exist("nometabellatransito") THEN
    Sql = "SELECT * FROM nometabellatransito;"
    RecTab = DB_Connection.Exec(Sql)
    FOR EACH RecTab
       PRINT "id= " & RecTab!id, "RecTab!Campo1= " & RecTab!Campo1, "RecTab!Campo2= " & RecTab!Campo2
    NEXT
   ENDIF

  Sql = "DROP TABLE nometabellaorigine"
 DB_Connection.Exec(Sql)

 Sql = "ALTER TABLE 'nometabellatransito' RENAME TO 'nometabellaorigine';"
 DB_Connection.Exec(Sql)
 '--- wwwwwwwwwwwwwwwwwww -------------------- HA FUNZIONATO: la tabella presenta tutto il suo contenuto anche con Sqliteman ----------------------
  IF DB_Connection.Tables.Exist("nometabellaorigine") THEN
    Sql = "SELECT * FROM causalifreq;"
    RecTab = DB_Connection.Exec(Sql)
   
    Sql = "SELECT * FROM nometabellaorigine;"
    RecTab = DB_Connection.Exec(Sql)
'--------------------------- qui ho dovuto sostituire l'istruzione  --> RecTab2 = DB_Connection.Edit("nometabellaorigine")  <-- perchè dava l'errore: ...' has no primary key.
   
    FOR EACH RecTab
       PRINT "id= " & RecTab!id, "RecTab!Campo1= " & RecTab!Campo1, "RecTab!Campo2= " & RecTab!Campo2
    NEXT
Tutte e due le funzioni di stampa hanno riportato le righe presenti effettivamente in tabella. Non solo, ho verificato anche con Sqliteman e ...
la tabella è completa con tutte le sue righe, per cui, ..... finalmente ... ALTER TABLE ha funzionato
 :D ;D
Ma solo perchè ... hai insistito.
Non capisco perchè la .Edit non ha voluto più funzionare.
Ciao.
:ciao:

Offline Picavbg

  • Senatore Gambero
  • ******
  • Post: 1.620
    • Mostra profilo
Re: rinominare tabella SQlite3 da programma
« Risposta #20 il: 02 Aprile 2010, 23:28:49 »
@ milio:
Ho cantato vittoria troppo presto. Infatti tutte le istruzioni
Codice: [Seleziona]
RecTab = DB_Connection.Edit("NomeTabella")
che hanno riferite alla tabella interessata dall'ALTER TABLE, producono l'errore
Citazione
"Table 'NomeTabella' has no priimary key
Ho guardato in Sqliteman->Contesto->Descrivi tabella, prima e dopo l'ALTER TABLE, ed ecco la differenza:
Citazione
Prima dell'istruzione ALTER TABLE:
-- Descrizione CAUSALIFREQ
Codice: [Seleziona]
CREATE TABLE 'causalifreq'('id' INTEGER PRIMARY KEY AUTOINCREMENT, 'DescrCausFreq' VARCHAR(100), 'DtUltCausFreq' INTEGER )

Dopo l'istruzione ALTER TABLE:
Codice: [Seleziona]
-- Descrizione CAUSALIFREQ
CREATE TABLE "causalifreq"(
  id INT,
  DescrCausFreq TEXT,
  DtUltCausFreq INT
)
Come vedi non esiste più la definizione INTEGER PRIMARY KEY AUTOINCREMENT per l'id e non esistono più datatype relativi alle colonne.
 :( :(
Ciao.
:ciao:

Offline milio

  • Senatore Gambero
  • ******
  • Post: 1.273
  • Chi parla poco dice tanto...
    • Mostra profilo
Re: rinominare tabella SQlite3 da programma
« Risposta #21 il: 03 Aprile 2010, 10:05:22 »
Si ho visto anche io (finalmente dirai tu ;) ) che si pianta casino con l'Alter Table... allora mi sono chiesto: come fa sqliteman a rinominare la tabella?

Prova a fare:

Selezioni una tabella.
Tasto destro del mouse - Modifica Tabella
Nella box Nome Tabella modifica il nome della tabella
Clicca su Esegui Alter
Guarda cosa succede nella finestra del log!

Offline Picavbg

  • Senatore Gambero
  • ******
  • Post: 1.620
    • Mostra profilo
Re: rinominare tabella SQlite3 da programma
« Risposta #22 il: 04 Aprile 2010, 10:31:09 »
@ milio:
Spero di avere capito il tuo riferimento alla finestra di log.

Ho segutio passo passo la tua indicazione per alterare a manina il nome di una tabella del mio DB; ho scelto la tabella "causalifreq"  . Riporto qui oltre al contenuto della relativa finestra di log, anche la descrizione, prima e dopo il processo di alterazione.
Citazione
-- Descrizione CAUSALIFREQ   (prima di ALTER):
CREATE TABLE "causalifreq2"('id' INTEGER PRIMARY KEY AUTOINCREMENT, 'DescrCausFreq' VARCHAR(100), 'DtUltCausFreq' INTEGER )

--Contenuto della finestra di log, in Sqliteman:
Renaming the table "causalifreq" to "causalifreq2".
Rinomino la tabella originale in _alter0_causalifreq2
Sto per creare una nuova Tabella: causalifreq2
Inizio la Transazione
Trasferimento Dati
Chiudo la Transazione
Elimino la tabella originale _alter0_causalifreq2
Alter Table Eseguito

-- Descrizione CAUSALIFREQ    (dopo di ALTER):
CREATE TABLE causalifreq2 (
    "id" INTEGER,
    "DescrCausFreq" VARCHAR(100),
    "DtUltCausFreq" INTEGER
)
Come si vede, Sqliteman, pur modificando qualcosa nella descrizione, si comporta bene: il comando ALTER ha funzionato perfettamente; ciascuna colonna ha mantenuto il suo datatype corretto. Ho guardato  la tabella  ed ho constatato che ha mantenuto tutte le sue righe; poi ho rieseguito il programma ed esso non ha prodotto alcun errore sull'istruzione:
Codice: [Seleziona]
RecTab = DB_Connection.edit($_NomeTab) 

Però devo aggiungere che in Sqliteman esiste un altro percorso per rinominare una tabella. Esso  è quello eseguito da me, per provare il mio prgramma, prima di conoscere la funzione ALTER. La funzione non utilizza tabelle di transito, ma cambia solamente il nome della tabella e, pertanto, non modifica la parte descrittiva della tabella. Ciò si vede dal seguente percorso:
Citazione
-- Descrizione CAUSALIFREQ (prima di Rinomina la tabella):
Codice: [Seleziona]
CREATE TABLE 'causalifreq'('id' INTEGER PRIMARY KEY AUTOINCREMENT, 'DescrCausFreq' VARCHAR(100), 'DtUltCausFreq' INTEGER )

Ho seleziono la tabella
Tasto destro del mouse - Rinomina la Tabella;
Nella box Nuovo Nome della Tabella, ho modificato il nome della tabella
ho cliccato su OK.
Non c'è finestra di log

-- Descrizione CAUSALIFREQ1  (dopo avere rinominato la tabella):
Codice: [Seleziona]
CREATE TABLE "causalifreq1"('id' INTEGER PRIMARY KEY AUTOINCREMENT, 'DescrCausFreq' VARCHAR(100), 'DtUltCausFreq' INTEGER )

Dal confronto delle due descrizioni, prima e dopo avere rinominatio la tabella, si rileva la perfetta corrispondenza di tutti i caratteri. Però, non mi pare che esista un'istruzionme SQL eseguibile da Gambas che svolga la stessa funzione, perchè, come abbiamo vissuto, con la funzione "ALTER TABLE" l'istruzione SQL in Gambas si comporta in maniera diversa rispetto a come lavora Sqliteman.
Ciao.
:ciao:

Offline Picavbg

  • Senatore Gambero
  • ******
  • Post: 1.620
    • Mostra profilo
Re: rinominare tabella SQlite3 da programma
« Risposta #23 il: 24 Settembre 2013, 00:11:34 »
Riprendo questa vecchia discussione solamente per porre la parola [Risolto].

Ieri, dopo tanto tempo, ho ripreso la parte di programma dove avrei voluto utilizzare all'epoca l'istruzione SQL si SQLite3 "ALTER TABLE". Allora non riuscii, nemmeno coi suggerimenti ricevuti, ad impiegare l'istruzione a causa di errori ottenuti durante l'esecuzione.
Cosa sia accaduto esattamente allora non ricordo più, ma sicuramente la mia inesperienza nell'utilizzo di SQLite3, ha influito enormemente.  :-\

Ieri, ripeto, allo scopo di ridurre notevolmente i tempi di rsequenziazione dei record di ciascuna tabella del mio DB, ho ripreso coraggio ed ho voluto ripetere la prova. Ebbene, è andato tutto liscio come l'olio, le tabelle sono state risequenziate copiandole, nell'ordine dovuto, in tabelle di transito che, dopo avere cancellato quelle d'origine, sono state rinominate ciascuna col suo nome originario. É stato finalmente un ottimo risultato che mi ha permesso praticamente di dimezzare il tempo di lettura e scrittura della tabelle.

Per completezza d'informazione riporto il concetto di risequenziazione vecchio:
1) lettura della 1a tabella del DB e scrittura della stessa, record dopo record, in una tabella transitoria
 
Codice: [Seleziona]
 Try RecTab = ApriDB.DBConnection.Exec("SELECT * FROM piancont ORDER BY NumVoce")
  If RecTab.Available = False Then
      Message.ERROR("Attenzione! ->  " & ERROR.Text & Chr(10) & Chr(10) & "durante la lettura della Tabella '" & ApriDB.$_DbNome & "!piancont'" & Chr(10) & Chr(10) & " il programma verrà chiuso")
      Quit
  Endif
  iId = 0
  For Each RecTab
      iId += 1
      Try ApriDB.DBConnection.EXEC("INSERT INTO piancont2 VALUES(" & RecTab!IdPiaCon & ", '" & RecTab!NumVoce & "', '" & RecTab!NomeVoce & "', '" & RecTab!ContrPartSiNo & "', '" & RecTab!DtPrimoUso & "')")
      If ( Error ) Then
          Message.ERROR("Attenzione!  ERRORE --> '" & ERROR.Text & "'" & Chr(10) & "alla riga " & Error.Where & Chr(10) & Chr(10) & "durante la registrazione della '" & ApriDB.$_DbNome & "!piancont2'" & Chr(10) & Chr(10) & Space$(30) & " IL PROGRAMMA VERRÀ CHIUSO")
          Quit
      Endif
 

2) svuotamento della tabella originaria e riscrittura della stessa coi record precedentemente inseriti nella tabella transitoria. Di questo passo riporto solamente l'istruzione di svuotamento della tabella originaria, perchè quella di scrittura è uguale a quella del passo1, coi nomi delle tabelle invertiti:
Codice: [Seleziona]
 Try ApriDB.DBConnection.EXEC("DELETE FROM piancont")  
3) cancellazione della tabella transitoria.

Il nuovo passo 2) è:
   
Codice: gambas [Seleziona]
 Try ApriDB.DBConnection.EXEC("DROP TABLE piancont")       'Cancellazione della Tabella 'ContabFamdb.piancont', a fine ordinamento
 If ( Error ) Then
        Message.ERROR("Attenzione!  ERRORE --> '" & ERROR.Text & "'" & Chr(10) & "alla riga " & Error.Where & Chr(10) & Chr(10) & "durante la cancellazione della tabella 'piancont' a fine riordino" & Chr(10) & Chr(10) & Space$(30) & " IL PROGRAMMA VERRÀ CHIUSO")
        Quit
    Endif
'------------------------------------------------------------------------------------------------------------------------------------------------------------
    ApriDB.DBConnection.Close
    ApriDB = New OpenDB
    ApriDB.DBConnection.EXEC("ALTER TABLE piancont2 RENAME To piancont")


Il tempo guadagnato è stato tantissimo, perchè attualmente il DB contiene circa 41000 record ed una sola tabella ne contiene 18000. Non sono tantissimi, ma la procedura di lettura e scrittura di quella più corposa impiega circa 35' . Ciò significa che prima della modifica il tempo di risequenziazione dei detta tabella era di circa: h 1:10:00. Sono perciò assai soddisfatto del grande risultato ottenuto ieri. ;D
 :ciao:
:ciao: