Erstellen von Tabellen

Für Themen zu Datenbanken und Zugriff auf diese. Auch für Datenbankkomponenten.
Benutzeravatar
Zvoni
Beiträge: 363
Registriert: Fr 5. Jul 2024, 08:26
OS, Lazarus, FPC: Windoof 10 Pro (Laz 2.2.2 FPC 3.2.2)
CPU-Target: 32Bit
Wohnort: BW

Re: Erstellen von Tabellen

Beitrag von Zvoni »

Stevie hat geschrieben: Fr 27. Sep 2024, 13:21 Na wie schon??! Das nimmt man natürlich, weil Netflix es nutzt (Cassandra), Amazon es verwendet (DynamoDB), und LinkedIn es unter der Haube hat (Voldemort) . :lol:
NOT YOUR ERNST????
Aber ernsthaft: Ein Vorteil nichtrelationaler und dokumentenorientierter Datenbanken ist, dass man sich das Schemadesign spart und gerade bei sehr großen _existierenden_ Datenmengen jederzeit in Mikrosekunden ändern kann, was gespeichert wird. Fällt einem also nach Monaten auf, dass man ein Feld vergessen hat, hat man keine Schemaänderungen am Hals, sondern definiert einfach eine neue Version des Dokumententyps und speichert seine Daten fortan mit diesem Typ. Und sowohl neue wie alte Programmversionen können brav nebeneinanderher laufen und jeweils ganz nach Belieben und Code-Base Datensätze der alten und neuen Struktur schreiben und lesen. Das macht so einen Releasewechsel _massiv_ einfacher.

Insbesondere die Varianten, die zur Speicherung JSON verwenden, fügen sich sehr harmonisch in die heute eher Javascript-lastigen Entwicklungsprozesse ein. Keine logischen Brüche am Übergang in die Persistenzschicht, sondern einfach dieselben JSON-Objekte speichern, mit denen man in seiner Anwendung sowieso hantiert.

Auch so etwas wie Sharding oder verzögerte Replikation baut sich mit MongoDB tatsächlich einfacher als mit PostgreSQL oder MariaDB. Und last, not least, horizontales Scaling (sprich: unter Last mal eben zusätzliche Knoten in den Cluster nehmen) ist mit MariaDB, PostgreSQL oder anderen RDBMS teilweise echt komplex.

Aber das nur als _mögliche_ Argumente, weil du fragst. Wenn es hart auf hart kommt, würde ich auch immer erstmal ein RDBMS vorschlagen und dann überlegen, ob etwas dagegen spricht. :)
Ich kenne diese Argumente.
Und mein Einwand "Ich war Einkäufer" war eher gewissermassen scherzhaft gedacht.

Was mich eher interessieren würde, wie gross der Unterschied im Platzbedarf ist für ein "vergleichbares" System.
Beispiel: Ein RDBMS eines ERP-Systems, welches mittlerweile 18 Jahre an Datenbestand hat als direkte "1:1"-Umsetzung auf eine non-relationale, dokumentbasierte Datenbank (Wobei mir da natürlich klar ist, dass das auch wiederum davon abhängt, wie ich die Dokumente definiere)
Ein System sie alle zu knechten, ein Code sie alle zu finden,
Eine IDE sie ins Dunkel zu treiben, und an das Framework ewig zu binden,
Im Lande Redmond, wo die Windows drohn.

Stevie
Beiträge: 162
Registriert: Di 27. Feb 2024, 22:40

Re: Erstellen von Tabellen

Beitrag von Stevie »

NOT YOUR ERNST????
Aber so was von my full Ernst ( https://www.project-voldemort.com/voldemort/). Ist die feine Selbstironie nicht letztlich das, weshalb wir uns in der IT so wohl fühlen? :) Allerdings habe ich gerade gesehen, dass LinkedIn seinen Support vor Jahren abgezogen hat und mittlerweile andere Persistenzlayer bevorzugt. Wahrscheinlich hat LinkedIn Voldemort durch KI ersetzt, weil man ja heutzutage alles mit KI macht. :lol:
Was mich eher interessieren würde, wie gross der Unterschied im Platzbedarf ist für ein "vergleichbares" System.
Ich glaube, diese Frage ist ähnlich zielführend wie die immer wieder auftauchenden Bemerkungen, dass "Hallo, Welt!" in C ja so viel kleiner sei, als in ${InsertYourFavoriteLanguageHere}...

Klar, eine sorgfältig normalisierte Datenbank ist an Speicherungseffizienz nicht zu schlagen. Aber in der Enterprise-Datenhaltung ist (Festplatten)Speicher nicht mehr so wichtig wie in den Tagen, als Codd sein Relationenmodell entwarf. Die einzig harte Währung, die im Laufe der Jahrzehnte in der IT die Wertigkeit nicht verändert hat, ist die Zeit. "Wie lange dauert die Schema-Änderung?", "Wie lange dauert die Entwicklung der Anwendung?", "Wie lange muss der Kunde warten, bis sich die Webseite aufgebaut hat?". Wenn es zu viel Speicher frisst, steck halt ein paar Riegel (oder Platten) nach. Deshalb ist die 3NF heute nicht mehr so wichtig wie früher. Und deshalb gönnt man sich eben auch im Zweifelsfalle, die Daten eines Artikels in jeder Bestellung zu speichern, um Konsistenzprobleme bei Altbestellungen zu verhindern oder einen Get-Request zu haben und nicht zehn.

Das ist bei Normalformen ähnlich wie bei der Frage der Datenkonsistenz. Früher waren die ACID-Regeln heilig und 2PC eine feste Große in jeder Datenbankprüfung. Aber was für ein Flugsicherungssystem nicht zu diskutieren ist, interessiert einen bei einer Amazon-Bestellung nicht die Bohne. Schaut dich nur der traurige Hund an, wenn Du Deine alten Bestellungen anklickst? Na und?! Und wird der USB-Stick zweimal geliefert? Schick halt einen zurück. Amazon gönnt sich "Eventual Consistency" und erhält zum Dank ein Backend, das auch am Black Friday noch dieselben Antwortzeiten hat wie an jedem anderen Tag.

Aber so langsam wird es echt OT. :)

wennerer
Beiträge: 607
Registriert: Di 19. Mai 2015, 20:05
OS, Lazarus, FPC: Linux Mint 20 Cinnamon,Lazarus 2.2.6 (rev lazarus_2_2_6) FPC 3.2.2 x86_64-linux-
CPU-Target: x86_64-linux-gtk2

Re: Erstellen von Tabellen

Beitrag von wennerer »

Hallo,
ich habe nun die "kleine Direkthilfe" von charlytango sowie ich es verstanden habe in den DB Browser eingetragen und etwas mit SQL herumgespielt:

SQL1.png
SQL1.png (40.71 KiB) 2213 mal betrachtet
Wie würde man bei diesen Tabellendesign nach Team Filtern? Der Fremdschlüssel sitz in der Tabelle "TabPerson". Ich habe mir so beholfen das ich den Fremdschlüssel IDTeam in die Tabelle TabPlan verschoben habe. Ich denke aber wenn ihr Profis dieses Design vorschlagt, das es dann auch möglich ist mit dem richtigen SQL Befehl nach Team zu filtern.
Ich hab meine Datei mal angehängt. Vielleicht hat ja jemand Lust mal zu schauen.

Viele Grüße
Bernd
Dateianhänge
Plan.sqlite.zip
(1011 Bytes) 87-mal heruntergeladen

Stevie
Beiträge: 162
Registriert: Di 27. Feb 2024, 22:40

Re: Erstellen von Tabellen

Beitrag von Stevie »

... was spricht gegen:

Code: Alles auswählen

select Name, TeamName, Plandatum, Aktionname  
  from TabPerson join TabTeam on TabPerson.IDTeam = TabTeam.IDTeam 
  join TabPlan on TabPlan.IDPerson = TabPerson.IDPerson
  join TabAktion on TabPlan.IDAktion = TabAktion.IDAktion
  where TeamName = 'T1' and Plandatum = '30.09.24'
  

Code: Alles auswählen

Bernd	T1	30.09.24	kochen
Ulf	T1	30.09.24	putzen
Lars	T1	30.09.24	streichen

wennerer
Beiträge: 607
Registriert: Di 19. Mai 2015, 20:05
OS, Lazarus, FPC: Linux Mint 20 Cinnamon,Lazarus 2.2.6 (rev lazarus_2_2_6) FPC 3.2.2 x86_64-linux-
CPU-Target: x86_64-linux-gtk2

Re: Erstellen von Tabellen

Beitrag von wennerer »

Hallo Stevie,
sofern man weiß wie es geht spricht nichts dagegen :D
Ich danke dir recht herzlich!
Bernd

Stevie
Beiträge: 162
Registriert: Di 27. Feb 2024, 22:40

Re: Erstellen von Tabellen

Beitrag von Stevie »

Ich danke dir recht herzlich!
Gerne, gerne. :)

Im Zusammenhang mit Selects und Joins möchte ich noch mal auf die schöne Zusammenfassung von Chris Moffatt verweisen, die sich auf der Webseite von Code Project (und vermutlich an vielen anderen Orten) finden lässt.

Bild

https://www.codeproject.com/Articles/33 ... -SQL-Joins

Benutzeravatar
Zvoni
Beiträge: 363
Registriert: Fr 5. Jul 2024, 08:26
OS, Lazarus, FPC: Windoof 10 Pro (Laz 2.2.2 FPC 3.2.2)
CPU-Target: 32Bit
Wohnort: BW

Re: Erstellen von Tabellen

Beitrag von Zvoni »

Achtung: nicht alle DBMS können alle gezeigten JOINS out-of-the-box
Ein System sie alle zu knechten, ein Code sie alle zu finden,
Eine IDE sie ins Dunkel zu treiben, und an das Framework ewig zu binden,
Im Lande Redmond, wo die Windows drohn.

wennerer
Beiträge: 607
Registriert: Di 19. Mai 2015, 20:05
OS, Lazarus, FPC: Linux Mint 20 Cinnamon,Lazarus 2.2.6 (rev lazarus_2_2_6) FPC 3.2.2 x86_64-linux-
CPU-Target: x86_64-linux-gtk2

Re: Erstellen von Tabellen

Beitrag von wennerer »

Hallo,
ich versuche immer noch meine Kenntnisse mit SQLite zu verbessern. Ich habe mir nun, nachdem ich einiges gelesen und probiert habe, ein kleines Programm erzeugt. Und natürlich treten da noch einige Fragen auf. Zunächst würde mich interessieren:

  • So wie die Tabelle jetzt angelegt ist kann ich das Plandatum mehrmals eingeben. Würde es nicht Sinn machen auch das noch zu "normalisieren" und sich eine Art "Haupttabelle" zu erstellen wo nur Fremdschlüssel verweise drin sind?
  • Ich habe Plandatum auf notnull gesetzt. Warum kann ich einen Datensatz ohne Plandatum eingeben?
  • Ich habe das Feld "Name" mal auf unique gesetzt und einen Namen doppelt vergeben. Es kommt dann eine Fehlermeldung "ESQLDataBaseError .....!" Wie fängt man das elegant ab?
  • Beim Einfügen eines neuen Datensatzes gibt der Benutzer ja Datum, Name, Aktion ein. Ich muss mir dann im Code die richtige Id holen. Macht man das so? Oder denke ich da zu umständlich?
Mein kleines Testprogramm habe ich angehängt. Würde mich freuen wenn wer Lust und Zeit findet es mal anzusehen. Es gibt bestimmt vieles zu verbessern.
PS: sollte in meiner .zip was fehlen bitte schreiben.

Viele Grüße
Bernd
Dateianhänge
project1.zip
(8.75 KiB) 104-mal heruntergeladen

charlytango
Beiträge: 1058
Registriert: Sa 12. Sep 2015, 12:10
OS, Lazarus, FPC: Laz stable (2.2.6, 3.x)
CPU-Target: Win 32/64, Linux64
Wohnort: Wien

Re: Erstellen von Tabellen

Beitrag von charlytango »

Allgemeine Tips, die mir beim schnellen Drüberschauen auffallen.

Pack die Datenbankkomponenten in ein Datenmodul, dafür wurden die gebaut. Das ist Quasi wie eine Form, die nicht angezeigt wird.
Einstellungen f die DB und das Öffnen in zwei Prozeduren.
Irgendwann wirdst du die grafischen Teile ausmustern und alles in eine Unit ohne grafische Oberfläche packen, aber fürs erste ist ein Datenmodul passend.

Da bei DB Anwendungen recht viele Sachen schief gehen können, versuche ich Automatismen zu vermeiden. Also auch im Datenmodul kein oder wenig Code im OnCreate.

Es wird auch nur das Hauptformular automatisch erzeugt, alle anderen Formulare werden im Code erzeugt und verwaltet.

In die Formulare komme die SQLQueries, Datasources und ggfs datensensitive Komponenten. (man kann auch eigene Datenmodule pro Formular erstellen, ist aber meistens ein overkill) Obwohl man auch in der GUI einer SQLQuery zuweisen kann mache ich das im Code. Eine besondere SQLQuery habe ich im Datenmodul gelassen, um eine zur Verfügung tzu haben wenn es um Dinge außer der Reihe geht -- irgendwelche Zählungen, Summierungen, Validierungen

Nutze QuotedStr()

Bau dir ein gutes Logging (im Datenmodul) dann siehst du, was tatsächlich von und zur DB los ist.
wennerer hat geschrieben: Sa 5. Okt 2024, 08:11 So wie die Tabelle jetzt angelegt ist kann ich das Plandatum mehrmals eingeben. Würde es nicht Sinn machen auch das noch zu "normalisieren" und sich eine Art "Haupttabelle" zu erstellen wo nur Fremdschlüssel verweise drin sind?
Kann man machen, ich normalisiere Datumswerte üblicherweise nicht.
Man kann beim Abfragen danach gruppieren.
wennerer hat geschrieben: Sa 5. Okt 2024, 08:11 Ich habe Plandatum auf notnull gesetzt. Warum kann ich einen Datensatz ohne Plandatum eingeben?
eingeben im Frontend kannst du vieles -- schlagend wird das erst wenn du Daten per SQL als UPDATE oder mit der Kombi

Code: Alles auswählen

SQLQuery1.Post;
SQLQuery.Applyupdates;
die lokal geänderten Daten aus der Query in die DB zurückschreiben willst.
Das Frontend hat keine direkte Verbindung mit der DB, weiß also nicht was alles in der DB definiert wurde (not null, oder auch andere Einschränkungen)
wennerer hat geschrieben: Sa 5. Okt 2024, 08:11 Ich habe das Feld "Name" mal auf unique gesetzt und einen Namen doppelt vergeben. Es kommt dann eine Fehlermeldung "ESQLDataBaseError .....!" Wie fängt man das elegant ab?
mit einer

Code: Alles auswählen

  try
    if SQLQry.Active then SQLQry.Close;
    SQLQry.SQL.Clear;
    SQLQry.SQL.Add('UPDATE.....');
    SQLQry.ExecSQL;
  except
      on E:ESQLDatabaseError do
      begin
        ShowMessageFmt('ErrorCode: %d; Message: %s', [E.ErrorCode, E.Message]);
      end;     
    
  end; 
oder

Code: Alles auswählen

  try
     SQLQuery1.Post;
     SQLQuery.Applyupdates;
  except
      on E:ESQLDatabaseError do
      begin
        ShowMessageFmt('ErrorCode: %d; Message: %s', [E.ErrorCode, E.Message]);
      end;     
    
  end; 

Einiges an Hinweisen ist auch im Projekt -- sorry, wenn ich das Projekt auf links gedreht haben sollte.

Falls du die ID des zuletzt eingefügten Records brauchst (um sie zb irgend wo anders als Fremdschlüssel einzufügen, kannst du sie mit SQL abfragen. Ein Beispiel dazu hab ich dir ins Datenmodul gepackt. Das klappt jetzt schon seit langem verlässlich und sessionsensitiv.

ich würde dir ans Herz legen, sprechende Formularnamen und Unitnamen zu benutzen. Numerierte Namen können die Hölle sein.
Dateianhänge
project_ct.zip
(9.99 KiB) 102-mal heruntergeladen

wennerer
Beiträge: 607
Registriert: Di 19. Mai 2015, 20:05
OS, Lazarus, FPC: Linux Mint 20 Cinnamon,Lazarus 2.2.6 (rev lazarus_2_2_6) FPC 3.2.2 x86_64-linux-
CPU-Target: x86_64-linux-gtk2

Re: Erstellen von Tabellen

Beitrag von wennerer »

Hallo charlytango,
du schriebst:
sorry, wenn ich das Projekt auf links gedreht haben sollte
Du kannst es gerne auf Links und wieder zurück drehen. Ich werde dabei sicher nicht dümmer :D
Herzlichen Dank für die lange Antwort und das kleine Projekt. Es ist für mich immer sehr interessant, in (für mich) überschaubaren Projekten zu sehen, wie erfahrene Programmierer an die Sache heran gehen. Ich werde jetzt wieder etwas Zeit brauchen um das alles aufzuarbeiten.

Viele Grüße
Bernd

charlytango
Beiträge: 1058
Registriert: Sa 12. Sep 2015, 12:10
OS, Lazarus, FPC: Laz stable (2.2.6, 3.x)
CPU-Target: Win 32/64, Linux64
Wohnort: Wien

Re: Erstellen von Tabellen

Beitrag von charlytango »

melde dich einfach wenn dir etwas komisch, undurchschaubar oder abwegig vorkommt ;-)
Ich habe jetzt nicht die absolute Wahrheit gepachtet, ich kann dir nur die Mauern zeigen an denen ich mir schon den Kopf eingerannt habe ggg

Soner
Beiträge: 724
Registriert: Do 27. Sep 2012, 00:07
OS, Lazarus, FPC: Win10Pro-64Bit, Immer letzte Lazarus Release mit SVN-Fixes
CPU-Target: x86_64-win64
Wohnort: Hamburg

Re: Erstellen von Tabellen

Beitrag von Soner »

charlytango hat geschrieben: Sa 5. Okt 2024, 12:23 ...
Falls du die ID des zuletzt eingefügten Records brauchst (um sie zb irgend wo anders als Fremdschlüssel einzufügen, kannst du sie mit SQL abfragen. Ein Beispiel dazu hab ich dir ins Datenmodul gepackt. Das klappt jetzt schon seit langem verlässlich und sessionsensitiv.
..
Mann kann das direkt mit "RETURNING irgendeinfeld" beim einfügen bekommen, natürlich sollte "irgendeinfeld" Indexfeld sein. Und man muss "Open"-Funktion benutzen nicht die Funktion "Exec", z.B.:

Code: Alles auswählen

SQLQuery1.SQL.Text:='insert into tablexy (feld1, feld2) values (1, 2) returning indexfield1';
SQLQuery1.SQL.Open; 
Naturlich hat das nur Sinn, wenn SQLQuery1 nicht mit datensensitiven Steuerungen verbunden sind, weil die anderen Felder nicht mehr vorhanden sind. Es ist hilfreich, wenn man im Hintergrund etwas macht. Firebird hat das, MariaDB soll es auch haben, ob Sqlite das hat, weiss ich nicht. Ich damals bei Sqlite genauso wie du gemacht.

charlytango
Beiträge: 1058
Registriert: Sa 12. Sep 2015, 12:10
OS, Lazarus, FPC: Laz stable (2.2.6, 3.x)
CPU-Target: Win 32/64, Linux64
Wohnort: Wien

Re: Erstellen von Tabellen

Beitrag von charlytango »

Wusste ich bis jetzt nicht, guter Input ! THX

wennerer
Beiträge: 607
Registriert: Di 19. Mai 2015, 20:05
OS, Lazarus, FPC: Linux Mint 20 Cinnamon,Lazarus 2.2.6 (rev lazarus_2_2_6) FPC 3.2.2 x86_64-linux-
CPU-Target: x86_64-linux-gtk2

Re: Erstellen von Tabellen

Beitrag von wennerer »

Auch von mir ein Dankeschön! Ich werde es bestimmt probieren.

Viele Grüße
Bernd

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 6762
Registriert: So 7. Jan 2007, 10:20
OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
CPU-Target: 32Bit (64Bit)
Wohnort: Burgenland
Kontaktdaten:

Re: Erstellen von Tabellen

Beitrag von af0815 »

Soner hat geschrieben: Sa 5. Okt 2024, 23:09 Mann kann das direkt mit "RETURNING irgendeinfeld" beim einfügen bekommen, natürlich sollte "irgendeinfeld" Indexfeld sein. Und man muss "Open"-Funktion benutzen nicht die Funktion "Exec", z.B.:

Code: Alles auswählen

SQLQuery1.SQL.Text:='insert into tablexy (feld1, feld2) values (1, 2) returning indexfield1';
SQLQuery1.SQL.Open; 
Naturlich hat das nur Sinn, wenn SQLQuery1 nicht mit datensensitiven Steuerungen verbunden sind, weil die anderen Felder nicht mehr vorhanden sind. Es ist hilfreich, wenn man im Hintergrund etwas macht. Firebird hat das, MariaDB soll es auch haben, ob Sqlite das hat, weiss ich nicht. Ich damals bei Sqlite genauso wie du gemacht.
Das ist sehr stark SQl-Dialekt abhängig. MS-SQL hat da wiederum nichts vergleichbares. Wenn man es relativ unabhängig von einem speziellen SQl-Server machen will, sollte man es vermeiden.
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

Antworten