Seite 1 von 1
automatischer Primärschlüssel als Kombination von 2 Feldern
Verfasst: Di, 05.11.2013 00:04
von Cyklista
Hallo! Ich bin dabei eine Datenbank zu erstellen, die der Erfassung von Übersetzungsaufträgen dienen soll.
Der Primärschlüssel der Tabelle "Auftraege" soll aus den Feldern "Id" und "Jahr" bestehen.
In das Feld "Id" soll automatisch die fortlaufende Nummer und in das Feld "Jahr" das aktuelle Jahr eingetragen werden.
Ich möchte, dass diese beiden Felder bei der Erstellung eines neuen Datensatzes im Formular automatisch ausgefüllt werden, aber dass man sie auch ändern kann. Der "Jahreswechsel" soll auch automatisch erfolgen, d.h. nach z.b. 1234 / 2013 soll automatisch 1 / 2014 kommen, wenn ich im nächsten Jahr den ersten Datensatz erstelle.
Wie lässt sich das machen?
Re: automatischer Primärschlüssel als Kombination von 2 Feld
Verfasst: Di, 05.11.2013 17:45
von RobertG
Hallo Cyklista,
das geht mit den Bordmitteln der Datenbank nicht. Autowerte einer Tabelle sind fortschreibend gedacht. Du kannst dafür über SQL einen neuen Wert setzen. Du kannst auch (über SQL) den Defaultwert für ein Feld auf das aktuelle Jahr setzen. Aber weder Autowert noch Defaultwert erscheinen vorher in dem Formular, sondern erst nach der Eingabe. Schließlich tritt die Datenbank erst nach der Eingabe in Aktion und kann dann diese entsprechenden Werte schreiben.
Also musst Du all das zu Fuß über Makros erstellen:
1. Tabelle abfragen und den höchsten Wert für das Feld "ID" für das aktuelle Jahr ermitteln.
2. In Dein Formular in "ID" zu dem Wert 1 addieren.
3. In Dein Formular in das Feld "Jahr" das aktuelle Jahr schreiben.
Falls Du eine entsprechende Lösung anstrebst schau Dir einmal das Kapitel zu den Makros im Handbuch an - oder siehe hier in der Liste einmal nach Makros. Wenn es nicht klappen sollte, so poste hier Deine Versuche, am besten mit einer Beispieldatei.
Gruß
Robert
Re: automatischer Primärschlüssel als Kombination von 2 Feld
Verfasst: Di, 05.11.2013 21:27
von Cyklista
Ok. Also um mir die Arbeit zu erleichtern und zu vereinfachen lege ich mir die Tabelle "LaufendesJahr" mit 2 Spalten "Id" als Primaärschlüssel und "Jahr" als INTEGER an.
RobertG hat geschrieben:1. Tabelle abfragen und den höchsten Wert für das Feld "ID" für das aktuelle Jahr ermitteln.
Code: Alles auswählen
SELECT MAX (Id) FROM "Auftraege" WHERE "Jahr"="Jahr" FROM "LaufendesJahr"
Wie kan ich also dazu eine "1" addieren ud in ein Formularfeld eintragen? Makros sin für mich (noch) ein Abrakadabra.
Re: automatischer Primärschlüssel als Kombination von 2 Feld
Verfasst: Mi, 06.11.2013 11:35
von RobertG
Hallo Cyklista,
Cyklista hat geschrieben:Lege ich mir die Tabelle "LaufendesJahr" mit 2 Spalten "Id" als Primärschlüssel und "Jahr" als INTEGER an.
Der Primärschlüssel muss sich auf beide zusammen beziehen, also "Id" und "Jahr". Für das Jahr brauchst Du keinen Integer-Wert. Es reicht auch Smallinteger, da dort das Maximum bei 5 Stellen liegt.
Cyklista hat geschrieben:
Code: Alles auswählen
SELECT MAX (Id) FROM "Auftraege" WHERE "Jahr"="Jahr" FROM "LaufendesJahr"
Du hast jetzt 2 Tabellen gegründet. Warum? Du benötigst doch nur einen eindeutigen Schlüssel für die Tabelle "Auftraege". Außerdem hast Du zwei Tabellen in eine Abfrage gepackt, ohne sie miteinander zu verbinden.
Jetzt einmal nur für die Tabelle "Auftraege", die dann die Felder "ID" und "Jahr" als Primärschlüssel enthält:
Code: Alles auswählen
SELECT MAX( "ID" ), "Jahr" FROM "Auftraege" GROUP BY "Jahr"
Es werden die momentan höchsten Einträge bei "ID" für die jeweiligen Jahr gelistet.
Code: Alles auswählen
SELECT MAX( "ID" ) AS "momentan höchste ID", MAX( "ID" ) + 1 AS "neue ID", "Jahr" FROM "Auftraege" GROUP BY "Jahr"
Zuerst einmal wird den Feldern ein Alias zugewiesen, damit klar ist, wofür sie dienen. Dann wird dem Maximum einfach '1' hinzugezählt. Das ist die nächste freie "ID".
Code: Alles auswählen
SELECT MAX( "ID" ) AS "momentan höchste ID", MAX( "ID" ) + 1 AS "neue ID", "Jahr" FROM "Auftraege" WHERE "Jahr" = YEAR( NOW( ) ) GROUP BY "Jahr"
Jetzt wird das Ganze noch auf das aktuelle Jahr bezogen, d.h. es wird nur ein Datensatz angezeigt. Oder es wird gar nichts angezeigt, wenn es der erste Datensatz im Jahr ist.
Eine entsprechende Übertragung als neue Werte in das Formular musst Du in dem Moment allerdings händisch erledigen, wenn Du nicht zu Makros greifen willst. Aber was nicht ist kann ja noch werden.
Gruß
Robert
Re: automatischer Primärschlüssel als Kombination von 2 Feld
Verfasst: Mi, 06.11.2013 22:17
von Cyklista
Vielen Dank für die Hinweise!

Die Abfrage funktioniert einwandfrei. Ich denke mir bloß, dass man sie abkürzen kann. Das Feld "Momentan höchste ID" brauche ich eingentlich nicht, wenn ich diesen Wert niergendwo einfüge, oder?
Dies müsste also reichen, nicht wahr? :
Code: Alles auswählen
SELECT MAX ( "ID" ) + 1 AS "neue ID", "Jahr" FROM "Auftraege" WHERE "Jahr" = YEAR( NOW( ) ) GROUP BY "Jahr"
Noch eine Sache: Wenn es im Laufenden Jahr noch keine Aufträge gibt, dann zeigt die Abfrage gar nichts an. Mann müsste also noch irgenwo "IFNULL" und den "sonst_Wert" einfügen, aber ich weiß nicht, wo. Ich habe Verschiedenes probiert, aber es klappt nicht.
Eine entsprechende Übertragung als neue Werte in das Formular musst Du in dem Moment allerdings händisch erledigen, wenn Du nicht zu Makros greifen willst.
Ehrlich gesagt, wenn ich die ID-Nr sowieso von Hand einfügen soll, dann kann ich gleich in der Tabelle nachschauen und brauche keine Abfrage dazu. Mit dem Makro muss ich schon irgwendwie hinkriegen, ich weiss nur noch nicht, wie. Der Prinzip für die Einfügung in das Formularfeld eines Wertes aus einer Abfrage muss doch immer der gleiche sein. Es ändern sich nur die entsprechenden Feldnamen. Ich muss bloß was ähnliches finden und modifizieren.
Noch mal vielen Dank für die Unterstützung
Gruß
Przemek
Re: automatischer Primärschlüssel als Kombination von 2 Feld
Verfasst: Do, 07.11.2013 07:45
von RobertG
Hallo Cyklista,
mit so einer Abfrage kannst Du nur Werte darstellen, für die Du auch ein Jahr in Deiner Tabelle hast. Das liegt einfach an der Bedingung
WHERE "Jahr" = YEAR( NOW( ) )
Die weitere Verarbeitung erfolgt dann im Makro.
Ich habe das jetzt auf die Schnelle einmal zusammen gestellt, damit Du erst einmal einen Ansatz hast.
Gruß
Robert
Re: automatischer Primärschlüssel als Kombination von 2 Feld
Verfasst: Do, 07.11.2013 13:43
von Cyklista
Klasse! Vielen Dank!
Ich habe nur noch paar Fragen:
Mit der Schaltfläche "Schlüselwerte füllen" kann man auch bestimmt zugleich einen neuen Datensatz anlegen. Es müsste aber dabei auch entsprechend das Feld "Annahmedatum" mit dem aktuellen Datm augefüllt werden.
Dann muss inch in noch folgendes das Makro einfügen?
Code: Alles auswählen
DIM oFeld3 AS OBJECT
...
oFeld3 = oForm.getByName("fmtAnnDatum")
...
' [und in der vorletztenj Ziele]:
oFeld3.BoundField.updateDate(unoDate)
Es lässt sich sicherlich auch so einrichten, dass das Makro beim öffnen des Formulars "Auftraege" ausgeführt wird?
Re: automatischer Primärschlüssel als Kombination von 2 Feld
Verfasst: Do, 07.11.2013 17:05
von RobertG
Hallo Cyklista,
mit folgenden Zugriffen hast Du auch das komplette Datum:
Code: Alles auswählen
unoDate = createUnoStruct("com.sun.star.util.Date")
unoDate.Year = Year(Date)
unoDate.Month = Month(Date)
unoDate.Day = Day(Date)
oFeld.BoundField.updateDate(unoDate)
Da Du das Struct und das Jahr schon definiert hast, musst Du jetzt auch noch Monat und Tag befüllen. Dann geht die Zuweisung auch als komplettes Datum (in ein Datumsfeld - updateDate!).
Jetzt musst Du schauen, wie Du das Makro einbinden willst. Dazu würde ich vorziehen, in den Formulareigenschaften das passende Ereignis zu suchen (z.B. "Beim Laden", "Beim erneuten Laden", "Beim Datensatzwechsel" - der "Datensatzwechsel" wird auf jeden Fall bei jedem Wechsel des Datensatzes, auch beim Laden, abgefragt ...). Dann würde ich abfragen, ob das Feld, das sich auf die "ID" bezieht, leer ist. Dies geht mit
IF oFeld2.getCurrentValue() = "" THEN
END IF
Fragst Du das ab und baust in die Abfrage dann den Rest des Makros ein, so erfolgen Änderungen nur, wenn das Feld "ID" leer ist. Du brauchst also keinen Button.
Gruß
Robert
Re: automatischer Primärschlüssel als Kombination von 2 Feld
Verfasst: Do, 07.11.2013 21:56
von Cyklista
DANKE !
Ich habe erstmal das Makro modifiziert um das Feld "AnnDat" auszufüllen und es funkioniert:
Code: Alles auswählen
SUB Datum_aktuell_ID_einfuegen
DIM oDoc AS OBJECT
DIM oDrawpage AS OBJECT
DIM oForm AS OBJECT
DIM oFeld1 AS OBJECT
DIM oFeld2 AS OBJECT
DIM oFeld3 AS OBJECT
DIM inIDneu AS INTEGER
DIM unoDate
oDoc = thisComponent
oDrawpage = oDoc.drawpage
oForm = oDrawpage.forms.getByName("MainForm")
oFeld1 = oForm.getByName("fmtJahr")
oFeld2 = oForm.getByName("fmtID")
oFeld3 = oForm.getByName("fmtAnnDat")
unoDate = createUnoStruct("com.sun.star.util.Date")
unoDate.Year = Year(Date)
unoDate.Month = Month(Date)
unoDate.Day = Day(Date)
oDatenquelle = ThisComponent.Parent.CurrentController
If NOT (oDatenquelle.isConnected()) THEN
oDatenquelle.connect()
END IF
oVerbindung = oDatenquelle.ActiveConnection()
oSQL_Anweisung = oVerbindung.createStatement()
stSql = "SELECT MAX( ""ID"" )+1 FROM ""Auftraege"" WHERE ""Jahr"" = YEAR( NOW( ) )"
oAbfrageergebnis = oSQL_Anweisung.executeQuery(stSql)' Ergebnis auswerten
WHILE oAbfrageergebnis.next
inIDneu = oAbfrageergebnis.getInt(1)
WEND ' nächster Datensatz
IF inIDneu = 0 THEN
inIDneu = 1
END IF
oFeld1.BoundField.updateInt(unoDate.Year)
oFeld2.BoundField.updateInt(inIDneu)
oFeld3.BoundField.updateDate(unoDate)
END SUB
Jetzt noch eine Frage: wo soll ich die beiden Zeilen "IF..." und "ENd IF" unterbringen?
Ich habe Verschiedenes ausprobiert und es klappt nicht. Es werden keine Daten eingefügt. Ich nehme an "END IF" kommit in die vorletzte Zeile, dirkt vor "END SUB", oder?
Re: automatischer Primärschlüssel als Kombination von 2 Feld
Verfasst: Fr, 08.11.2013 09:08
von RobertG
Hallo Cyklista,
mit den Bedingungen für ein leeres Feld stehe ich immer etwas auf Kriegsfuß. Es muss nicht
IF oFeld2.getCurrentValue() = "" THEN
heißen, sondern
IF IsEmpty(oFeld2.getCurrentValue()) THEN
Mit der Bedingung wird alles eingekreist, was unter den Bedingungen nicht benötigt wird. Die Abfrage ist nicht nötig, das Zusammenstellen des Datums ist nicht nötig - eigentlich auch die Variablen für Feld1 und Feld3 in dem folgenden Code.
Code: Alles auswählen
SUB Datum_aktuell_ID_einfuegen
DIM oDoc AS OBJECT
DIM oDrawpage AS OBJECT
DIM oForm AS OBJECT
DIM oFeld1 AS OBJECT
DIM oFeld2 AS OBJECT
DIM oFeld3 AS OBJECT
DIM inIDneu AS INTEGER
DIM unoDate
oDoc = thisComponent
oDrawpage = oDoc.drawpage
oForm = oDrawpage.forms.getByName("MainForm")
oFeld1 = oForm.getByName("fmtJahr")
oFeld2 = oForm.getByName("fmtID")
oFeld3 = oForm.getByName("datDatum")
IF IsEmpty(oFeld2.getCurrentValue()) THEN
unoDate = createUnoStruct("com.sun.star.util.Date")
unoDate.Year = Year(Date)
unoDate.Month = Month(Date)
unoDate.Day = Day(Date)
oDatenquelle = ThisComponent.Parent.CurrentController
If NOT (oDatenquelle.isConnected()) THEN
oDatenquelle.connect()
END IF
oVerbindung = oDatenquelle.ActiveConnection()
oSQL_Anweisung = oVerbindung.createStatement()
stSql = "SELECT MAX( ""ID"" )+1 FROM ""Auftraege"" WHERE ""Jahr"" = YEAR( NOW( ) )"
oAbfrageergebnis = oSQL_Anweisung.executeQuery(stSql)' Ergebnis auswerten
WHILE oAbfrageergebnis.next
inIDneu = oAbfrageergebnis.getInt(1)
WEND ' nächster Datensatz
IF inIDneu = 0 THEN
inIDneu = 1
END IF
oFeld1.BoundField.updateInt(unoDate.Year)
oFeld2.BoundField.updateInt(inIDneu)
oFeld3.BoundField.updateDate(unoDate)
END IF
END SUB
Gruß
Robert
Re: automatischer Primärschlüssel als Kombination von 2 Feld
Verfasst: Fr, 08.11.2013 10:48
von Cyklista
Danke!
Es funktioniert nach einer kleinen Korrektur der Bezeichnung für das Feld 3
Mit der Bedingung wird alles eingekreist, was unter den Bedingungen nicht benötigt wird
Wenn die Bedingung also nicht erfüllt ist, dann braucht der weitere Code nich verarbeitet werden.
Nochmals vielen Dank!
Przemek