Haushaltsbuch / SQL / redundant / Beziehungen

  • VB.NET
  • .NET (FX) 4.5–4.8

Es gibt 8 Antworten in diesem Thema. Der letzte Beitrag () ist von ErfinderDesRades.

    Haushaltsbuch / SQL / redundant / Beziehungen

    Hallo!

    Ich möchte gerne ein kleines Haushaltsbuch mit Tabellen erstellen.

    Ich hab da auch schon was hingeschustert..jedoch habe ich noch einige Fragen bezüglich Redundanz und Beziehungen.

    In der Tabelle 'Positionen' habe ich vier Spalten die sich auf Werte einer jeweils anderen Tabelle beziehen..ist das redundant?
    Außerdem denke ich das mit dieser Konfiguration das Modifizieren der einen Tabelle nicht automatisch die Werte der anderen Bezugstabelle geändert werden.
    Was denkt Ihr, wie sieht das bisher aus?


    Spoiler anzeigen

    SQL-Abfrage

    1. DROP TABLE IF EXISTS [dbo].[Beziehungen]
    2. DROP TABLE IF EXISTS [dbo].[Positionen]
    3. DROP TABLE IF EXISTS [dbo].[EinAus]
    4. DROP TABLE IF EXISTS [dbo].[Kategorien]
    5. CREATE TABLE [dbo].[Kategorien] (
    6. [IDKat] INT PRIMARY KEY IDENTITY(1,1),
    7. [NameKategorie] NVARCHAR(20) UNIQUE NOT NULL
    8. )
    9. CREATE TABLE [dbo].[EinAus] (
    10. [IDEinAus] INT PRIMARY KEY IDENTITY(1,1),
    11. [NameEinAus] NVARCHAR(10) UNIQUE NOT NULL
    12. )
    13. CREATE TABLE [dbo].[Positionen] (
    14. [IDPos] INT PRIMARY KEY IDENTITY(1,1),
    15. [Kategorie_ID] INT NOT NULL,
    16. [Kategorie_Name] NVARCHAR(20) NULL,
    17. [EinAus_ID] INT NOT NULL,
    18. [EinAus_Name] NVARCHAR(10) NULL,
    19. [Datum] Date NULL,
    20. [Betrag] Money NOT NULL,
    21. CONSTRAINT [FK_Positionen_Kategorien_ID] FOREIGN KEY ([Kategorie_ID]) REFERENCES [dbo].[Kategorien] ([IDKat]),
    22. CONSTRAINT [FK_Positionen_EinAus_ID] FOREIGN KEY ([EinAus_ID]) REFERENCES [dbo].[EinAus] ([IDEinAus]),
    23. CONSTRAINT [FK_Positionen_Kategorien_Name] FOREIGN KEY ([Kategorie_Name]) REFERENCES [dbo].[Kategorien] ([NameKategorie]),
    24. CONSTRAINT [FK_Positionen_EinAus_Name] FOREIGN KEY ([EinAus_Name]) REFERENCES [dbo].[EinAus] ([NameEinAus])
    25. )
    26. CREATE TABLE [dbo].[Beziehungen] (
    27. [KategorieID] INT NOT NULL,
    28. [EinAusID] INT NOT NULL,
    29. [PosID] INT NOT NULL,
    30. CONSTRAINT [PK_Beziehungen] PRIMARY KEY CLUSTERED ([KategorieID] ASC, [EinAusID] ASC, [PosID] ASC),
    31. CONSTRAINT [FK_BeziehungenKategorie] FOREIGN KEY ([KategorieID]) REFERENCES [dbo].[Kategorien] ([IDKat]),
    32. CONSTRAINT [FK_BeziehungenEinAus] FOREIGN KEY ([EinAusID]) REFERENCES [dbo].[EinAus] ([IDEinAus]),
    33. CONSTRAINT [FK_BeziehungenPosID] FOREIGN KEY ([PosID]) REFERENCES [dbo].[Positionen] ([IDPos])
    34. )
    35. INSERT INTO [dbo].[Kategorien]
    36. ([NameKategorie])
    37. VALUES
    38. ('Gehalt'),
    39. ('Miete'),
    40. ('Verkäufe'),
    41. ('Versicherung'),
    42. ('Lebensmittel'),
    43. ('Haushaltsartikel'),
    44. ('Sonstige')
    45. INSERT INTO [dbo].[EinAus]
    46. ([NameEinAus])
    47. VALUES
    48. ('Eingang'),
    49. ('Ausgang')
    50. INSERT INTO [dbo].[Positionen]
    51. ([Kategorie_ID], [EinAus_ID], [Datum], [Betrag])
    52. VALUES
    53. (1, 1, '2022-02-02', 2000),
    54. (2, 2, '2022-02-10', 500),
    55. (4, 2, '2022-02-10', 450),
    56. (3, 1, '2022-02-20', 300),
    57. (2, 1, '2022-02-25', 800),
    58. (5, 2, '2022-02-05', 150),
    59. (5, 2, '2022-02-25', 150),
    60. (7, 2, '2022-02-28', 300)
    61. INSERT INTO [dbo].[Beziehungen]
    62. ([KategorieID], [EinAusID], [PosID])
    63. VALUES
    64. (1, 1, 1),
    65. (2, 2, 2),
    66. (4, 2, 3),
    67. (3, 1, 4),
    68. (2, 1, 5),
    69. (5, 2, 6),
    70. (5, 2, 7),
    71. (7, 2, 8)
    72. SELECT
    73. STR([IDPos], 5) 'POSITION',
    74. STR([Kategorie_ID], 5) 'KATEGORIE ID',
    75. LEFT(NameKategorie, 15) 'KATEGORIE',
    76. STR([EinAus_ID], 5) 'EINGANG/AUSGANG ID',
    77. LEFT(NameEinAus, 15) 'EINGANG/AUSGANG',
    78. CONVERT(CHAR(10), [Datum], 104) 'DATUM',
    79. STR([Betrag], 15) 'BETRAG'
    80. FROM
    81. [dbo].[Positionen] JOIN [dbo].[Kategorien]
    82. ON Positionen.Kategorie_ID = Kategorien.IDKat
    83. JOIN [dbo].[EinAus]
    84. ON Positionen.EinAus_ID = EinAus.IDEinAus
    85. ORDER BY DATUM ASC
    ich blicke bei dieser "Darstellung" schlecht durch.
    Kannst du nicht ein ER-Diagramm deines Datenmodells erstellen?
    Im SqlServer kann man zB "Diagramme hinzufügen" - das sind ER-Diagramme.
    Kann aber sein das Feature gibts nur in Kauf-Versionen des SqlMMS.

    Alternativ generierst du dir ein typisiertes Dataset - das ist auch ein ER-Diagramm.

    Jdfs misstrauisch macht mich, dass bei dir Positionen so sehr ähnliche ForeignKeys aufweist wie Beziehungen.

    Und jajaa, Benamung: Singular benamen, Primärschlüssel einfach ID nennen usw. - steht alles hier, und ist dort auch begründet: codeproject.com/Articles/10309…l-Datamodel-for-Beginners
    Und Folge-Artikel
    Hallo,
    ich halte nicht mehr viel davon, selbst SQL zu schreiben, wenn es Tools wie das Entity Framework gibt, die einem die Arbeit komplett abnehmen. Als Übung ist das sicherlich ganz nett, aber in 2022 würde ich das einfach automatisch erzeugen lassen. Aber jeder, wie er möchte. :)
    Was mir bei deinen Tabellen-Definitionen auffällt: z.B.

    Quellcode

    1. ​CREATE TABLE [dbo].[Kategorien] (
    2. [IDKat] INT PRIMARY KEY IDENTITY(1,1),
    3. [NameKategorie] NVARCHAR(20) UNIQUE NOT NULL
    4. )

    Die Feldnamen brauchen nicht den Namen der Tabelle enthalten. Das ist doppelt gemoppelt, weil der Tabellennamen vorgibt, um welche Id oder welchen Namen es sich handelt. (Gilt auch für die anderen Tabellen) Besonders schlimm finde ich, dass du einmal "Kat" und einmal "Kategorie" verwendet hast. (Falls du unbedingt die Feldnamen so haben möchtest, dann entscheide dich wenigstens für eine Schreibweise und zieh es bei allen Feldern durch.)

    Morrison schrieb:

    anderen Tabelle beziehen..ist das redundant?

    Ja, ist es. Würde Felder wie [Kategorie_Name] und [EinAus_Name] entfernen und letztlich über JOINS holen, wenn sie gebraucht werden.

    Wofür brauchst du die Tabelle "Beziehungen"?

    Sieht für mich bis jetzt eher so "naja" aus, auch weil ich mich einfach nicht mit deutschen Tabellen-/Spaltennamen anfreunden kann. Aber das ist meine persönliche Präferenz.
    So, hab des bissl überarbeitet.

    Ich denke Redundanz ist ausgeschlossen..
    ..ist das sonst OK so? :whistling:

    Spoiler anzeigen

    SQL-Abfrage

    1. DROP TABLE IF EXISTS [dbo].[Positionen]
    2. DROP TABLE IF EXISTS [dbo].[EinAus]
    3. DROP TABLE IF EXISTS [dbo].[Kategorien]
    4. CREATE TABLE [dbo].[EinAus] (
    5. [IDEinAus] INT PRIMARY KEY CLUSTERED IDENTITY (1, 1) NOT NULL,
    6. [NameEinAus] NVARCHAR(10) UNIQUE NONCLUSTERED NOT NULL
    7. )
    8. CREATE TABLE [dbo].[Kategorien] (
    9. [IDKategorie] INT PRIMARY KEY CLUSTERED IDENTITY (1, 1) NOT NULL,
    10. [NameKategorie] NVARCHAR(20) UNIQUE NONCLUSTERED NOT NULL
    11. )
    12. CREATE TABLE [dbo].[Positionen] (
    13. [IDPosition] INT PRIMARY KEY CLUSTERED IDENTITY (1, 1) NOT NULL,
    14. [KategorieID] INT NOT NULL,
    15. [EinAusID] INT NOT NULL,
    16. [Datum] DATE NOT NULL,
    17. [Betrag] MONEY NOT NULL
    18. CONSTRAINT [FK_BeziehungenKategorie] FOREIGN KEY ([KategorieID])
    19. REFERENCES [dbo].[Kategorien] ([IDKategorie]) ON DELETE CASCADE ON UPDATE CASCADE,
    20. CONSTRAINT [FK_BeziehungenEinAus] FOREIGN KEY ([EinAusID])
    21. REFERENCES [dbo].[EinAus] ([IDEinAus]) ON DELETE CASCADE ON UPDATE CASCADE,
    22. )
    23. INSERT INTO [dbo].[Kategorien]
    24. ([NameKategorie])
    25. VALUES
    26. ('Gehalt'),
    27. ('Miete'),
    28. ('Verkäufe'),
    29. ('Versicherung'),
    30. ('Lebensmittel'),
    31. ('Haushaltsartikel'),
    32. ('Sonstige')
    33. INSERT INTO [dbo].[EinAus]
    34. ([NameEinAus])
    35. VALUES
    36. ('Eingang'),
    37. ('Ausgang')
    38. INSERT INTO [dbo].[Positionen]
    39. ([KategorieID], [EinAusID], [Datum], [Betrag])
    40. VALUES
    41. (1, 1, '2022-02-02', 2000),
    42. (5, 2, '2022-02-03', 150),
    43. (3, 1, '2022-02-05', 500),
    44. (4, 2, '2022-02-05', 450),
    45. (2, 1, '2022-02-10', 300),
    46. (7, 2, '2022-02-25', 150),
    47. (5, 2, '2022-02-27', 300),
    48. (2, 2, '2022-02-28', 800)
    49. SELECT
    50. STR([IDPosition], 5) 'POSITION',
    51. LEFT(NameKategorie, 15) 'KATEGORIE',
    52. LEFT(NameEinAus, 15) 'EINGANG/AUSGANG',
    53. CONVERT(CHAR(10), [Datum], 104) 'DATUM',
    54. STR([Betrag], 15) 'BETRAG'
    55. FROM
    56. [dbo].[Positionen] JOIN [dbo].[Kategorien]
    57. ON Positionen.KategorieID = Kategorien.IDKategorie
    58. JOIN [dbo].[EinAus]
    59. ON Positionen.EinAusID = EinAus.IDEinAus
    60. ORDER BY DATUM ASC


    Ja mist:
    "Einschränkungen konnten nicht aktiviert werden. Mindestens eine Zeile enthält Werte die die Einschränkungen non-null, unique or foreign-key verletzen."

    Aber nur so hab ich auch die anderen Tabellen unter der 'Positionen'-Tabelle..
    ..oder wie bekomme ich des im Designer hin das wenn ich im Navigator einen Eintrag weiter gehe sich auch alle Werte in der Detail-Ansicht ändern..
    So klappts nich

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „Morrison“ ()

    Das mit der Benennung der ID Spalte hängt etwas davon ab, wann man die Programmierung gelernt hat.

    M.E. macht es durchaus Sinn, den Primärindex Spalten den Tabellennamen mit zugeben statt nur ID zuschreiben, wenn man den Fremdschlüsselspalten, dann den gleichen Namen gibt. Dann weiß man direkt was zusammen gehört. Dies ist in einigen Mikrosoft-Programmen durchaus von Vorteil (Access, PowerBI, PowerQuery).

    Wie man die Benennung macht ist aber eigentlich egal, solang sie einheitlich durch das Projekt durchhält.

    Du solltest Dich mal mit dem Thema Normalisierung von Datenbanken auseinander setzen, dann wäre das mit den redundanten Namen in der Tabelle Positionen und der Tabelle Beziehungen aufgefallen. de.wikipedia.org/wiki/Normalisierung_(Datenbank)
    NB. Es ist doch schön, wenn man lesbare Namen vergibt. Siehe auch [VB.NET] Beispiele für guten und schlechten Code (Stil).
    Ich hätte jetzt nochmal ne Frage bezüglich Master-Detail-Ansicht.

    Ich soll eine Master-Detail Ansicht erstellen.

    Die Master-Tabelle ist "Artists", diese ziehe ich als Detail-Ansicht auf die Form.
    Die darunter liegende Tabelle ist "Albums", diese ziehe ich als DGV aufs Form.

    Soll/Muss ich jetzt die Restlichen Tabellen auch aufs Form ziehen, damit die Ansicht komplett ist oder bezieht sich die Ansicht auf jeweils nur eine Tabelle?!?
    Bilder
    • MP3-Master-Detail.JPG

      79,96 kB, 1.316×422, 81 mal angesehen
    Probier es aus: Wahrscheinliches Ergebnis: Du siehst im DGV die Alben mit ihren Daten, die für den gewählten Künstler vermerkt sind. Weitere DGVs mit den Daten der anderen Tabellen (z.B. Tracks) würden sich dann (abhängig davon, was Du auf's Form für Datenansichten ziehst) nur wieder auf das ausgewählte Album beziehen. Kommt also drauf an, was Du anzeigen lassen willst.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.

    Morrison schrieb:

    Ich soll eine Master-Detail Ansicht erstellen.
    Definiere "Master-Detail".
    Ich liefere meine Definition in vier Views-Videos
    Dabei unterscheide ich Master-Detail von Parent-Child-View.
    Die meisten Leuts sagen "Master-Detail", wenn sie Parent-Child meinen.
    Und für was ich unter Master-Detail verstehe, haben sie dann gar kein Wort.

    Jo- wie gesagt: und ich habe nu keinen Begriff, was du nun unter "Master-Detail" verstehst.