Newsgroup: it.comp.software.database
Titolo: Campi numerici con autoincremento

Ciao a tutti. Desideravo porvi una domanda di carattere generale, non 
legata ad alcun DBMS: è ultile servirsi dei campi numerici con 
autoincremento?
Mi spiego meglio: utilizzare questo tipo di campo è un modo veloce per 
assegnare una chiave primaria ad una tabella. Dopo, però, non nascono 
problemi in fase di backup/restore dei dati?
Faccio un esempio: inserisco tre record in una tabella, che avranno 
rispettivamente come valore di chiave 1, 2 e 3. Successivamente elimino 
uno qualsiasi di questi tre record, supponiamo il secondo; quindi 
rimango con i record 1 e 3.
Supponiamo anche di avere una seconda tabella con una chiave esterna che 
referenzia la chiave primaria della prima tabella. Inserisco, quindi, 
dei record che contengano nel campo chiave esterna i valori 1 e 3. A 
questo punto, per precauzione, faccio un bel backup di entrambe le 
tabelle, masterizzo il tutto su DVD e me lo porto a casa.
Durante la notte un fulmine distrugge il centro di elaborazione dati... 
(lo so, l'esempio è un po' estremo, ma serve a far capire il punto). 
Quando arriva il nuovo server faccio il backup del database e... cosa 
succede?
Lo script di backup tenterà di fare qualcosa del genere:
INSERT INTO TABELLA1 VALUES(1, ...);
INSERT INTO TABELLA1 VALUES(3, ...);
(perché abbiamo supposto di aver cancellato il secondo record prima di 
effettuare il backup). Però, visto che la chiave primaria di questa 
tabella è stata indicata come autoincremento, il DBMS ignorerà il valore 
3 della seconda INSERT e assegnerà al campo chiave il valore 2.
A questo punto il ripristino della seconda tabella sarebbe inconsistente 
perché i suoi record (che hanno una chiave esterna alla prima tabella) 
referenzierebbo i record sbagliati (1 e 3), mentre nella prima tabella 
abbiamo i valori di chiave 1 e 2.
Voi come mi consigliate di agire? Lascio perdere i campi con autoincremento?
Grazie,
Nick

Il campo autoincrementale nel Db del Backup a gia un valore (1 e 3)
quindi non viene riassegnato, come pensi tu.
Ciao Jack

 Nick
Bye
-- 
Luca Bianchi
Microsoft MVP - SQL Server
http://blogs.aspitalia.com/lucabianchi/
http://mvp.support.microsoft.com

 abbiamo i valori di chiave 1 e 2.
No, perchè se tu assegni nella insert un valore esplicito non viene
riassegnato. L'auto increment viene usato solo se ommetti il valore
della chiave, se specifichi il valore lui usa quella e allinea di
conseguenza il sequence al massimo.

 autoincremento?
SI :-)

 Evidentemente il team di sviluppo non ha saputo fare di meglio
Può darsi, ma voglio spezzare una lancia a favore del backup a mo'
di script, il quale ti permette a tutti gli effetti di avere la
trasportabilità dei backup su *ogni* database che usi sql.


Cosa assolutamente impossile vista la differenza fra data type nei 
diversi RDBMS.
(Senza considerare le incompatibilita' di sintassi).
-- 
Fabrizio Magni
fabrizi...@mycontinent.com
replace mycontinent with europe

 
Per carita' non posso certo parlare per tutti gli RDBMS ma se prendo sql 
server, l'autoicremento e' solo una proprieta' applicabile ad una colanno.
Il data type sara' semplicemente un intero e ogni valore ha poco a che 
vedere con l'indirizzo fisico.
Un 5 sara' sempre e solo un cinque, qualsiasi sia la sua posizione nel 
DB e anche spostandolo (replicandolo) su un altro DB restera' sempre un 5.
Quindi rimane nello strato "logico", se la distinzione fra logico e 
fisico puo' avere un qualche senso...
Credo che qualche MVP che conosci sql server in maniera piu' 
approfondita possa spiegare molto meglio il concetto.
Ciao


 (Senza considerare le incompatibilita' di sintassi).
Come sopra, anche per la sintassi (benché per un semplice inserimento
dati non serva granché...)
Sembra purtroppo che la "S" in Sql sia assai poco rispettata :-)
Visto che Luca aveva citato Joe Celko, quoto un suo scambio sui NG
a proposito di un utente che voleva usare un datatype non standard:
J.C.:
There is no BIT datatype in Standard SQL.  It is too low level and as
you are finding out, too poorily defined from one language to another.
User:
I pass my bits as Boolean (True/False). That seems to work just fine.
ADO resolves the 1/0 to the correct True/False as expected.
J.C.:
"Forgive him, Theodeus, for he is a barbarian and thinks the ways of his
tribe are the laws of nature." -- G.B. Shaw, "Julius Caesar"
[...]
You might leave before this gets you, but it is a safe bet that some poor
bastard that has to maintain or port the code after you will get caught
on it.
:-)

 approfondita possa spiegare molto meglio il concetto.
Garantisco di accettare spiegazioni da chiunque, indipendentemente dal
blasone.

 
Esiste una suddivisione in layer?!?!?


 trasportabilità dei backup su *ogni* database che usi sql.
...ferme restando le limitazioni legate ai differenti dialetti, questa 
potrebbe essere una feature aggiuntiva, ma chiamarlo backup non mi sembra il 
caso...
Bye
-- 
Luca Bianchi
Microsoft MVP - SQL Server
http://mvp.support.microsoft.com

Ciao Nick,
un esempio di backup e recovery su una tabella con campi autoincrementali.
Nel mezzo puoi anche vedere come sia possibile eseguire inserimenti 
forzando il valore del campo.
Anche un dump (chiamalo backup logico) formato da una serie di 
istruzioni sql rimetterebbe le cose a posto (in questi casi i constraint 
sono riabilitati solo alla fine).
L'esempio usa sql server (oracle non ha l'autoincrementale e non ho al 
momento altri RDBMS a disposizione).
drop table dbo.TestID;
go
CREATE TABLE dbo.TestID
	(
	ID int NOT NULL IDENTITY (2, 1),
	Name varchar(20) NOT NULL
	)  ON [PRIMARY]
GO
ALTER TABLE dbo.TestID ADD CONSTRAINT
	PK_Table1 PRIMARY KEY CLUSTERED
	(
	ID
	) ON [PRIMARY]
GO
insert into dbo.TestID (Name) values ('Giovanni');
insert into dbo.TestID (Name) values ('Giacomo');
insert into dbo.TestID (Name) values ('Romero');
select * from TestID;
2	Giovanni
3	Giacomo
4	Romero
SET IDENTITY_INSERT dbo.TestID ON
insert into dbo.TestID (ID,Name) values (7,'Ruggero');
SET IDENTITY_INSERT dbo.TestID OFF
select * from TestID;
2	Giovanni
3	Giacomo
4	Romero
7	Ruggero
USE master
EXEC sp_addumpdevice 'disk','NorthWind','c:\backup\NorthWind.bak'
BACKUP DATABASE Northwind TO NorthWind
Processed 400 pages for database 'Northwind', file 'Northwind' on file 1.
Processed 1 pages for database 'Northwind', file 'Northwind_log' on file 1.
BACKUP DATABASE successfully processed 401 pages in 2.849 seconds (1.151 
MB/sec).
USE Northwind
drop table dbo.TestID
select * from TestID;
Server: Msg 208, Level 16, State 1, Line 1
Invalid object name 'TestID'.
USE master
RESTORE DATABASE Northwind FROM NorthWind
Processed 400 pages for database 'Northwind', file 'Northwind' on file 1.
Processed 1 pages for database 'Northwind', file 'Northwind_log' on file 1.
RESTORE DATABASE successfully processed 401 pages in 1.553 seconds 
(2.111 MB/sec).
USE Northwind
select * from TestID;
2	Giovanni
3	Giacomo
4	Romero
7	Ruggero
Ciao


 sembra il caso...
Già, il termine backup è troppo ampio in questo caso, specialmente
contando che non sarebbe in grado di ripristinare correttamente i
trigger sui diversi dbms, dato che lo standard Sql non definisce nessun
linguaggio per essi; per cui l'idea, che per un attimo mi ha
affascinato :-) non è fattibile neppure IN TEORIA.
Bisogna derubricare il mio discorso da "backup" a "dump di tabelle"...

 Esiste una suddivisione in layer?!?!?
Eh, si, esiste, ed č un concetto fondamentale dei db e dell'informatica
in generale.
Questo mi chiarisce alcune risposte che hai dato.
Parlare di argomenti avanzati senza prima avere salde le basi č
impresa improba, che rischia di sfociare in inutili discussioni su
concetti basilari.

 
Sai mi capita di essere iscritto alla mia terza laurea e la seconda era 
appunto in informatica.
Se vuoi puoi trovare ancora la mia pagina al Helsinki University of 
Technology e alcuni articoli sulla logica matematica pubblicati da 
ricercatore.
Anche riguardando i miei testi di basi di dati I e II non trovo una 
suddivisione in layer.
Neanche un tentativo simila all pila ISO/OSI per le reti.
Nota che non ho commentato fra si come:
"Succede che la seconda tabella fa riferimento ad uno stato fisico della
macchina"
Se puoi mi vorresti descrivere come riesci a distingure uno stato fisico 
da uno logico te ne sarei grato.
Cordialita'


 Cordialita'
Cordialmente ti saluto :-)

 
Ancora non vedo la suddivisione tra fisico e logico.
Per te tutto cio' che non e' data model e' fisico?
Un blocco di un RDBMS e' fisico?
Anche se sta su un filesystem che e' un costrutto logico?
Anche se e' in un device i cui indirizzi sono offset logici?
Anche se si e' su un dispositivo che maschera uno storage complesso dove 
la componente fisica (il piatto del disco) e' difficile da individuare?
Il tuo modello a layer comprende solo il logico e il fisico? Mi sembra 
un po' grezzo.
Mi diresti su quali testi hai letto la suddivisione? Vedro' di procurarmeli.
Aggiungo: nel caso volessi dimostrare le tue affermazioni del post delle 
27/11/2005 17.13...
Finora tutte le mie prove di backup e recovery sembrano contraddirti non 
mostrando problemi sull'uso di autoincrementali.
Se vuoi domani provo anche con i dump di mysql e posto i risultati.
Ciao


 >procurarmeli.
Ti ho già citato varie referenze, ma comunque trovi molto sul web...

La prima stesura era ben diversa.
Vedro' di essere maggiormente diplomatico.
Stai completamente confondendo le cose e ora mi chiedo quanto tu
conosca dell'argomento.
cio' che mi hai inviato e' la suddivisione in tre tier di un sistema
informativo.
Il tipico esempio:
webserver
application sevrver
DB server.
Mi sai dire cosa questo ha a che fare con la suddivisione in layer fra
fisico e logico?!?!?!?!
Quello che mi sarei aspettato dalla tuo risposta e' uno stack simile
all'ISO/OSI per le reti.
Application Layer
Presentation Layer
Session Layer
Transport Layer
Network Layer
Data Link Layer
Physical Layer
Dove il livello fisico specifica inezie che vanno dal mezzo trasmissivo
fino ai livelli di tensione necessari per descrivere uno zero o un uno.
Come vedi i vari livelli sono ben descritti e definiti.
Esiste la stessa cosa per le basi dati?
Non mi risulta.
Ma sono pronto a ritrattare se mi mostra un qualche testo di una certa
validita' che riporti questa suddivisione.
Prendiamo come esempio le strutture di memorizzazione in un database
oracle (che mi sembri conoscere).
tabella
segmento
extent
blocco
tablespace
datafile
senza contare i possibili
filesystem
device
RAID
etc
Mi sai dire dove parte il livello fisico e dove quello logico?
Invece il *tuo* concetto fondamentale dell'informatica si riduce a ben
poco (con tutto il rispetto per il multi-tier).
Ti ripeto le basi di dati esistevano anche con i terminali dummy dove
non si pensava nemmeno alle implementazioni a due livelli, come le
semplici client-server, figuriamoci quelle a tre.
In piu', per il tuo punto 3:
oltre a non aver mai sentito parlare di un " principio informativo dei
dati" aggiungo che le basi dati non sono solo relazionali e che
l'informatica, fortunatamente, non si basa solo su questo concetto.
A questo punto ti domando:
un'architettura a due livelli (client-server) come l'ssh cos'ha a che
spartire con le basi dati??????
E quella a tre livelli?
Un webserver viene preso in esame nel tuo data model?!?!?
Il bello e' che alla mia domanda sulla differenza fra fisico e logico
mi hai anche risposto se avevo le basi!!!!!
Ma se vuoi interpella Celko.
Partecipero' volentieri alla discussione!


Man,
in questo thread hai partecipato inizialmente con due dichiarazioni.
Una ritrattata da te stesso.
L'altra passata sotto silenzio.
Nick (l'OP) chiedeva se esistessero problemi nel restore di tabelle che
fanno uso degli autoincrementali.
Tra "stati fisici delle macchine" mi sembra di legegre che tu reputi
che effettivamente il problema ci sia.
Un posto precedente ha dimostrato come un backup e restore fisico (si
ripristina i blocchi del DB) non provochi problemi di sorta.
Ora aggiungo due test con mysql e l'uso di dump (quindi istruzioni
sql).
In entrambi i casi i dati, dopo il restore rimangono consistenti.
Il primo esempio mostra la di un database dopo la drop di una tabella.
Il secondo usa due tabelle con foreign key e ne ripristina una
mostrando come il constraint viene riabilitato correttamente semnza
avere perdita di integrita' dei dati.
Nel caso aspetto volentieri dei contro esempi.
CREATE TABLE testid (
id MEDIUMINT NOT NULL AUTO_INCREMENT,
name CHAR(30) NOT NULL,
PRIMARY KEY (id)
);
insert into testid (Name) values ('Giovanni');
insert into testid (Name) values ('Giacomo');
insert into testid (Name) values ('Romero');
mysql> select * from testid;
+----+----------+
| id | name |
+----+----------+
| 1 | Giovanni |
| 2 | Giacomo |
| 3 | Romero |
+----+----------+
3 rows in set (0.03 sec)
mysql> insert into testid (id,name) values (7,'Ruggero');
Query OK, 1 row affected (0.00 sec)
mysql> select * from testid;
+----+----------+
| id | name |
+----+----------+
| 1 | Giovanni |
| 2 | Giacomo |
| 3 | Romero |
| 7 | Ruggero |
+----+----------+
4 rows in set (0.00 sec)
# mysqldump -p --single-transaction --databases prova > prova.sql
Enter password:
mysqlhotcopy --password=pain_9_ prova
Using copy suffix '_copy'
Locked 1 tables in 0 seconds.
Flushed tables (`prova`.`testid`) in 0 seconds.
Copying 3 files...
Copying indices for 0 files...
Unlocked tables.
mysqlhotcopy copied 1 tables (3 files) in 0 seconds (1 seconds
overall).
mysql> use prova
Database changed
mysql> drop table testid;
Query OK, 0 rows affected (0.00 sec)
mysql> select * from testid;
ERROR 1146: Table 'prova.testid' doesn't exist
breoradbls01:~ # mysql -p < prova.sql
Enter password:
breoradbls01:~ # mysql -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 8 to server version: 4.0.18-Max
Type 'help;' or '\h' for help. Type '\c' to
clear the buffer.
mysql> use prova
Database changed
mysql> select * from testid;
+----+----------+
| id | name |
+----+----------+
| 1 | Giovanni |
| 2 | Giacomo |
| 3 | Romero |
| 7 | Ruggero |
+----+----------+
4 rows in set (0.00 sec)
drop table IF EXISTS testid;
CREATE TABLE testid (
id INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
name CHAR(30) NOT NULL,
PRIMARY KEY (id)
) TYPE = InnoDB;
drop table IF EXISTS surname;
CREATE TABLE surname (id INTEGER UNSIGNED NOT NULL,
sname char(30) NOT NULL,
index (id),
FOREIGN KEY (id)
REFERENCES testid (id) ON DELETE CASCADE ON
UPDATE CASCADE) TYPE =
InnoDB;
insert into testid (Name) values ('Giovanni');
insert into testid (Name) values ('Giacomo');
insert into testid (Name) values ('Romero');
insert into surname values (1,'Rossi');
insert into surname values (3,'Bianchi');
insert into surname values (7,'Verdi');
Provo ad inserire una chiave errata:
insert into surname values (5,'Baldi');
ERROR 1216: Cannot add or update a child row: a foreign key constraint
fails
mysql> select * from surname;
+----+---------+
| id | surname |
+----+---------+
| 1 | Rossi |
| 3 | Bianchi |
| 7 | Verdi |
+----+---------+
3 rows in set (0.00 sec)
mysqldump -p --single-transaction --databases prova > prova2.sql
mysqldump -p --single-transaction prova testid > testid.sql
mysql> use prova
Database changed
mysql> alter table surname drop foreign key surname_ibfk_1;
Query OK, 3 rows affected (0.10 sec)
Records: 3 Duplicates: 0 Warnings: 0
mysql> drop table testid;
Query OK, 0 rows affected (0.05 sec)
alter table surname add foreign key surname_ibfk_1 (`id`) REFERENCES
`testid` (`id`) ON
DELETE CASCADE ON UPDATE CASCADE;
mysql> use prova
Database changed
mysql> alter table surname add foreign key surname_ibfk_1 (`id`)
REFERENCES `testid` (`id`)
ON DELETE CASCADE ON UPDATE CASCADE;
Query OK, 3 rows affected (0.13 sec)
Records: 3 Duplicates: 0 Warnings: 0
mysql> select * from surname;
+----+---------+
| id | sname |
+----+---------+
| 1 | Rossi |
| 3 | Bianchi |
| 7 | Verdi |
+----+---------+
3 rows in set (0.00 sec)
mysql> select * from testid;
+----+----------+
| id | name |
+----+----------+
| 1 | Giovanni |
| 2 | Giacomo |
| 3 | Romero |
| 7 | Ruggero |
+----+----------+
4 rows in set (0.00 sec)


 dati"
Non ti sei neppure degnato di leggere i riferimenti che ti ho dato.
Bah :-<

 
Nel caso mi scuso ancora.
