Newsgroup: it.comp.lang.visual-basic
Titolo: [DAO3.5] Chiavi, indici e relazioni....

Ciao a tutti,
Volevo creare un database MDB relazionale. Questo è banale farlo "a
mano" con Access ,ma per portabilità volevo fare tutto in VB.
Per prova il db contiene 3 tabelle.
Una tabella è un anagrafica ANCONTATTO che è associata con la DTVENDITA e
l'altra è TBTIPOPRODOTTO è una semplice tabella con i vari tipi di prodotto
che alimenta un dettaglio di DTVENDITA.
Schema:
ANCONTATTO:
--------------
CODCONTATTO    Campo a chiave primaria, unica
RAGSOC
INDIRIZZO
DTVENDITA:
------------
ID_VENDITA        Campo 1 della chiave primaria composta, unica
CODCONTATTO    Campo 2 della chiave primaria composta, unica
CODTIPOPROD     Campo a chiave esterna, non unica
NUMEROITEM
COSTOITEM
TBTIPOPRODOTTO:
------------------
CODTIPOPROD     Campo a chiave primaria, unica)
DESCRPRODOTTO
Le relazioni sarebbero queste:
ANCONTATTO 1 ------ m DTVENDITA m ------ 1 TBTIPOPRODOTTO
Quello che mi serve sono dei suggerimenti su come realizzare la creazione di
questa struttura. In particolare so già fare la creazione
dell'archivio, delle tabelle. Impostare gli indici ma solo come campo a
chiave primaria. Non so come creare una chiave primaria composta (vedi caso
DTVENDITA). Non so creare le relazioni (ma solo perchè mi sono bloccato
sugli indici).
Chi mi da una mano?
Sono ben accetti sia riferimenti a buoni libri, soprattutto esempi concreti
:-) ma anche idee per realizzarlo nel complesso (quali controlli ecc.).
Tra l'altro questo programmetto, una volta realizzato, potrebbe essere
anche un mini tutorial da mettere in comune (credo ci sia un sito...)
per quelli che come me inizieranno a sviluppare su DB relazionali senza
usare access.
Grazie,
            Mandru70

 wrote in message 7snsp1$gj$1...@nslave1.tin.it...

Sull'help in linea trovi tutto cio' che ti serve, cerca gli oggetti
DBEngine, Database, Field, Relation (tutti oggetti relativi a DAO). Se,
invece, stai usando ADO, c'e' una libreria aggiuntiva (ADOX) che e' dedicata
alla creazione e definizione dei database.
--
Roal Zanazzi
z...@iol.it

Non so se ti sara' chiaro, ma copia questo codice in un Form nuovo ed
esegui. Osservando il DB da Access non dovrebbe essere difficile comprendere
le regole che stai cercando. Forse.
P.S. imposta un riferimento a Microsoft ADO Ext. 2.1 e Microsoft ActiveX
Data Object 2.1 library
Un saluto a tutti
Roberto Bergonzini
Option Explicit
Public NuovoCatalogo As New ADOX.Catalog
Public StringaDiConnessione As String
Private Sub Form_Load()
    StringaDiConnessione = "Provider=Microsoft.Jet.OLEDB.4.0;Data
Source=C:\prova.mdb;"
'INIZIO Creazione del Database (ovviamente è vuoto)
    NuovoCatalogo.Create StringaDiConnessione
    Set NuovoCatalogo = Nothing
'Ora apro una connessione al database e creo le tabelle con indici e
relazioni
    Dim cnn As ADODB.Connection
    Set cnn = New ADODB.Connection
    With cnn
        .ConnectionString = StringaDiConnessione
        .Open
    End With
'TABELLA TEMPISCUOLA-------------------------------------------------
'ID tipo diventa contatore che parte da 1 e si incrementa di 1
(IDENTITY(1,1)) e nello stesso tempo anche chiave primaria unica Primary Key
NOT NULL UNIQUE
    cnn.Execute "CREATE TABLE TempiScuola (" & _
                    "[IDTipo] Int IDENTITY(1,1) Primary Key NOT NULL
UNIQUE," & _
                    "[Descrizione]CHAR(30) NOT NULL);"
'--------------------------------------------FINE TABELLA TEMPISCUOLA
'TABELLA CLASSI------------------------------------------------------
    cnn.Execute "CREATE TABLE Classi (" & _
                    "[Classe] CHAR (4) Primary Key NOT NULL UNIQUE," & _
                    "[IDTipo] int NOT NULL," & _
                    "CONSTRAINT TempiScuola_CLassi FOREIGN KEY (IDTipo)
REFERENCES TempiScuola);"
'CONSTRAINT crea una RELAZIONE 1 a Molti tra le tabelle TempiScuola-->Classi
tra i campi IDTipo
'-------------------------------------------------FINE TABELLA CLASSI
'TABELLA DOCENTI----------------------------------------------------
    cnn.Execute "CREATE TABLE Docenti (" & _
                    "[IDDocente] int IDENTITY(1,1)Primary Key NOT NULL
UNIQUE," & _
                    "[Nome] int NOT NULL," & _
                    "[OreSett] tinyint NOT NULL," & _
                    "[IDGiornoLibero] tinyint);"
'-----------------------------------------------FINE TABELLA DOCENTI
'TABELLA CLASSIDOCENTI-----------------------------------------------
    cnn.Execute "CREATE TABLE ClassiDocenti (" & _
                    "[IDDocente] int ," & _
                    "[Classe]char(4)," & _
                    "CONSTRAINT PkClassiDocenti PRIMARY KEY(IDDocente,
Classe)," & _
                    "CONSTRAINT Classi_ClassiDocenti FOREIGN KEY (Classe)
REFERENCES CLassi," & _
                    "CONSTRAINT Docenti_ClassiDocenti FOREIGN KEY
(IDDocente) REFERENCES Docenti);"
'la prima CONSTRAINT crea una chiave composta da IDDocente e Classe
'la penultima CONSTRAINT crea una Relazione 1 a molti tra le tabelle
Classi -> ClassiDocenti tra i campi Classe
'l'ultima CONSTRAINT crea una Relazione 1 a molti tra le tabelle Docenti ->
ClassiDocenti tra i campi IDDocente
'-----------------------------------------FINE TABELLA CLASSIDOCENTI
End Sub


Chiedo scusa per il precedente messaggio. Che sbadato 8( non ho notato [DAO
3.5] e ho spedito un esempio per ADO.
Probabilmente, ma non sono sicuro, funziona anche con DAO, ovviamente solo
il codice che scrive tramite stringhe SQL le tabelle e gli indici.


mano" con Access ,ma per portabilità volevo fare tutto in VB.
Ho preso il tuo sorgente da it.binari.visual-basic e ho apportato solo
alcune piccole modifiche come il set a nothing degli oggetti che sono
utilizzati come appoggio per la creazione dopo il loro utilizzo. Ho ordinato
un pò la sequenza dei comandi, anche se forse andava bene come era prima.
Gli errori mi sembravano solamente su due istruzioni e precisamente
1) nell' "Append" di un "Field" della chiave dovresti usare il "CreateField"
relativo all'indice :
        idxIndice.Fields.Append idxIndice.CreateField("CODCONTATTO",
dbInteger)
oppure all'interno del With
          .Fields.Append .CreateField("CODTIPOPROD", dbInteger)
  2)  nell'assegnazione della proprietà nella prima relazione hai usato il
campo "CODTIPOPROD" che non esiste invece del "CODCONTATTO"
    relNew.Fields("CODTIPOPROD").ForeignName = "CODCONTATTO"
    relNew.Fields!CODCONTATTO.ForeignName = "CODCONTATTO"
Allego comunque tutta la routine che mi sembra interessante anche per altri
vista la tua disponibilità a renderlo pubblico.
Saluti
Private Sub Form_Load()
On Error Resume Next
Dim FileArchivio As String
Dim PathArchivio As String
Dim tdfTab As TableDef
Dim fldCampo As Field
Dim idxIndice As Index
Dim idxContatto As Index
Dim idxTipoProd As Index
Dim relNew As Relation
'Verifico la presenza del database, se non esiste lo creo
FileArchivio = "ARCHIVIO.MDB"
PathArchivio = App.Path
If (Dir(PathArchivio + "\" + FileArchivio) = FileArchivio) Then
Else
    'Creo un nuovo database nella directory di lavoro di nome ARCHIVIO.MDB
    MsgBox "Il file " + FileArchivio + " non esiste!" + vbCrLf + "Creo un
nuovo database.", vbInformation, "MESSAGGIO - MandruDB v1.0"
    Set wrkDefault = DBEngine.Workspaces(0)
    Set dbArchivio = wrkDefault.CreateDatabase(FileArchivio, dbLangGeneral)
    MsgBox "Creo la tabella ANCONTATTO nel nuovo database.", vbInformation,
"MESSAGGIO - MandruDB v1.0"
    ' *** Creo la tabella ANCONTATTO del database
    Set tdfTab = dbArchivio.CreateTableDef("ANCONTATTO")
    With tdfTab
        ' *** Aggiunta campi
        .Fields.Append .CreateField("CODCONTATTO", dbInteger)
        .Fields.Append .CreateField("RAGSOC", dbText, 40)
        .Fields.Append .CreateField("INDIRIZZO", dbText, 50)
        .Fields.Append .CreateField("TELCASA", dbText, 14)
        .Fields.Append .CreateField("TELUFFI", dbText, 14)
        .Fields.Append .CreateField("TELCELL", dbText, 14)
        .Fields.Append .CreateField("TELFAX", dbText, 14)
        .Fields.Append .CreateField("EMAIL", dbText, 50)
        .Fields.Append .CreateField("PAGWEB", dbText, 50)
        .Fields.Append .CreateField("NOTE", dbMemo)
        ' *** Crazione del campo a chiave primaria, unica ***
        Set idxIndice = tdfTab.CreateIndex("CODCONTATTO")
        idxIndice.Fields.Append idxIndice.CreateField("CODCONTATTO",
dbInteger)
        idxIndice.Primary = True
        idxIndice.Unique = True
        .Indexes.Append idxIndice
        Set idxIndice = Nothing
    End With
    dbArchivio.TableDefs.Append tdfTab
    Set tdfTab = Nothing
    'Creo la tabella DTVENDITA del database
    MsgBox "Creo la tabella DTVENDITA nel nuovo database.", vbInformation,
"MESSAGGIO - MandruDB v1.0"
    Set tdfTab = dbArchivio.CreateTableDef("DTVENDITA")
    With tdfTab
        .Fields.Append .CreateField("IDVENDITA", dbInteger)
        .Fields.Append .CreateField("CODCONTATTO", dbInteger)
        .Fields.Append .CreateField("CODTIPOPROD", dbInteger)
        .Fields.Append .CreateField("NUMITEM", dbInteger)
        .Fields.Append .CreateField("COSTITEM", dbInteger)
        ' *** Crazione del campo a chiave primaria mista  ***
        Set idxIndice = .CreateIndex("IDVENDITA")
        With idxIndice
            .Fields.Append .CreateField("IDVENDITA", dbInteger)
            .Fields.Append .CreateField("CODCONTATTO", dbInteger)
            .Primary = True
            .Unique = True
        End With
        .Indexes.Append idxIndice
        Set idxIndice = Nothing
        ' *** Crazione del campo a chiave esterna ***
        Set idxIndice = .CreateIndex("CODTIPOPROD")
        idxIndice.Fields.Append idxIndice.CreateField("CODTIPOPROD",
dbInteger)
        .Indexes.Append idxIndice
        Set idxIndice = Nothing
    End With
    dbArchivio.TableDefs.Append tdfTab
    Set tdfTab = Nothing
    'Creo la tabella TBTIPOPROD del database
    MsgBox "Creo la tabella TBTIPOPROD nel nuovo database.", vbInformation,
"MESSAGGIO - MandruDB v1.0"
    Set tdfTab = dbArchivio.CreateTableDef("TBTIPOPROD")
    With tdfTab
        .Fields.Append .CreateField("CODTIPOPROD", dbInteger)
        .Fields.Append .CreateField("DESCRTIPOPROD", dbText, 30)
        Set idxIndice = .CreateIndex("CODTIPOPROD")
        With idxIndice
            .Fields.Append .CreateField("CODTIPOPROD", dbInteger)
            .Primary = True
            .Unique = True
        End With
        .Indexes.Append idxIndice
        Set idxIndice = Nothing
    End With
    dbArchivio.TableDefs.Append tdfTab
    Set tdfTab = Nothing
    MsgBox "Creo relazioni: ANCONTATTO 1-m DTVENDITA m-1 TBTIPOPROD",
vbInformation, "MESSAGGIO - MandruDB v1.0"
    ' *** Creo la RELAZIONE (1 a molti) fra ANCONTATTO e DTVENDITA
    Set relNew = dbArchivio.CreateRelation("Rel_contatto_vendita",
"ANCONTATTO", "DTVENDITA", dbRelationUpdateCascade)
    relNew.Fields.Append relNew.CreateField("CODCONTATTO")
    relNew.Fields!CODCONTATTO.ForeignName = "CODCONTATTO"
    dbArchivio.Relations.Append relNew
    Set relNew = Nothing
    ' *** Creo la RELAZIONE (molti a 1) fra TBTIPOPROD e DTVENDITA
    Set relNew = dbArchivio.CreateRelation("Rel_TipoProd_Vendita",
"TBTIPOPROD", "DTVENDITA", dbRelationUpdateCascade)
    relNew.Fields.Append relNew.CreateField("CODTIPOPROD")
    relNew.Fields!CODTIPOPROD.ForeignName = "CODTIPOPROD"
    dbArchivio.Relations.Append relNew
    dbArchivio.Close
End If
If Err <> 0 Then
    MsgBox "ATTENZIONE! Probabili errori nella creazione del DB",
vbCritical, "ERRORE - MandruDB v1.0"
    End
End If
End Sub

>     Set dbArchivio = wrkDefault.CreateDatabase(FileArchivio,
dbLangGeneral)
su questa istruzione devi inoltre creare l'archivio nella directory
dell'applicazione altrimenti ne testi l'esistenza da una parte e lo crei su
di un'altra !!!!!!!!
Ciao
Ven.

Ringrazio tutti quelli che hanno avuto tempo per rispondermi....
Ho guardato gli indici della DTVENDITA che ho creato assieme alle
altre tabelle in modo manuale con access.
Mi dava allora il seguente schema:
NOME INDICE        NOME CAMPO
-----------------------------------------------------
IDVENDITA           IDVENDITA          (Primario = No, Unico = No)
-----------------------------------------------------
CODCONTATTO     CODCONTATTO    (Primario = No, Unico = No)
-----------------------------------------------------
PrimaryKey       IDVENDITA              (Primario = Si, Unico = Si)
[Chiave Primaria Unica]
                      CODCONT
-----------------------------------------------------
CODTIPOPROD   CODTIPOPROD        (Primario = No, Unico = No)   [Chiave
Esterna]
-----------------------------------------------------
 Allora il l'ho così realizzato:
    '***
    '*** DTVENDITA
    '***
    Set tdfTab = dbArchivio.CreateTableDef("DTVENDITA")
    With tdfTab
        '*** Creo tutti i campi della tabella
        .Fields.Append .CreateField("IDVENDITA", dbInteger)
        .Fields.Append .CreateField("CODCONTATTO", dbInteger)
        .Fields.Append .CreateField("CODTIPOPROD", dbInteger)
        .Fields.Append .CreateField("NUMITEM", dbInteger)
        .Fields.Append .CreateField("COSTITEM", dbInteger)
        ' *** Indicizzo i campi che formeranno la chiave primaria mista
        Set idxIndice = .CreateIndex("IDVENDITA")
        With idxIndice
            .Fields.Append .CreateField("IDVENDITA", dbInteger)
            .Primary = False
            .Unique = False
        End With
        .Indexes.Append idxIndice
        .Indexes.Refresh
        Set idxIndice = .CreateIndex("CODCONTATTO")
        With idxIndice
            .Fields.Append .CreateField("CODCONTATTO", dbInteger)
            .Primary = False
            .Unique = False
        End With
        .Indexes.Append idxIndice
        .Indexes.Refresh
        ' *** Creo la chiave primaria mista associata ai campi
precedentemente indicizzati
        Set idxPrimaryKey = .CreateIndex("PrimaryKey")
        With idxPrimaryKey
            .Fields.Append .CreateField("IDVENDITA", dbInteger)
            .Fields.Append .CreateField("CODCONTATTO", dbInteger)
            .Primary = True
            .Unique = True
        End With
        .Indexes.Append idxPrimaryKey
        .Indexes.Refresh
        ' *** Indicizzo un campo che sarà chiave esterna ***
        Set idxIndice = .CreateIndex("CODTIPOPROD")
        With idxIndice
            .Fields.Append .CreateField("CODTIPOPROD", dbInteger)
            .Primary = False
            .Unique = False
        End With
        .Indexes.Append idxIndice
        .Indexes.Refresh
    End With
    dbArchivio.TableDefs.Append tdfTab
------
OK, spero di non aver toppato! :-)
Adesso mi servirebbe un altro aiuto.
Che controlli devo utilizzare per poter:
1.SCORRERE i Records (una specie di data control collegato ad una
tabella...p.e.)
2.VEDERE i Records (una dbgrid da associare al data control)
Grazie e alla prossima!

Ti ringrazio per le segnalazioni.
Adesso è disponibile in ibv-b il programmetto di esempio con le nuove
correzioni. Adesso funziona davvero tutto.
Pensavo di postare in ibv-b  mano a mano che il progettino progredisce
le versioni funzionanti, sempre allo scopo di demo sul Dao 3.5. Ti va bene?
best regards,
                    Mandru70