Ik wil in Microsoft SQL Server 2000 een foreign key maken naar 2 kolommen, maar dat is niet toegestaan. Het probleem is wat uitgebreider, maar gegeneraliseerd komt het hier op neer; twee tabellen:
dbo.Rekening:
Rekeningnr (int, PK)
…
dbo.Instellingen
DefaultRekeningInkoop (int)
DefaultRekeningVerkoop (int)
…
Ik kan een Forgein Key maken van dbo.Rekening.Rekeningnr naar dbo.Instellingen.DefaultRekeningInkoop. Het fijne is dan dat als het rekeningnr wordt geupdate, dat dan dit wordt meegenomen in de instellingen. (Uiteraard On delete no action, anders ben ik straks al mijn instellingen kwijt
)
Hetzelfde wil ik ook voor DefaultRekeningVerkoop, door nog een Foreign Key te definiëren van Rekeningnr naar DefaultRekeningVerkoop maar dit mag niet, want MSSQL geeft dan aan dat er dan een loop in de boom van cascaded updates zit (error: Introducing FOREIGN KEY constraint 'FK_Instellingen_Rekening1' on table 'Instellingen' may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints.). Jammer maar helaas, het is niet mogelijk
Volgens mij kan dit alleen opgelost worden door een trigger op dbo.Rekening te plaatsen. In een “For update” trigger op dbo.Rekening voer ik dan zelf de updates door (zie onderaan). Hiervoor moet ik de Foreign-Keys verwijderen, omdat anders de foreign-key de update ook wil doorvoeren (error: Another user has modified the contents of this table or view; the database row you are modifying no longer exists in the database).
Nu ik het probleem verder heb lopen specificeren om een mooie post te maken, heb ik het al uitgevoerd op de bovenstaande manier, omdat ik met een beetje testen het gewenste resultaat kreeg
. Maar toch krijg ik een beetje jeuk:
Adequate oplossing?
Als ik beide DefaultX-kolommen door een trigger laat updaten, ziet niemand dat die velden in dbo.Instellingen afhankelijk zijn van dbo.Rekening. Ik moet dan de documentatie goed maken om te voorkomen dat mensen rare dingen gaan doen met de DefaultRekeningen.
Ook kan ik ervoor kiezen om voor DefaultRekeningInkoop een trigger te plaatsen en voor DefaultRekeningVerkoop de Foreign-key te laten staan, maar dan ben ik inconsitent bezig en zal ik het ook goed moeten documenteren. Hoe zal ik het aanpakken? Dit moet toch een vrij standaard probleem zijn?
Inconsitentie?
De database kan nu, vanwege het gebrek aan Foreign keys, inconsitente gegevens bevatten door in DefaultRekeningVerkoop een willekeurig nummer te plaatsen. Moet ik nou ook op dbo.Instellingen een trigger plaatsen die de inhoud vergelijkt met dbo.Rekening, of is er een andere weg mogelijk –misschien toch met Foreign keys-?
p.s. sinds deze week ben ik voor het eerst met triggers bezig geweest. Ik heb nu geen idee of ik ze op de juiste wijze toepas.
dbo.Rekening:
Rekeningnr (int, PK)
…
dbo.Instellingen
DefaultRekeningInkoop (int)
DefaultRekeningVerkoop (int)
…
Ik kan een Forgein Key maken van dbo.Rekening.Rekeningnr naar dbo.Instellingen.DefaultRekeningInkoop. Het fijne is dan dat als het rekeningnr wordt geupdate, dat dan dit wordt meegenomen in de instellingen. (Uiteraard On delete no action, anders ben ik straks al mijn instellingen kwijt
Hetzelfde wil ik ook voor DefaultRekeningVerkoop, door nog een Foreign Key te definiëren van Rekeningnr naar DefaultRekeningVerkoop maar dit mag niet, want MSSQL geeft dan aan dat er dan een loop in de boom van cascaded updates zit (error: Introducing FOREIGN KEY constraint 'FK_Instellingen_Rekening1' on table 'Instellingen' may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints.). Jammer maar helaas, het is niet mogelijk
Volgens mij kan dit alleen opgelost worden door een trigger op dbo.Rekening te plaatsen. In een “For update” trigger op dbo.Rekening voer ik dan zelf de updates door (zie onderaan). Hiervoor moet ik de Foreign-Keys verwijderen, omdat anders de foreign-key de update ook wil doorvoeren (error: Another user has modified the contents of this table or view; the database row you are modifying no longer exists in the database).
Nu ik het probleem verder heb lopen specificeren om een mooie post te maken, heb ik het al uitgevoerd op de bovenstaande manier, omdat ik met een beetje testen het gewenste resultaat kreeg
Adequate oplossing?
Als ik beide DefaultX-kolommen door een trigger laat updaten, ziet niemand dat die velden in dbo.Instellingen afhankelijk zijn van dbo.Rekening. Ik moet dan de documentatie goed maken om te voorkomen dat mensen rare dingen gaan doen met de DefaultRekeningen.
Ook kan ik ervoor kiezen om voor DefaultRekeningInkoop een trigger te plaatsen en voor DefaultRekeningVerkoop de Foreign-key te laten staan, maar dan ben ik inconsitent bezig en zal ik het ook goed moeten documenteren. Hoe zal ik het aanpakken? Dit moet toch een vrij standaard probleem zijn?
Inconsitentie?
De database kan nu, vanwege het gebrek aan Foreign keys, inconsitente gegevens bevatten door in DefaultRekeningVerkoop een willekeurig nummer te plaatsen. Moet ik nou ook op dbo.Instellingen een trigger plaatsen die de inhoud vergelijkt met dbo.Rekening, of is er een andere weg mogelijk –misschien toch met Foreign keys-?
p.s. sinds deze week ben ik voor het eerst met triggers bezig geweest. Ik heb nu geen idee of ik ze op de juiste wijze toepas.
BTW: de trigger:
SQL:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
| CREATE TRIGGER [Update_Credit] ON [dbo].[Rekening] FOR UPDATE AS Declare @OudCredit char(1), @OudRekeningnr int Select @OudCredit = Credit, @OudRekeningnr = Rekeningnr From Deleted Declare @NieuwCredit char(1), @NieuwRekeningnr int Select @NieuwCredit = Credit, @NieuwRekeningnr = Rekeningnr From Inserted -- Updaten van De rekeningnrs. (Alle referenties (in dbo.Instellingen) naar een -- rekeningnr moeten hersteld worden) if Update(Rekeningnr) begin if @OudRekeningnr <> @NieuwRekeningnr begin -- dbo.Instellingen (DefaultVerkoopRekeningnr) eventueel updaten Update dbo.Instellingen Set DefaultVerkoopRekeningnr = @NieuwRekeningnr where DefaultVerkoopRekeningnr = @OudRekeningnr -- dbo.Instellingen (DefaultInkoopRekeningnr) eventueel updaten Update dbo.Instellingen Set DefaultInkoopRekeningnr = @NieuwRekeningnr where DefaultInkoopRekeningnr = @OudRekeningnr end end end |
[ Voor 5% gewijzigd door drm op 08-07-2003 16:14 . Reden: leesbare tekst ]


