Le avventure in VB.Net di un principiante ex-VB6 - 2
a cura di Oscar Zanin e Diego Cattaruzza (requisiti: Visual Basic Express e SqlServer Express)Premessa
Nell'articolo precedente è stato presentato il progetto di questa serie di articoli e si è impostato l'ambiente di programmazione, visual studio e sqlserver, in cui esso verrà sviluppato.
In questo articolo verrà creato e illustrato il database di esempio, con qualche informazione teorico-pratica suggerita dall'argomento.Creazione attraverso il Management del database di esempio
Prima di tutto creiamo la cartella GesImp che dovrà contenere il progetto e in essa la sottocartella Risorse, destinata ai file di database.Nella colonna di sinistra del Management clicchiamo con il tasto destro sulla voce Database e quindi su Nuovo database.
Nel form che appare impostare come nome APP-P (acronimo di Articolo Primi Passi - Principiante) e nella griglia sottostante indicare come percorso la sottocartella Risorse appena creata.
Ora abbiamo il nostro database vuoto.Tipi di dato
Prima di iniziare a creare le tabelle credo sia utile fare qualche riflessione sui tipi dei dati. Per chi arriva come me da Access è necessario comprendere cosa cambia rispetto a SQL Server e cosa è rimasto sostanzialmente immutato.
- Campi di tipo stringa
.
- In SQL Server abbiamo a disposizione char, nchar, varchar, nvarchar e text.
Cinque tipi di campo per le stringhe a fronte dei due di Access: Testo e Memo.
Testo ha il limite dei 255 caratteri, oltre questi si deve passare al campo Memo, il cui uso, però, data la scarsissima efficienza, è assolutamente deprecabile. Con i cinque tipi di SQL Server si ha maggiore libertà di movimento.- Lasciando da parte per un momento il tipo Text, vediamo le differenze fra char, varchar, nchar e nvarchar:
I campi char e nchar sono a lunghezza fissa, i varchar e nvarchar a lunghezza variabile. Quindi se creo un campo char di lunghezza 10 e un campo varchar anch'esso di lunghezza 10 non occuperanno sempre lo stesso spazio di memoria in quanto per il char la memoria occupata sarà sempre e comunque 10 caratteri, mentre per il varchar 10 caratteri è solo il massimo spazio occupabile: se il contenuto è minore, lo spazio occupato è inferiore.- Un'altra differenza sostanziale è costituita dal tipo di caratteri usato in char/varchar e in nchar/nvarchar: in questi ultimi vengono usati caratteri di tipo UNICODE.
Lo standard UNICODE, a differenza dello standard ANSI, mira a supportare tutti i caratteri dei linguaggi e alfabeti del mondo. UNICODE è ben supportato nei programmi che girano nella galassia Windows, ma non efficacemente nei sistemi UNIX ,IBM, e DOS. La memoria necessaria per memorizzare un carattere UNICODE è doppia (2 byte per carattere) rispetto a quella per i caratteri ANSI (1 byte per carattere). In Sql Server i tipi dati che supportano lo standard UNICODE sono: nchar, nvarchar, ntext. Il prefisso n(national) non è casuale: è stato fissato dallo standard SQL-92. I caratteri codificabili con UNICODE sono oltre 65.000, con ANSI solo 256. Da questo si deduce che se per char/varchar il limite di caratteri memorizzabili è di 8.000 per nchar/nvarchar è di 4.000 usando 2 byte invece di 1.
Se non si ha bisogno di memorizzare stringhe in più lingue (con alfabeti differenti dal nostro) si può utilizzare tranquillamente data type non UNICODE.- Il tipo di campo text è rivolto all'archiviazione di grosse moli di dati: 2.147.483.647 caratteri. Ben più dei 65.535 dei campi Memo di Access, nonché una gestione di gran lunga più efficiente e affidabile.
- Nelle tabelle del database di esempio useremo il tipo di campo char solo per i campi a lunghezza fissa, come può essere un campo dove si desidera salvare il CIN di un conto corrente che, come è noto, è sempre costituito da un carattere. Per tutti gli altri campi di testo useremo il varchar.
- Campi di tipo data
- In SQL Server abbiamo a disposizione datetime (in diverse forme) e smalldatetime. In Access il tipo equivalente è Data/Ora.
- I tipi datetime e smalldatetime contengono sia l'informazione data che l'informazione oraria, ma con validità e precisione differenti:
- datetime ha un intervallo di validità che va dal 1 gennaio 1753 al 31 dicembre 9999 con una precisione pari a 0.00333 secondi. Occupa 8 Bytes (2 coppie di interi di 4 bytes), i primi 4 per la memorizzazione dei giorni prima o dopo l'1 gennaio 1900, gli altri 4 per la memorizzazione dei millisecondi dopo la mezzanotte.
- smalldatetime ha un intervallo di validità che va dal 1 gennaio 1900 al 6 giugno 2079 con una precisione al minuto. Occupa 4 Bytes (2 coppie di interi di 2 bytes), i primi 2 per la memorizzazione dei giorni dopo l'1 gennaio 1900, gli altri 2 per la memorizzazione dei minuti dopo la mezzanotte.
- Nelle tabelle del database di esempio useremo il tipo di campo smalldatetime.
- Campi numerici
- In SQL Server abbiamo a disposizione int, bigint, tinyint, smallint, numeric, real, float e decimal. Dopo alcune ricerche ho dedotto le seguenti equivalenze con i campi numerici che usavo in Access:
SQL Server Access smallint Intero int Intero lungo real Precisione singola float Precisione doppia decimal Decimale - Campi valuta
- E' il tipo che mi ha creato più dubbi per determinare un'equivalenza fra Access e SQL Server. In Access usavo il campo Valuta e, vedendo che SQL Server ha due tipi come smallmoney e money, ho pensato inizialmente di utilizzare quest'ultimo. Provando ad inserire dei dati ho però notato un comportamento che non mi andava bene. Per esempio, una cifra come 5.478,17873 (che potrebbe risultare da un calcolo effettuato a runtime), in un campo di tipo money viene salvata solo come 5.478,1787. Questo non sta bene se si vuole che la cifra sia conforme all'Euro (cinque decimali di precisione). Tra l'altro, io vorrei che fosse salvato 5.478,18. Ho rinunciato pertanto ai campi di tipo money e ai loro 4 numeri fissi dopo la virgola. Al loro posto ho optato per il tipo decimal.
Anche in questo caso ho avuto delle difficoltà a capire come funzionasse la precisione e la scala. Riporto da TechNet: "La precisione è il numero di cifre di cui è composto un numero. La scala è il numero di cifre a destra del separatore decimale in un numero. Il numero 123,45, ad esempio, ha una precisione pari a 5 e una scala pari a 2". Dopo avere letto, come è stato per me, credo che ora sia chiaro come funzionano i due parametri.- In conclusione per i campi valuta uso il tipo decimal con precisione 13 e scala 2.
- Campi booleani
- In SQL Server al posto del tipo Yes/No di Access si usa il tipo bit. Questo tipo accetta i valori 0 o 1. In realtà possono essere usati anche altri numeri, ma verranno comunque interpretati come 1.
A parte, in Tabella1, ho compilato l'elenco dei tipi di dato messi a disposizione da SQL Server, divisi opportunamente per categoria, con relativa descrizione. In realtà con SQL 2008 mi sembra che siano stati aggiunti altri tipi di dati ma, visto che il mio approccio a SQL Server è ancora troppo recente, non voglio cimentarmi in un aggiornamento dell'elenco sottostante.
Mi sembra interessante riportare anche due tabelle che ho trovato durante le mie ricerche. La prima riporta le equivalenze fra i tipi di Access e quelli di SQL Server. La seconda, oltre a fornire lo stesso servizio in modo più schematico, mappa i tipi fra Visual Basic 6, Access, SQL Server e il .NET Framework.
Sono in inglese, ma il tutto è ugualmente facilmente comprensibile, a chi ne ha una minima infarinatura.
Per tutte e tre le tabelle purtroppo non ricordo le fonti, pertanto mi scuso con i creatori se non li cito.Creazione Tabelle
Apriamo la struttura ad albero dei Database, quella del database APP-P, quindi clicchiamo con il tasto destro su Tabelle selezionando poi Nuova tabella.
Siamo entrati nella progettazione della nuova tabella.
Creiamo i campi seguenti:
Nome Tipo Consenti
valori
NullStato varchar(30) No Modifica bit Si Il campo Stato è chiave univoca. La chiave univoca di una tabella si crea selezionando il o i campi necessari e cliccando sull'apposito pulsante "Imposta chiave primaria", contraddistinto dall'icona a forma di chiave, posizionato in alto sopra la colonna Esplora oggetti.
Devo aprire una piccola parentesi per spiegare il significato che avrà il campo Modifica. Questo campo me lo porto dietro da Visual Basic 6 e Access. Lo uso per gestire la concorrenza durante l'uso simultaneo del programma da parte di più utenti. Non ho mai voluto usare i blocchi di record, un po' perché complicati da gestire, un po' perché sconsigliati da molti. Ho optato quindi per una gestione "artigianale" della concorrenza.
In pratica, quando un utente entra in modifica su un record imposto a vero il campo Modifica dello stesso e lo riporto a falso quando lo stesso utente conferma l'operazione oppure l'annulla. Nel frattempo il record è bloccato. In Visual Basic 6 in realtà lanciavo un semplice avviso a video senza bloccare ma in NET ho preferito bloccarlo proprio. Tutte le form che creo hanno comunque in dotazione un pulsante di emergenza per lo sblocco: se per caso va via la corrente mentre un record è in modifica e il capo rimane impostato vero.La prima tabella è fatta. Si può salvarla e nominarla Stati.
Questa è la procedura standard da seguire per ciascuna delle tabelle di cui si illustra la struttura, prima di salvare e dare il nome.Nuova Tabella. I campi da creare sono i seguenti:
Nome Tipo Consenti
valori
NullBanca varchar(50) No Agenzia varchar(50) No ABI varchar(10) Si CAB varchar(10) Si Swift varchar(15) Si Indirizzo varchar(50) Si CAP varchar(5) Si Citta varchar(50) Si Provincia varchar(4) Si Stato varchar(30) Si Telefono varchar(25) Si Fax varchar(25) Si Modifica bit Si La chiave univoca è rappresentata dalla coppia di campi Banca e Agenzia.
([Diego]: avrei preferito un campo Int di nome IDbanca, come altrettanto avrei preferito un campo IDstato per la tabella Stati. Un indice primario su un campo di testo è particolarmente costoso e certamente meno efficiente di uno su un campo di tipo 'nativo' come il tipo Intero Lungo.
Inoltre, ABI e CAB hanno una lunghezza fissa minore di 10. Volendo si potrebbe normalizzare ulteriormente per province e città)Avendo già creato in precedenza la tabella Stati e avendo questa tabella, fra gli altri, il campo Stato possiamo creare una relazione fra le due tabelle. Il rapporto fra Stati e Banche sarà naturalmente di uno a molti.
Per creare la relazione, essendo ancora in progettazione della tabella Banche, clicchiamo sul relativo pulsante "Relazioni" contraddistinto dall'icona con tre form collegate fra loro, sempre posizionato sopra la colonna Esplora oggetti.
Appare un form denominato "Relazioni chiave esterne". Selezioniamo la proprietà "Specifica tabelle e colonne", quindi clicchiamo sul pulsante con i tre puntini.
Apparirà un nuovo form denominato "Tabelle e colonne". Nell'elenco a tendina "Tabella di chiave primaria" selezioniamo la tabella Stati; nella griglia sottostante selezioniamo il campo Stato sia in corrispondenza della tabella Stati che di quella Banche.
Come avrete notato il nome della relazione è stato costruito in modo appropriato automaticamente.Una scelta che avevo già fatto in Access è quella relativa agli automatismi che sia Access che SQL Server mettono a disposizione nel momento in cui si crea una relazione fra tabelle. Sto parlando del lasciar verificare la congruenza dei dati al database. Come avrete notato, fra le altre ci sono tre proprietà impostate a Si che io voglio portare a No, ovvero:
- Verifica dati esistenti durante la creazione o la riabilitazione
Supponendo di avere due tabelle (Clienti e Clienti_riferimenti) unite da una relazione uno a molti, impedisce per esempio che si possa inserire una persona di riferimento per un cliente che non ha un record corrispondente nella tabella Clienti- Attiva per replica
Non ho mai usato le repliche e pertanto lo disattivo. Motivo stupido? Può darsi ma preferisco disattivarlo. Riporto comunque da MSDN: " Indica se applicare il vincolo quando un agente di replica esegue un'inserimento o un aggiornamento in questa tabella"- Attiva vincolo della chiave esterna
Riporto anche qui da MSDN: " Indica se le modifiche ai dati delle colonne coinvolte nella relazione sono consentite quando rischiano di compromettere l'integrità della relazione di chiave esterna". A fronte di quanto già detto sopra mi sembra abbastanza chiaroInoltre richiamo l'attenzione sulla proprietà Specifica INSERT e UPDATE che a sua volta si suddivide in Regola di aggiornamento e regola di eliminazione. Entrambi li lasceremo impostati a "Nessuna azione". A cosa servono? Riporto anche qui da TechNet in quanto mi sembra ben spiegato:
- Regola di eliminazione
Specifica che cosa accade se un utente tenta di eliminare una riga contenente dati coinvolti in una relazione di chiave esterna:
- Nessuna azione
Un messaggio di errore indica che l'eliminazione non è consentita e viene eseguito il rollback dell'operazione DELETE- Sovrapponi
Elimina tutte le righe che contengono dati coinvolti nella relazione di chiave esterna.
Non specificare CASCADE se la tabella verrà inclusa in una pubblicazione di tipo merge che utilizza record logici- Imposta Null
Imposta il valore su Null se tutte le colonne di chiave esterna della tabella possono accettare valori Null. Non applicabile a SQL Server 2000- Imposta predefinito
Imposta il valore predefinito per la colonna se per tutte le colonne di chiave esterna della tabella sono stati impostati valori predefiniti. Non applicabile a SQL Server 2000- Regola di aggiornamento
Specifica ciò che accade se un utente tenta di aggiornare una riga contenente dati coinvolti in una relazione di chiave esterna:
- Nessuna azione
Un messaggio di errore indica che l'aggiornamento non è consentito e viene eseguito il rollback dell'operazione UPDATE- Sovrapponi
Aggiorna tutte le righe che contengono dati coinvolti nella relazione di chiave esterna.
Non specificare CASCADE se la tabella verrà inclusa in una pubblicazione di tipo merge che utilizza record logici- Imposta Null
Imposta il valore su Null se tutte le colonne di chiave esterna della tabella possono accettare valori Null. Non applicabile a SQL Server 2000- Imposta predefinito
Imposta il valore predefinito definito per la colonna se per tutte le colonne di chiave esterna della tabella sono stati impostati valori predefiniti. Non applicabile a SQL Server 2000Vi starete dicendo ... "ma così hai eliminato tutti gli automatismi". E' vero! Tutte queste cose preferisco controllarmele da codice. Non voglio che "qualcun'altro" lo faccia per me. Come scrivevo nell'introduzione sono uno al quale piace avere pieno controllo del flusso del codice, anche se questo va a penalizzarmi costringendomi a scrivere del codice in più.
([Diego]: con SqlServer ci si può ragionevolmente fidare, di alcuni automatismi, ma in questo caso l'impostazione a 'nessuna azione' ci conviene.
Questa struttura riprende, evidentemente, una struttura già sperimentata su un database Access.
Si vedrà nel seguito se ci riesce di applicare modifiche alla struttura del database. Poiché è una situazione abbastanza 'normale', esamineremo le problematiche sovvenienti al momento giusto.
Per il momento mi limiterò a fare qualche critica, quando è il caso)In tutte le tabelle che seguiranno queste proprietà andranno impostate in questo modo.
Confermiamo l'operazione e salviamo la relazione.
Si può ora salvare la tabella e nominarla Banche.Nuova Tabella. I campi da creare sono i seguenti:
Nome Tipo Consenti
valori
NullPagamento varchar(50) No Fine_mese bit Si Giorno_fisso smallint Si Appoggio_banca bit Si Modifica bit Si La chiave univoca è il campo Pagamento ([Diego]: anche qui è preferibile una chiave IDpagamento).
Salvare la tabella e nominarla Pagamenti.Nuova Tabella. I campi da creare sono i seguenti:
Nome Tipo Consenti
valori
NullPagamento varchar(50) No Scadenza smallint No Percentuale real No La chiave univoca è rappresentata dalla coppia di campi Pagamento e Scadenza ([Diego]: così non si sfrutta bene le capacità di sqlserver: è molto più performante un indice su due Int che su qualsiasi altro tipo, se poi sono due tipi diversi tra loro...).
Questa tabella, come facilmente si può intuire, è legata con la precedente da una relazione Master/Detail. Creiamo la relazione indicando come campo comune alle due tabelle il campo Pagamento.
Salvare la tabella e nominarla Pagamenti_dettaglio.Nuova Tabella. I campi da creare sono i seguenti:
Nome Tipo Consenti
valori
NullCodice int No Nome varchar(50) No Indirizzo varchar(50) No CAP varchar(5) Si Citta varchar(50) No Provincia varchar(4) Si Stato varchar(30) Si Telefono varchar(25) Si Fax varchar(25) Si Cellulare varchar(25) Si Telefono1 varchar(25) Si Fax1 varchar(25) Si Cellulare1 varchar(25) Si Codice_fiscale varchar(16) Si Partita_iva varchar(13) Si Pagamento varchar(50) Si Banca varchar(50) Si Agenzia varchar(50) Si ABI varchar(10) Si CAB varchar(10) Si NumCC varchar(15) Si TitCC varchar(30) Si CIN char(1) Si IBAN varchar(35) Si Internet varchar(50) Si varchar(50) Si Riclis real Si Oratecs decimal(13, 2) No Oratecsstr decimal(13, 2) No Oratec decimal(13, 2) No Oratecstr decimal(13, 2) No Oraaiu decimal(13, 2) No Oraaiustr decimal(13, 2) No Modifica bit Si La chiave univoca è il campo Codice ([Diego]: perché mai un nome così generico? Io l'avrei chiamato IDcliente. Inoltre, mi danno fastidio i nomi non autodescrittivi come Riclis e Oraxxx).
Vanno create le relazioni fra questa tabella e alcune di quelle create in precedenza e più nello specifico (rapporto uno a molti):
- Banche / Clienti
Aprire in modifica (versione 2005) o in progettazione (versione 2008) la tabella Banche, visualizziamo le relazioni e impostiamo come campi comuni alle due tabelle Banca e Agenzia.- Pagamenti / Clienti
Aprire in modifica (versione 2005) o in progettazione (versione 2008) la tabella Pagamenti, visualizziamo le relazioni e impostiamo come campo comune Pagamento- Stati / Clienti
Aprire in modifica (versione 2005) o in progettazione (versione 2008) la tabella Stati, visualizziamo le relazioni e impostiamo come campo comune StatoSalvare la tabella e nominarla Clienti.
Nuova Tabella. I campi da creare sono i seguenti:
Nome Tipo Consenti
valori
NullCodice int No Riferimento varchar(50) No Telefono varchar(25) Si Fax varchar(25) Si Cellulare varchar(25) Si varchar(50) Si La chiave univoca è rappresentata dalla coppia di campi Codice e Riferimento ([Diego]: se uno non sa a priori a cosa si riferisce codice, che ne può capire? se il campo si chiamasse IDcliente, sarebbe chiaro, anche fra tre anni).
Questa tabella è legata con la tabella Clienti da una relazione Master/Detail. Creiamo la relazione indicando come campo comune alle due tabelle il campo Codice.
Salvare la tabella e nominarla Clienti_riferimenti.Nuova Tabella. I campi da creare sono i seguenti:
Nome Tipo Consenti
valori
NullCodice int No Nome varchar(50) No Indirizzo varchar(50) No CAP varchar(5) Si Citta varchar(50) No Provincia varchar(4) Si Stato varchar(30) Si Telefono varchar(25) Si Fax varchar(25) Si Cellulare varchar(25) Si La chiave univoca è rappresentata dai campi Codice ([Diego]: visto? un campo omonimo di un altro. Non ci sarebbe ambiguità se ognuno fosse 'chiaro', come IDsede, per esempio qui), Nome ([Diego]: altro nome generico, mentre con un minimo di fantasia si può denominare il campo Sede) e Citta.
Questa tabella è legata con la tabella Clienti da una relazione Master/Detail.
Creiamo la relazione indicando come campo comune alle due tabelle il campo Codice.
Salvare la tabella e nominarla Clienti_sedi.Nuova Tabella. I campi da creare sono i seguenti:
Nome Tipo Consenti
valori
NullCodice int No Nome varchar(50) No Indirizzo varchar(50) No CAP varchar(5) Si Citta varchar(50) No Provincia varchar(4) Si Stato varchar(30) Si Telefono varchar(25) Si Fax varchar(25) Si Cellulare varchar(25) Si Telefono1 varchar(25) Si Fax1 varchar(25) Si Cellulare1 varchar(25) Si Codice_fiscale varchar(16) Si Partita_iva varchar(13) Si Pagamento varchar(50) Si Banca varchar(50) Si Agenzia varchar(50) Si ABI varchar(10) Si CAB varchar(10) Si NumCC varchar(15) Si TitCC varchar(30) Si CIN char(1) Si IBAN varchar(50) Si Internet varchar(50) Si varchar(50) Si Modifica bit Si La chiave univoca è il campo Codice ([Diego]: IDfornitore..., inoltre, a me danno fastidio i nomi di capo non autodescrittivi, come NumCC e TitCC).
Vanno create le relazioni fra questa tabella e alcune di quelle create in precedenza:
- Banche / Fornitori
Apriamo in modifica (versione 2005) o in progettazione (versione 2008) la tabella Banche, visualizziamo le relazioni e impostiamo come campi comuni alle due tabelle Banca e Agenzia.- Pagamenti / Fornitori
Apriamo in modifica (versione 2005) o in progettazione (versione 2008) la tabella Pagamenti, visualizziamo le relazioni e impostiamo come campo comune Pagamento- Stati / Fornitori
Apriamo in modifica (versione 2005) o in progettazione (versione 2008) la tabella Stati, visualizziamo le relazioni e impostiamo come campo comune StatoSalvare la tabella e nominarla Fornitori.
Nuova Tabella. I campi da creare sono i seguenti:
Nome Tipo Consenti
valori
NullCodice int No Riferimento varchar(50) No Telefono varchar(25) Si Fax varchar(25) Si Cellulare varchar(25) Si varchar(50) Si La chiave univoca è rappresentata dalla coppia di campi Codice e Riferimento.
Questa tabella è legata con la tabella Fornitori da una relazione Master/Detail. Creiamo la relazione indicando come campo comune alle due tabelle il campo Codice.
Salvare la tabella e nominarla Fornitori_riferimenti.Nuova Tabella. I campi da creare sono i seguenti:
Nome Tipo Consenti
valori
NullUM varchar(5) No Modifica bit Si La chiave univoca è il campo UM.
Salvare la tabella e nominarla Unita_di_misura.Nuova Tabella. I campi da creare sono i seguenti:
Nome Tipo Consenti
valori
NullCodice varchar(20) No Prodotto varchar(50) No UM varchar(5) No Preacq decimal(13, 2) Si Preven decimal(13, 2) Si Quantita float Si Acquisto bit Si Vendita bit Si Stampa bit Si Modifica bit Si La chiave univoca è il campo Codice ([Diego]: IDprodotto, nomi non autodescrittivi come Preacq e Preven).
Va creata la relazione (uno a molti) fra questa tabella e la tabella Unita_di_misura:
- Unita_di_misura / Prodotti
Apriamo in modifica (versione 2005) o in progettazione (versione 2008) la tabella Unita_di_misura, visualizziamo le relazioni e impostiamo come campo comune alle due tabelle UMSalvare la tabella e nominarla Prodotti.
Nuova Tabella. I campi da creare sono i seguenti:
Nome Tipo Consenti
valori
NullData smalldatetime No Numero varchar(20) No Codfor int No Fornitore varchar(50) No Modifica bit Si La chiave univoca è rappresentata dai campi Data, Numero e Codfor.
Va creata la relazione fra questa tabella e la tabella Fornitori (rapporto uno a molti):
- Fornitori / Carico_magazzino
Aprire in modifica (versione 2005) o in progettazione (versione 2008) la tabella Fornitori, visualizziamo le relazioni e impostiamo come campo della tabella Carico_magazzino, Codfor e come campo della tabella Fornitori, Codice ([Diego]: se il campo della tabella Fornitori fosse denominato IDfornitore, non ci sarebbe alcun problema di ambiguità, non ci si troverebbe a dover inventare un nome come CodFor).Salvare la tabella e nominarla Carico_magazzino.
Nuova Tabella. I campi da creare sono i seguenti:
Nome Tipo Consenti
valori
NullData smalldatetime No Numero varchar(20) No Codfor int No Codice varchar(20) No Prodotto varchar(50) No UM varchar(5) No Quantita float No Preacq decimal(13, 2) No Preven decimal(13, 2) No La chiave univoca è rappresentata dai campi Data, Numero, Codfor e Codice (prodotto) ([Diego]: se si fosse chiamato IDprodotto, non ci sarebbe stato bisogno di specificare).
Deve essere creata la relazione Master/Detail con la tabella Carico_magazzino. Creiamo la relazione indicando come campi comuni alle due tabelle Data, Numero e Codfor.
Inoltre va creata la relazione fra questa tabella e la tabella creata in precedenza Prodotti (rapporto uno a molti):
- Prodotti / Carico_prodotti
Apriamo in modifica (versione 2005) o in progettazione (versione 2008) la tabella Prodotti, visualizziamo le relazioni e impostiamo come campo comune alle due tabelle Codice.Salvare la tabella e nominarla Carico_prodotti.
Conclusione
Abbiamo terminato di creare la base dati necessaria al nostro esempio.
Nel prossimo articolo della serie passeremo finalmente al Visual Basic e alla creazione del nuovo progetto.