automatischer Primärschlüssel als Kombination von 2 Feldern

Datenbanklösungen mit AOO/LO

Moderator: Moderatoren

Cyklista
***
Beiträge: 50
Registriert: Mo, 04.11.2013 23:34

automatischer Primärschlüssel als Kombination von 2 Feldern

Beitrag 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?
RobertG
********
Beiträge: 2067
Registriert: Fr, 13.04.2012 19:28
Kontaktdaten:

Re: automatischer Primärschlüssel als Kombination von 2 Feld

Beitrag 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
Cyklista
***
Beiträge: 50
Registriert: Mo, 04.11.2013 23:34

Re: automatischer Primärschlüssel als Kombination von 2 Feld

Beitrag 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.
RobertG
********
Beiträge: 2067
Registriert: Fr, 13.04.2012 19:28
Kontaktdaten:

Re: automatischer Primärschlüssel als Kombination von 2 Feld

Beitrag 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
Cyklista
***
Beiträge: 50
Registriert: Mo, 04.11.2013 23:34

Re: automatischer Primärschlüssel als Kombination von 2 Feld

Beitrag 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
RobertG
********
Beiträge: 2067
Registriert: Fr, 13.04.2012 19:28
Kontaktdaten:

Re: automatischer Primärschlüssel als Kombination von 2 Feld

Beitrag 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
Dateianhänge
Fortlaufende_Nummer_Jahr.odb
Einfügen einer fortlaufenden Nummer, abhängig vom Jahr, im Formular
(12.42 KiB) 122-mal heruntergeladen
Cyklista
***
Beiträge: 50
Registriert: Mo, 04.11.2013 23:34

Re: automatischer Primärschlüssel als Kombination von 2 Feld

Beitrag 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?
RobertG
********
Beiträge: 2067
Registriert: Fr, 13.04.2012 19:28
Kontaktdaten:

Re: automatischer Primärschlüssel als Kombination von 2 Feld

Beitrag 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
Cyklista
***
Beiträge: 50
Registriert: Mo, 04.11.2013 23:34

Re: automatischer Primärschlüssel als Kombination von 2 Feld

Beitrag 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?
RobertG
********
Beiträge: 2067
Registriert: Fr, 13.04.2012 19:28
Kontaktdaten:

Re: automatischer Primärschlüssel als Kombination von 2 Feld

Beitrag 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
Cyklista
***
Beiträge: 50
Registriert: Mo, 04.11.2013 23:34

Re: automatischer Primärschlüssel als Kombination von 2 Feld

Beitrag von Cyklista »

Danke!
Es funktioniert nach einer kleinen Korrektur der Bezeichnung für das Feld 3 :)

Code: Alles auswählen

   oFeld3 = oForm.getByName("fmtAnnDat")
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
Antworten