Newsgroup: it.comp.software.database
Titolo: SQLite chiave primaria univoca

Il mio problema è costruire con SQlite un codice univoco.
 
CREATE TABLE t_test(
 id INTEGER PRIMARY KEY AUTOINCREMENT,
 name VARCHAR(10)
 );
 
Funziona bene con un insert MA
1 pippo
2 pluto
3 paperino
 
Cancello 2 e aggiungo nonna papera
1 pippo
3 paperino
4 nonna papera
 
MA se per una sciaguratissima ipotesi
INSERT INTO t_test(id,name) VALUES (2,'Gambadilegno');
 
Ottengo
1 pippo
2 Gambadilegno
3 paperino
4 nonna papera
 
mi riusa il 2...e se io c'ho un controllo su una tabella correlata 
questo non si accorge della mancanza del padre e mi fa anche 
peggio...imputa dati a un genitore errato!
 
Per ovviare mi tocca scrivere molto più codice! Ho letto del ROWid ma 
non mi riesce usarlo! e comunque se io reimputo un codice(un integer) 
gia usato me lo accetta!
Il classico contatore di access è comodissimo per non scrivere codice 
in più! Si può implementare in sqlite?
 
Grazie!
 
-- 
----- Italliaaaaa 3227! -----
Pasquà...Pasquale Zagaria...u'fighh'Riccard
[Vieni avanti cretino (1982)
c'ho pure il video! 
http://www.martek.it/public/dblog/banfi1.swf
 ]
 
 

 Per ovviare mi tocca scrivere molto più codice!
 
Perche`?
Ti basta non mettere l'id quando fai le insert e le update.
 
Bye.
 

 peggio...imputa dati a un genitore errato!
 
Non mi è chiaro il caso a cui ti riferisci, puoi incollare un esempio 
per riprodurre il problema?

 Il mio problema è costruire con SQlite un codice univoco.
...scusate ma mi sembrava abbastanza chiaro!
Costruire una sequenza dove un numero usato non fosse più riusabile!
 
In access questa cosa è implementata dal campo "contatore" che è a sola 
lettura...
 
In Sqlite leggendo la documentazione sembra esistere Rowid che dovrebbe 
essere lo stesso...ma ho difficoltà a capir bene come 
impostarlo...probabilmente devo creare una tabella di sistema di 
supporto? Perchè in automatico il mio sqlite(3) non me lo crea!
 
Ovvio che mi serve per l'integrità referenziale (che comunque sqlite 
non supporta  e quindi a maggior ragione servirebbe una autogenerazione 
di un codice univoco non ripetibile ne impostabile)
 
Ovvio che posso cavarmela da codice
in una qualsiasi INSERT non imputerò mai il campo codice...in una 
UPDATE lo stesso!
 
Perchè può accadere in sqlite
ClienteID --- integer primary key
di fatto è un autonumber
 
se ho Articoli
IdArticolo
IDcliente Integer
 
Con Un Where ClienteID=IDcliente ho stabilito una relazione
 
Cancello ClienteID
ArticoliID rimane zoppo...la query va in errore...mi accorgo subito di 
un grave problema (nello specifico...chi è il bischero che ha 
cancellato il padre prima dei figli???)
 
Ma se per qualche motivo (anche fraudolento)
Creo un nuovo cliente
Cancello un vecchio
Aggiorno il nuovo cliente all'id del vecchio
Tutto continua a funzionare!...e non va bene!
Anche qui workaround...si lavora di trigger...ma allora si complica 
tutto ... butto alle ortiche SQlite e uso Postgresql o Sqlserver con il 
supporto all'integrità referenziale....uso sqlite proprio perchè mi 
gira sotto php e aspnet e mi serve una cosa leggera senza tante 
pretese!
 
Quindi riformulo
come si fa in sqlite (se è possibile ovvio!) a costruire una sequenza 
univoca per la tabella in sola lettura? (O in subordine come si 
implementa nel caso concreto rowid?)
 
Grazie della pazienza!
 
-- 
----- Italliaaaaa 3227! -----
Please, visits website, but please visit Italy. We’re t’best country in 
the world in terms of: Culture, Landscapes, Arts, History, Cities, 
Villages, Beautiful countryside, seaside, mountains. That is Italy. You 
know, perhaps, you dreaming about. But please, visit or country. We 
will welcome you warmly and with a better organization.
(Francesco Rutelli Video a: 
http://www.martek.it/dblog/mostraVideo.asp?p=/public/dblog/Rutelli1.wmv
 
)
 
 

Wodka40° scriveva il 07/11/2011 :
per chiarire
 
CREATE TABLE `contenuto`
 
(
       idcontenuto rowid Not Null PRIMARY KEY ,
       idautore INTEGER NOT NULL,
       data DATETIME,
       titolo TEXT,
       contenuto BLOB,
       commenti INTEGER DEFAULT "0" ,
       matatag TEXT,
       visibile INTEGER DEFAULT "1" ,
       flag INTEGER DEFAULT "1"
 
)
 
Il rowid non mi mostra nulla ed accetta numeri come un normale integer
 
-- 
----- Italliaaaaa 3227! -----
Il coraggio ce l'ho. E' la paura che mi frega.
(Totò)
 
 

 implementa nel caso concreto rowid?)
 
Non lo fai.
 
E comunque l'errore e` appunto nell'integrita`, non nel DB. Se cancelli 
un cliente devi cancellare anche tutti i dati che si riferiscono a lui. 
Se non lo fai e` un bug dell'applicazione (che non ha messo i vincoli di 
integrita` o che non li gestisce da sola), e non del DB, che fa 
esattamente quello che gli dici di fare.
 
Nemmeno PostgreSQL ti salverebbe da una situazione del genere (anche se 
hai gli OID che dovrebbero essere univoci a livello di database, ma non 
so se farei integrita` con gli oid). E nemmeno Oracle, presumo.
 
Bye.
 

 Il Mon, 07 Nov 2011 15:36:43 +0100, Wodka40° ha scritto:
zac
...era proprio la risposta che temevo, mi immaginavo...ma che non 
speravo di veder scritta! ;o)
 
-- 
----- Italliaaaaa 3227! -----


 implementa nel caso concreto rowid?)
 
Non lo fai nel db, oppure aggiungi una colonna "cliente attivo" e invece 
di cancellare i clienti li marchi come non attivi.

 [...]
 
 
Ciao  Manlio

 Il mio problema è costruire con SQlite un codice univoco.
risolto così
se vi interessa
tab.padre  tab.figlio
autori->contenuto
ho risolto impostando un trigger che quando cancello un autore cancella 
gli articoli corrispondenti nella tabella contenuto
 
/* DDL information for - deletecontenuto */
-------------------------------------------
CREATE TRIGGER deletecontenuto
BEFORE DELETE ON autori
FOR EACH ROW BEGIN
    DELETE FROM contenuto WHERE contenuto.idautore = OLD.idautore;
END
 
 e impostando un foreignkey su sqlite3 nella tabella contenuto
CONSTRAINT "fk_autore" FOREIGN KEY ("idautore") REFERENCES "autori" 
("idautore") ON DELETE CASCADE
 
e comunque impostando un altro trigger sull'insert della tabella 
contenuto che solelva esplicitamente un eccezione
 
DROP TRIGGER IF EXISTS controlla_autore;
CREATE TRIGGER controlla_autore
BEFORE INSERT ON contenuto
FOR EACH ROW BEGIN
   SELECT RAISE(ROLLBACK, '10#Non esiste un autore associato per questo 
articolo')
   WHERE (SELECT idautore FROM autori WHERE idautore = NEW.idautore) IS 
NULL;
END


 Il mio problema è costruire con SQlite un codice univoco.
 
Non vedo perche` (o meglio, non lo vedo nel caso da te postato), visto che 
SQLite supporta le foreign key (che devono essere abilitate):
 
PRAGMA foreign_keys = ON;
 
CREATE TABLE artist(
  artistid    INTEGER PRIMARY KEY, 
  artistname  TEXT
);
 
CREATE TABLE track(
  trackid     INTEGER, 
  trackname   TEXT, 
  trackartist INTEGER,
  FOREIGN KEY(trackartist) REFERENCES artist(artistid) ON DELETE CASCADE
);
 
INSERT INTO artist VALUES(1, 'Dean Martin');
INSERT INTO track VALUES(11, 'That''s Amore', 1);
INSERT INTO track VALUES(13, 'My Way', 2);
Error: foreign key constraint failed
 
Tieni comunque presente due cose:
 - L'abilitazione delle foreign key e` a livello di connessione. Devi quindi
   prevedere, lato applicativo, l'esecuzione del comando ad ogni apertura di
   connessione (cosa abbastanza semplice da eseguire).
 - SQLite fa il check delle foreign key solamente dal momento in cui le
   abiliti, percio` se prima di abilitarle hai inserito antani record, puoi
   ritrovarti il database sporco
 
Enrico
P.S. per tutti, consiglio di dare un'occhiata alla lista dei pragma 
disponibili per SQLite, in quanto permettono di fare cose carine (e.g. 
l'aumento del numero di pagine dedicate alla cache)