U kunt geen record toevoegen of wijzigen

Status
Niet open voor verdere reacties.

so10070

Gebruiker
Lid geworden
4 feb 2014
Berichten
419
Ik krijg de volgende foutmelding: "U kunt geen record toevoegen of wijzigen omdat voor de tabel tblRolgebruikers een gerelateerde record vereist is." (-2147217887 ). Ik heb de volgende relatie uitgebouwd:
tblRolgebruikers > (1>veel) > tblRolgebruikersNiveau > (1>veel) > tblRolgebruikersInstelling > (1>veel) > tblRolgbruikersRechten
Naargelang de selectie uit een keuzemenu maak ik via ADODB een nieuw record in tblRolgebruikers aan. Dit is de code
Code:
    rst1.AddNew
    rst1!rid = Me.pslRID
    rst1!GNNaam = Me.lstNiveau.Column(1)
    rst1.Update
rst1.AddNew >> geen probleeem
rst1.Update >> foutmelding

Wat is het probleem. Ik begrijp het niet. :confused:
 
Het probleem lijkt mij duidelijk; je probeert een niet-compleet record op te slaan waarvoor je dus gegevens mist. Ik snap eerlijk gezegd je procedure zo ook niet; je tabel [tblRolgebruikers] is je hoofdtabel, dus die zou helemaal niks met de andere tabellen te maken hoeven hebben. Waarom je een gekoppeld veld wilt opslaan in een gerelateerde tabel (op dit gegevensniveau) vind ik ook enigszins dubieus. Maar de hele constructie is dus erg onduidelijk. Als je een rolgebruiker toevoegt, dan heb je daarvoor normaal gesproken een aantal tekstvelden voor (de naam bijvoorbeeld) en hooguit wat keuzelijsten voor de gegevens die je voor de rolgebruikers dan weer als stamtabel gebruikt, zoals Afdeling, Manager etc. Maar dus nooit gegevens die er onder hangen.
 
tblRolgebruikers: is dat de koppeltabel tussen de tabel met rollen en de tabel die de gebruikers bevat? Waarom gebruik je voor veld GNNaam (gebruikersnaam?) kolom 1 van de lijst lstNiveau? Meestal bevat kolom 0 de primary key waarde die in de gerelateerde tabel als foreign key waarde wordt ingevuld, terwijl kolom(1) de omschrijving bevat die getoond wordt.
Lijkt de structuur een beetje op:
Classmodel1.jpg

?
 
Ik heb mijn probleem verkeerd gezien en verkeerd uitgelegd. Zie voor de relaties bijgevoegd knipsel. In een niet gekoppeld formulier wil ik de geselecteerde waarden in deze gerelateerde tabellen opslaan (geselecteerd uit een pulldown of een lijst (soms met meervoudige keuze)). Ik doe dit nu als volgt, maar zit met een probleem met het commando rst.AddNew voor elke gerelateerde tabel. Hoe voeg ik in een in een gerelateerde tabel meerdere records in. Als ik hier rst.AddNew als instructie geef, wordt dan in de hoofdtabel niet telkens een record aangemaakt? Ik zit hier een beetje mee in de knoei. :(

Code:
Private Sub butBewaarRolbeheer_Click()
    Dim cnn As ADODB.Connection
    Dim rst As New ADODB.Recordset 'sqlRolbeheer
    Dim sqlRolbeheer As String
    Dim iDoorgeefRID As Long
    Dim varInstelling As Variant
    Dim varThemas As Variant
    Dim strCodeModule As String

    strCodeModule = "frmRolbeheer butBewaarRolbeheer_Click()"

    On Error GoTo foutafhandeling

    sqlRolbeheer = "SELECT tblRolgebruikers.*, tblRolgebruikersNiveau.*, tblRolgebruikersInstelling.*, tblRolgebruikersRechten.*, tblRolgebruikersThemas.* " & _
        "FROM (((tblRolgebruikers INNER JOIN tblRolgebruikersNiveau ON tblRolgebruikers.RId = tblRolgebruikersNiveau.RID) " & _
        "INNER JOIN tblRolgebruikersInstelling ON tblRolgebruikersNiveau.GNID = tblRolgebruikersInstelling.GNID) " & _
        "INNER JOIN tblRolgebruikersRechten ON tblRolgebruikersInstelling.GIID = tblRolgebruikersRechten.GIID) " & _
        "INNER JOIN tblRolgebruikersThemas ON tblRolgebruikersInstelling.GIID = tblRolgebruikersThemas.GIID " & _
        "WHERE tblRolgebruikers.RId = " & iDoorgeefRID & ";"

    Set cnn = CurrentProject.Connection
    rst.Open sqlRolbeheer, cnn, adOpenKeyset, adLockPessimistic

    'Eerst Niveau invullen (slechts 1) [COLOR="#FF0000"][B]>> als ik hier rst.AddNew zet wordt dan in de hoofdtabel tblRolgebruikers niet een nieuw record aangemaak.  Dat wil ik niet. Ik wil hier in de tabel tblRolgebruikersNiveau een nieuw gerelateerd record aanmaken[/B][/COLOR]
    rst!GNNaam = Me.lstNiveau.Column(1)
    
    'Dan alle gekozen instellingen doorlopen (meerkeuze)
    For Each varInstelling In Me.lstInstellingen.ItemsSelected
[B][COLOR="#FF0000"]>> hetzelfde hier: ik wil hier het aantal records aan de tabel tblRolgebruikersInstelling toevoegen als er aangeduid zijn in de lijst.  Wat gebeurt er hier als ik hier ook rst.AddNew zet >> opnieuw in de hoofdtabel aangemaakt.  En hoe doe ik dat dan?[/COLOR][/B]
        rst!GINummer = Me.lstInstellingen.Column(3)
        rst!GINaam = Me.lstInstellingen.Column(2)
        rst!GIOfficieleNaam = Me.lstInstellingen.Column(4)

        'Dan het gebruikersrecht (slechts 1)
        rst!GRNaam = Me.lstGebruikersrechten.Column(0)
        
        'Dan indien in .lstGebruikersrechten "Mijn onderwijs Gebruiker" aangeduid is al de thema's opnemen
        If Me.lstGebruikersrechten.Value = "Mijn Onderwijs Gebruiker" Then
            For Each varThemas In Me.lstThemas.ItemsSelected
                rst!GTNaam = Me.lstThemas.Column(0)
            Next
        End If
        
    Next

    Set rst = Nothing
    Set cnn = Nothing

Exit_Sub:
    Exit Sub
    
foutafhandeling:
    Call FoutenRegistratie(Err.Number, Err.Description, strCodeModule, Environ("Username"))
    Resume Exit_Sub
End Sub
 

Bijlagen

  • Relaties.PNG
    Relaties.PNG
    17,7 KB · Weergaven: 51
Stop maar met deze procedure, want je maakt een paar enorme fouten. Laten we beginnen met de grootste, dan gaan we daarna wel opschonen :).

Punt 1: als je een tabel wilt updaten, dan moet je in essentie alleen die tabel in je recordset opnemen. Jij hebt een query gemaakt met zo’n beetje alle tabellen die je kon vinden :).
Punt 2: (nog belangrijker eigenlijk) als je een tabel wilt updaten, en je gebruikt meerdere tabellen, dan mag je nooit de sleutelvelden opnemen.
Punt 3: het lijkt makkelijk om het * teken te gebruiken om alle velden te selecteren, maar je komt dan dus automatisch in fout 2 terecht. Sowieso neem je dan de koppelveld en dubbel op in de query, en dat resulteert dan in jouw foutmelding.

Samenvattend:
1. als je meerdere tabellen in één procedure wilt updaten, doe dat dan in de juiste volgorde.
2. Gebruik altijd de [veldnamen] om de query te maken. Sowieso heb je die namen nodig in de Edit procedure
3. Neem nooit sleutelvelden mee in de query als je meerdere tabellen gebruikt (wat doorgaans onzinnig is, maar dit terzijde)

Wellicht kun je hier al verder mee. Zo niet: post een voorbeeldje, dat kijkt voor ons een stuk makkelijker.
 
Hallo,

als ik vanuit een ongebonden formulier gegevens wil toevoegen dan maak ik meestal per tabel een klassemodule met o.a. de methodes ADD/DELETE/UPDATE. Een ADD geeft altijd de PK van het nieuwe record terug bij succes, -1 bij failure. Deze kunnen dan in je procedure één voor één opgeroepen worden in de juiste volgorde. Dat lost probleem 1 van Octafish al op.
Van punt 2 heb ik nog nooit gehoord. Integendeel, als je een record wil aanmaken/updaten is het van groot belang dat je wel de vreemde sleutelvelden opneemt, anders kan je die niet aanpassen. Het primaire sleutelveld kan je bij een insert alleen weglaten als het een autonumber is. In alle andere gevallen moet je zeker alle velden opnemen die deel uitmaken van je PK in de insert en zelf invullen met een unieke combinatie.
 
Ik heb dit nu zo gedaan, maar geeft nog dezelfde fout op het rood gemarkeerde. Ik heb nergens de primary key gebruikt maar ook niet de foreign key en dat is verkeerd denk ik? :confused:

Code:
Private Sub butBewaarRolbeheer_Click()
    Dim cnn As ADODB.Connection
    Dim rst1 As New ADODB.Recordset 'sqlRolgebruikers
    Dim rst2 As New ADODB.Recordset 'sqlRolgebruikersNiveau
    Dim rst3 As New ADODB.Recordset 'sqlRolgebruikersInstelling
    Dim rst4 As New ADODB.Recordset 'sqlRolgebruikersRechten
    Dim rst5 As New ADODB.Recordset 'sqlRolgebruikersThemas
    Dim sqlRolgebruikers As String
    Dim sqlRolgebruikersNiveau As String
    Dim sqlRolgebruikersInstelling As String
    Dim sqlRolgebruikersRechten As String
    Dim sqlRolgebruikersThemas As String
    Dim iDoorgeefRID As Long
    Dim varInstelling As Variant
    Dim varThemas As Variant
    Dim strCodeModule As String

    strCodeModule = "frmRolbeheer butBewaarRolbeheer_Click()"

    On Error GoTo foutafhandeling

    sqlRolgebruikers = "SELECT RGebruikerNaam, RGebruikerVoornaam, REmail FROM tblRolgebruikers;"
    sqlRolgebruikersNiveau = "SELECT GNNaam FROM tblRolgebruikersNiveau;"
    sqlRolgebruikersInstelling = "SELECT GINaam, GINummer, GIOfficieleNaam FROM tblRolgebruikersInstelling;"
    sqlRolgebruikersRechten = "SELECT GRNaam FROM tblRolgebruikersRechten;"
    sqlRolgebruikersThemas = "SELECT GTNaam FROM tblRolgebruikersThemas;"

    Set cnn = CurrentProject.Connection
    rst1.Open sqlRolgebruikers, cnn, adOpenKeyset, adLockPessimistic
    rst2.Open sqlRolgebruikersNiveau, cnn, adOpenKeyset, adLockPessimistic
    rst3.Open sqlRolgebruikersInstelling, cnn, adOpenKeyset, adLockPessimistic
    rst4.Open sqlRolgebruikersRechten, cnn, adOpenKeyset, adLockPessimistic
    rst5.Open sqlRolgebruikersThemas, cnn, adOpenKeyset, adLockPessimistic

    'Eerst nieuwe gebruiker aanmaken (slechts 1)
    rst1.AddNew
    rst1!RGebruikerNaam = TempVars.Item("NaamGebruiker")
    rst1!RGebruikerVoornaam = TempVars.Item("VoornaamGebruiker")
    rst1!REmail = TempVars.Item("EmailGebruiker")
    rst1.Update
    
    'Eerst Niveau invullen (slechts 1)
    rst2.AddNew
    rst2!GNNaam = Me.lstNiveau.Column(1)
    [COLOR="#FF0000"][B]rst2.Save >> ook als ik hier rst2.Update zet[/B][/COLOR]
    
    'Dan alle gekozen instellingen doorlopen (meerkeuze)
    For Each varInstelling In Me.lstInstellingen.ItemsSelected
        rst3.AddNew
        rst3!GINummer = Me.lstInstellingen.Column(3)
        rst3!GINaam = Me.lstInstellingen.Column(2)
        rst3!GIOfficieleNaam = Me.lstInstellingen.Column(4)
        rst3.Update
        
        'Dan het gebruikersrecht (slechts 1)
        rst4.AddNew
        rst4!GRNaam = Me.lstGebruikersrechten.Column(0)
        rst4.Update
        
        'Dan indien in .lstGebruikersrechten "Mijn onderwijs Gebruiker" is al de thema's opnemen
        If Me.lstGebruikersrechten.Value = "Mijn Onderwijs Gebruiker" Then
            For Each varThemas In Me.lstThemas.ItemsSelected
                rst5.AddNew
                rst5!GTNaam = Me.lstThemas.Column(0)
                rst5.Update
            Next
        End If
    Next
    
    Set rst1 = Nothing
    Set rst2 = Nothing
    Set rst3 = Nothing
    Set rst4 = Nothing
    Set rst5 = Nothing
    Set cnn = Nothing
    
    TempVars.Remove "NaamGebruiker"
    TempVars.Remove "VoornaamGebruiker"
    TempVars.Remove "EmailGebruiker"

Exit_Sub:
    Exit Sub
    
foutafhandeling:
    Call FoutenRegistratie(Err.Number, Err.Description, strCodeModule, Environ("Username"))
    Resume Exit_Sub
End Sub
 
Als je een nieuwe gebruiker toevoegt en de RID is een autonumber dan kan je dat opvangen door na rst1.update de nieuwe ID in een variabele op te slaan, bv. lngRID = rst1.RID
Deze kan je dan gebruiken in het aanmaken van het niveau:

rst2.AddNew
rst2.RID = lngRID
rst2!GNNAAM = … enz.
 
Noell, het werkt perfect. Thanks! :d Klassenmodules moet ik nog eens serieus tijd in steken om dit onder de knie te krijgen!
 
Het hele principe van niet-gebonden formulieren met recordsets staat uitgebreid beschreven in de Access cursus in de Handleidingen sectie :).
 
Status
Niet open voor verdere reacties.
Terug
Bovenaan Onderaan