SQLite ha colpito ancora! :o
Sarebbe il caso di dire: Non ne posso più! ... Ma vado al dunque: Dall'idea fissa di mantenere il contenuto di ciascuna tabella ordinato in base alla mia configurazione originaria di chiave primaria (costituita da una sola colonna o da più colonne, a seconda delle necessità), ho inserito come prima colonna di ciascuna tabella il codice id autoincrement, però ho anche inserito una gestione semiautomatica di ordinamento; infatti essa può scattare in seguito ad una segnalazione su eventuali nuovi inserimenti nelle varie tabelle, consigliando il riordino di quelle che abbiano subito, per es., più 100 accodamenti. Dall'apposita Form di avvertimento, l'utente può avviare l'ordinamento o rimandarlo ad un momento successivo. La procedura di ordinamento prevede:
1) la creazione di una tabella transitoria;
2) la trascrizione nella nuova tabella di tutte le righe lette dalla prima col criterio "ORDER BY";
3) la cancellazione della tabella originaria;
4) la ridenominazione della tabella transitoria, attribuendole il nome della tabella appena cancellata.
le istruzioni utilizzate sono le seguenti:1) CREATE TABLE "NomeTabellaTransito "('id' INTEGER PRIMARY KEY AUTOINCREMENT, 'Colonna2' INTEGER, 'Colonna3' VARCHAR(50) DEFAULT NULL, 'Colonna4' CHAR(1) DEFAULT NULL, 'Colonna5' INTEGER );
2) RecTab = DB_Connection.Edit("NomeTabellaOrigine")
RecTab = DB_Connection.Exec("SELECT * FROM NomeTabellaOrigine ORDER BY Colonna2")
FOR EACH RecTab
i_id += 1
DB_Connection.EXEC("INSERT INTO NomeTabellaTransito VALUES(" & i_id & ", '" & RecTab!Colonna2 & "', '" & RecTab!Colonna3 & "', '" & RecTab!Colonna4 & "', '" & RecTab!Colonna5 & "')")
NEXT
DB_Connection.Commit
DB_Connection.Close
3) DB_Connection.EXEC("DROP TABLE NomeTabellaOrigine ")
4) DB_Connection.EXEC("ALTER TABLE 'NomeTabellaTransito' RENAME TO 'NomeTabellaOrigine'")
Dopo l'esecuzione delle suddette istruzioni, sembra che tutto sia andato bene, però proseguendo ottengo un errore, attraverso il quale rilevo che:
la tabella rinominata non viene riconosciuta dall'istruzione IF NOT DB_Connection.Tables.Exist("NomeTabellaOrigine")
, mentre viene trovata tranquillamente da "Sqliteman", però il passo 4), di ridenominazione, l'ha completamente svuotata del suo contenuto.
Chi mi potrebbe spiegare perchè succede tutto ciò? >:( :'(
Ciao a tutti.
invece di cambiargli nome perchè non la riscrivi in una nuova tabella con il nome corretto?
Un pò, perchè ho l'indole del programmatore pigro, :D un pò perchè pensavo di abbreviare i tempi di esecuzione con una sola trascrizione dalla TabellaOriginaria alla TabellaTransitoria. Infatti ottenuta la nuova Tabella, ordinata a mio piacimento, cancellando l'originaira e ridenominado la Transitoria col nome di origine, avrei evitato proprio tutta la seconda trascrizione per riportare i dati nell'Originaria. Chissà perchè, ma ogni volta che provo un percorso fuori dallo standard, anche se citato nella guida sql, vado sempre ad incappare in problematiche pratiche che non dovrebbero assolutamente manifestarsi. Magari penserai che io ce l'ho con SQLite; io invece penso che è SQLite ad avercela con me! ;)
Comunque, ho gia avviato la correzione del programma aggiungendo l'intera ritrascrizione dalla TabellaTransitoria alla TabellaOriginaria. Ho solamente aggiunto una riga SQL per lo svuotamento del contenuto della TabellaOriginaria ed ha funzionato:
DB_Connection.EXEC("DELETE FROM TabellaOriginaria")
Si, direi, dato che col tuo invito, mi dai conferma di avere incontrato un ostacolo insormontabile, il problema segnalato sia proprio irrisolvibile. :-X :)
Ciao.
la tabella rinominata non viene riconosciuta dall'istruzione IF NOT DB_Connection.Tables.Exist("NomeTabellaOrigine")
, mentre viene trovata tranquillamente da "Sqliteman", però il passo 4), di ridenominazione, l'ha completamente svuotata del suo contenuto.
Chi mi potrebbe spiegare perchè succede tutto ciò? >:( :'(
Ciao a tutti.
L'istruzione che hai scritto ti ritorna TRUE se la tabella non esiste...
Era quello che volevi fare?
/quote]
No, il problema non è quello; L'istruzione di test sull'esistenza della tabella funziona benissimo. Quella che non funziona è l'istruzione di ridenominazione della tabella già valorizzata con gli elementi provenienti dalla TabellaOriginaria. Essa
DB_Connection.EXEC("ALTER TABLE 'NomeTabellaTransito' RENAME TO 'NomeTabellaOrigine'")
infatti produce due effetti incredibili:
1) Modifica il nome della tabella, ma poi l'istruzione di test usata in Gambas non la trova, mentre il gestore di DB Sqliteman (io uso Fedora), la tabella viene riconosciuta col nuovo nome (TabellaOriginaria)
2) Svuota completamente il contenuto della tabella,
Se la mia "ALTER TABLE" è stata scritta correttamente, il risultato finale è assolutamente illogico. Spero di essere riuscito chiararti il problema incontrato e l'annesso mio concetto.
Ciao.
Ho fatto il seguente test:
PUBLIC SUB QueryTest()
DIM Sql AS String
DIM Nx AS Integer
DIM Res AS Result
' Funzione che mi ritorna la connessione al db (non sono stato li a postarla)
conn = MDatabase.CreateDatabase()
' la seguente sql mi crea la tabella e ci inserisce i dati dentro dalla tabella di origine
Sql = "CREATE TABLE NomeTabellaTransito AS SELECT * FROM NomeTabellaOrigine ORDER BY cassa;"
conn.Exec(Sql)
' cancello la tabella di origine
Sql = "DROP TABLE NomeTabellaOrigine"
conn.Exec(Sql)
' Rinomino la tabella di transito
Sql = "ALTER TABLE 'NomeTabellaTransito' RENAME TO 'NomeTabellaOrigine';"
conn.Exec(Sql)
' Test: Se la tabella NomeTabellaOrgine esiste mi esegue il test
IF conn.Tables.Exist("NomeTabellaOrigine") THEN
Sql = "SELECT * FROM NomeTabellaOrigine;"
Res = conn.Exec(Sql)
FOR Nx = 0 TO Res.Max
Res.MoveTo(Nx)
FMain.TextArea1.Text &= Res[0] & ";" & Res[1] & ";" & Res[2] & ";" & Res[3] & Chr(10)
NEXT
ENDIF
END
Il test viene eseguito perfettamente e mi ritorna nella mia textarea i record separati da ;
quello che volevo dire io e' che se metti
IF conn.Tables.Exist("NomeTabellaOrigine") THEN
gambas esegue le istruzioni se la tabella esiste, invece se
IF NOT conn.Tables.Exist("NomeTabellaOrigine") THEN
come hai scritto tu nel primo post, esegue le istruzioni se la tabella NON esiste...
Scusa, milio, ma non ho capito cosa mi vuoi dimostrare con la tua prova. La prima parte di essa coincide con le istruzioni utilizzate da me, per cui fino alla "ALTER TABLE" siamo sulla stessa linea. Infatti io ho scritto:
CREATE TABLE "NomeTabellaTransito "('id' INTEGER PRIMARY KEY AUTOINCREMENT, 'Colonna2' INTEGER, 'Colonna3' VARCHAR(50) DEFAULT NULL, 'Colonna4' CHAR(1) DEFAULT NULL, 'Colonna5' INTEGER );
RecTab = DB_Connection.Edit("NomeTabellaOrigine")
RecTab = DB_Connection.Exec("SELECT * FROM NomeTabellaOrigine ORDER BY Colonna2")
FOR EACH RecTab
i_id += 1
DB_Connection.EXEC("INSERT INTO NomeTabellaTransito VALUES(" & i_id & ", '" & RecTab!Colonna2 & "', '" & RecTab!Colonna3 & "', '" & RecTab!Colonna4 & "', '" & RecTab!Colonna5 & "')")
NEXT
DB_Connection.Commit
DB_Connection.Close
DB_Connection.EXEC("DROP TABLE NomeTabellaOrigine ") DB_Connection.EXEC("ALTER TABLE 'NomeTabellaTransito' RENAME TO 'NomeTabellaOrigine'")
DB_Connection.EXEC("ALTER TABLE 'NomeTabellaTransito' RENAME TO 'NomeTabellaOrigine'")
mentre tu hai scritto:
Ho fatto il seguente test:
Sql = "CREATE TABLE NomeTabellaTransito AS SELECT * FROM NomeTabellaOrigine ORDER BY cassa;"
conn.Exec(Sql)
' cancello la tabella di origine
Sql = "DROP TABLE NomeTabellaOrigine"
conn.Exec(Sql)
' Rinomino la tabella di transito
Sql = "ALTER TABLE 'NomeTabellaTransito' RENAME TO 'NomeTabellaOrigine';"
conn.Exec(Sql)
Stabilito ciò, quello che bisognerebbe capire è perchè a te il test
IF conn.Tables.Exist("NomeTabellaOrigine") THEN
si conclude con "TRUE", mentre a me si conclude con "FALSE" e, poi, perchè tu ritrovi, nella tabella rinominata, tutti i record copiati precedentemente, mentre io mi ritrovo la tabella vuota. :o
La risposta a codeste domande non è facilmente fornibile, perchè operiamo in ambienti operativi diversi (tu usi Ubuntu ed io Fedora), e probabilmente tu usi una versionme di Gambas diversa dalla mia che è la 2.19. Potrebbero proprio i motori su cui girano i nostri programmai a produrre, non so per quale motivo, effetti diversi. Un'altra considerazione potrebbe essere: l'ambiente su cui gira il mio programma è teoricamente non responsabile, però l'anomalia che mi si verifica dipende dall'assenza nell'ide del mio Gambas di qualche componente preposto a svolgere correttamente le funzioni che ho richiamate.
Ti ringrazio per l'aiuto e mi complimento con te per la tua conoscenza di SQLite3; ho visto come usi le istruzioni SQL anche in altre discussioni e non posso che fare tesoro dei tuoi consigli. Mi dispiace solo che non possa trarne vantaggio in questo momento. Ciao.
Concordo con Milio su tutti i punti:
1) nessuno ti ha dato del pivello, ti sei scaldato proprio per nulla ;)
2) ho letto tutta la discussione e nel tuo primo post hai scritto che Gambas non vede la tabella creata ma Sqliteman sì anche se vuota;
3) non è facile capire i problemi quando uno è seduto di fronte ad un computer e l'altro è a 500 km di distanza ::)
4) googlando ho trovato questo procedimento per cambiare il nome ad una tabella:
-Inserire una nuova colonna nel database (esempio completo).
ATTENZIONE FARE PRIMA UNA COPIA DEL FILE-DATABASE
sqlite prova
#Crea una tabella
sqlite> create table t1(a text, b text);
#Inizia la transazione
sqlite> BEGIN TRANSACTION;
#Crea una tabella temporanea uguale all'altra tabella
sqlite> CREATE TEMPORARY TABLE t1_backup(a,b);
#Fa un copia ed incolla dalla prima tabella alla tabella temporanea
sqlite> INSERT INTO t1_backup SELECT a,b FROM t1;
#Cancella la prima tabella
sqlite> DROP TABLE t1;
#Crea la nuova tabella con la nuova colonna
sqlite> CREATE TABLE t1(a text,b text,c text);
#Fa una copia dalla tabella temporanea alla nuova tabella
sqlite> INSERT INTO t1 (a,b) select * FROM t1_backup;
#Cancella la tabella temporanea
sqlite> DROP TABLE t1_backup;
#Finisce la transazione.
sqlite> COMMIT;
#Controllo nomi colonne
sqlite> .schema
Immagino che un adattamento a Gambas non sia difficile.
Qualcosa tipo:
DB_Connection.Begin
RecTab = DB_Connection.EXEC("CREATE TEMPORARY TABLE NomeTabellaTransito (id INTEGER PRIMARY KEY AUTOINCREMENT, Colonna2 INTEGER, Colonna3 VARCHAR(50) DEFAULT NULL, Colonna4 CHAR(1) DEFAULT NULL, Colonna5 INTEGER );")
RecTab = DB_Connection.EXEC("INSERT INTO NomeTabellaTransito FROM NomeTabellaOrigine ORDER BY Colonna2;")
RecTab = DB_Connection.EXEC("DROP TABLE NomeTabellaOrigine;")
RecTab = DB_Connection.EXEC("CREATE TABLE NomeTabellaOrigine (id INTEGER PRIMARY KEY AUTOINCREMENT, Colonna2 INTEGER, Colonna3 VARCHAR(50) DEFAULT NULL, Colonna4 CHAR(1) DEFAULT NULL, Colonna5 INTEGER );")
RecTab = DB_Connection.EXEC("INSERT INTO NomeTabellaOrigine FROM NomeTabellaTransito;")
RecTab = DB_Connection.EXEC("DROP TABLE NomeTabellaTransito;")
DB_Connection.Commit
DB_Connection.Close
Poi per fare un'altra prova potresti usare il mio codice per testare se funziona anche sul tuo pc, con la tua distro e la tua versione di gambas... almeno ci togliamo ogni dubbio ;)
io uso kubuntu con gambas 2.20.2
Rispondo solo ora perchè ho voluto concludere un test sul programma. Infatti, mentre ragionavo con voi sulla funzione SQL "ALTER TABLE", sono andato avanti.
Anche se a me non piacciono le polemiche, devo dire che, per gli appellativi come "pivello" possono anche essere dichiarati senza nominare il termine esatto: Lo stesso effetto si ottiene, usando frasi che lo facciano capire:
(((se metti IF conn.Tables.Exist("NomeTabellaOrigine") THEN gambas esegue le istruzioni se la tabella esiste, invece se IF NOT conn.Tables.Exist("NomeTabellaOrigine") THEN esegue le istruzioni se la tabella NON esiste), rafforzata poi da: (Milio ti sta dicendo che il test che esegui tu domanda al DB se NON esiste la tabella. Siccome la tabella esiste, ti restituisce False perché il test non è andato a buon fine (cioè la tabella esiste). Quel "NOT" significa proprio questo: inverti il senso (o risultato) del test. La tabella SQLiteMan la vede proprio perché c'è.)))
Come vedi, soprattutto nella seconda affermazione il concetto è pungente, anche se il termine non è stato citato.
Siccome non credo che che sia costruttivo andare avanti con simili ragionamenti, anche perchè sono convinto che sia io, da una parte, che voi due, dall'altra, rimarremo sempre nelle nostre posizioni, per quanto mi riguarda, la parentesi comportamentale, può considerarsi chiusa.
:)
Ho voluto provare il tuo codice, anche perchè contiene un'istruzione originale, che non conoscevo (ammetto la mia ignoranza in proposito):
' la seguente sql mi crea la tabella e ci inserisce i dati dentro dalla tabella di origine
Sql = "CREATE TABLE NomeTabellaTransito AS SELECT * FROM NomeTabellaOrigine ORDER BY cassa;"
IF DB_Connection.Tables.Exist("NomeTabellaTransito") THEN
Sql = "SELECT * FROM NomeTabellaTransito;"
RecTab = DB_Connection.Exec(Sql)
FOR i = 0 TO RecTab.Max
NEXT
PRINT i ----> stampa 142 (cioè il n° dei record teoricamente copiati)
ENDIF
' cancello la tabella di origine
Sql = "DROP TABLE NomeTabellaOrigine"
DB_Connection.Exec(Sql)
' Rinomino la tabella di transito
Sql = "ALTER TABLE 'NomeTabellaTransito' RENAME TO 'NomeTabellaOrigine';"
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("NomeTabellaOrigine") THEN
Sql = "SELECT * FROM NomeTabellaOrigine;"
RecTab = DB_Connection.Exec(Sql)
FOR i = 0 TO RecTab.Max
NEXT
PRINT i ----> stampa ancora 142 (sembrerebbe perciò che il lavoro sia andato bene)
ELSE
PRINT "La Tabella 'piancont' non esiste"
ENDIF
Dall'andamento delle interrogazioni sui record di tabella, sia nella fase intermedia, di registrazione sulla 'TabellaTransito', che nella fase finale, di registrazione sulla 'TabellaOrigine', sembrerebbe che abbia funzionato.
Accedendo però alla Tabella di DB tramite Sqliteman, ahimè, l'ho trovata di nuovo vuota. L'unica cosa che è cambiata dalla mia prova iniziale è che il test 'IF DB_Connection.Tables.Exist("NomeTabellaOrigine") ' questa volta trova la tabella.
:-\
Che ne pensi?
Secondo me, non conviene insistere. :)
Ciao.
Nessun problema, discussione 'animata' chiusa; discussione 'costruttiva' aperta ;)
hai provato a vedere se gambas 'vede' i record, cioe' se al posto di contare i record ci fai un print del contenuto ?
cosi' vediamo se effettivamente sono stati copiati... fammi sapere...
ps. altra cosa che ho visto e' che hai preso pari pari il mio codice
Sql = "CREATE TABLE NomeTabellaTransito AS SELECT * FROM NomeTabellaOrigine ORDER BY cassa;"
io ho messo ORDER BY cassa perche' avevo un campo chiamato cosi'... e' chiamato cosi' anche il tuo campo di riordino?
facci sapere quando risolvi ciao ciao
Per la verità, praticamente ho superato l'ostacolo seguendo il tuo consiglio, cioè:
$_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
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.
@ 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.
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
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.
e se fai in questo modo?
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
e se fai in questo modo?
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.
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.
@ milio:
Ho cantato vittoria troppo presto. Infatti tutte le istruzioni
RecTab = DB_Connection.Edit("NomeTabella")
che hanno riferite alla tabella interessata dall'ALTER TABLE, producono l'errore
"Table 'NomeTabella' has no priimary key
Ho guardato in Sqliteman->Contesto->Descrivi tabella, prima e dopo l'ALTER TABLE, ed ecco la differenza:
Prima dell'istruzione ALTER TABLE:
-- Descrizione CAUSALIFREQ
CREATE TABLE 'causalifreq'('id' INTEGER PRIMARY KEY AUTOINCREMENT, 'DescrCausFreq' VARCHAR(100), 'DtUltCausFreq' INTEGER )
Dopo l'istruzione ALTER TABLE:
-- 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.
@ 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.
-- 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:
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:
-- Descrizione CAUSALIFREQ (prima di Rinomina la tabella):
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):
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.
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
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:
Try ApriDB.DBConnection.EXEC("DELETE FROM piancont")
3) cancellazione della tabella transitoria.
Il nuovo passo 2) è:
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: