english preferred


Vorweg

In meinen eigenen Datenbank habe ich schon ewig ein Longint-Feld, das als Primärschlüssel des Datensatzes dient. Die habe ich noch in V12 oder V13 als primary key gesetzt. War Arbeit, aber nur einmal. Anders sieht es aus bei Kunden, die ich in der Weiterentwicklung Ihrer Datenbanken unterstütze. Deren Datensatzkennung ist sehr heterogen.

Dieser Essay zeigt den mir einzig sinnvollen Weg Primärschlüssel anzulegen. Mit Dank an die Kunden und die Kollegen*.

Reinstolpern

Viele 4D-Anwendungen draußen haben den Update auf die V14 noch vor sich. Die V14 erwartet Primärschlüssel für jede Tabelle oder weigert sich ein Logbuch zwischen den Backups zu führen. Kein Logbuch ist keine Option.

Eine frisch nach V14 konvertierte Datenbank meldet die Tabellen, denen der Primärschlüssel fehlt. Nicht weil ihnen einer fehlt, sondern weil 4D nicht weiß, welches Feld als Primärschlüssel verwendet wird.
pk_Hinweis

Hier verspricht ein Assistent Hilfe und kann gleich an dieser Stelle gestartet werden. Anstatt einfach ein Feld Primärschlüssel anzulegen darf ich optimieren. Für jede Tabelle kann ich wählen ob ich ein bestehendes Feld nutze und ob ich das vorausgewählte oder ein anderes dazu verwenden will. Ich kann auch ein neues Feld anlegen lassen und wählen zwischen UUID und Longint. Oder Sie entscheiden: kein Primärschlüssel und kein Logbuch zu dieser Tabelle.

pk_Assistent

Lassen Sie das

Die paar Bytes pro Datensatz, die Sie sparen könnten, indem Sie ein bestehendes Feld nutzen oder eine Longint statt einer UUID, stehen in keinem Verhältnis zum Preis einer Festplatte, ob Platte oder SSD. Und den Ärger, weil das ausgesuchte Feld doppelte Einträge enthält, doppelte Leer-Einträge, sollte man sich sparen.

Vergessen Sie den Assistenten. Legen Sie vor dem Update auf die V14 in der Struktur ein UUID-Feld an, aktivieren Sie Auto UUID. pk_impossible_deBevor Sie dieses neue Feld als Primärschlüssel definieren können, müssen Sie für eindeutige Feldinhalte sorgen. Sonst gibt es diese Meldung.

Gehen Sie jede Tabelle durch und legen das Feld an. Sobald die Daten in den Feldern eindeutig sind, können Sie das Feld als Primärschlüssel setzen. Leider gibt es keine 4D Befehle aus dem Thema Strukturzugriff zu diesem Zweck.

Denken Sie erst gar nicht darüber nach, wie Sie die neue Version Ihrer Struktur, also die mit den Primärschlüsselfeldern an die Kunden ausliefern? Wie schaffen Sie es, die Kundendaten mit eindeutigen Feldinhalten zu versorgen? Zweistufiger Update ist eine Option. Nicht wirklich!

So ist es besser!

Die Primary Key-Anforderung stammt aus dem SQL-Konzept. Dort in den 4D-Befehlen zum Thema SQL finden Sie dann auch die Option, in einer Schleife über alle Tabellen Primary Keys anzulegen. Formulieren Sie dieses SQL-Statement
$statement_t:=„ALTER TABLE [„+$tableName_t+„] ADD „+$fieldName+“ UUID AUTO_GENERATE PRIMARY KEY;“
und führen es aus
Begin SQL
EXECUTE IMMEDIATE:$statement_t;
End SQL
Das kann länger dauern, weil 4D nicht nur die Struktur um das Feld erweitert sondern auch den vorhandenen Datensätzen eine eindeutige UUID verpasst. Ich sollte das wiederholen, denn das kennen wir von 4D nicht: 4D legt nicht nur das Feld in der Struktur an, sondern verpasst den vorhandenen Datensätzen eine eindeutige ID. Das ist die einzige Stelle in 4D, daß eine Strukturänderung eine nicht beeinflussbare Datenänderung verursacht.

In vertrautem Gefilde

Ist diese Hürde überwunden erkenne ich mein vertrautes und mir die Arbeit abnehmendes 4D wieder. Sind in der Struktur die Primärschlüssel angelegt, macht 4D den Rest. Schicke ich die neue Struktur an einen anderen Kunden, rödelt 4D über deren Datenbank, füllt die Primärschlüssel-Felder und fertig ist die Laube. Die Rückmeldung von 4D könnte informativer sein, kein Fortschrittsbalken bewegt sich, nur der Name des Primärschlüssel-Feldes ändert sich in der Anzeige. Deshalb schicke ich den Kunden eine kurze Anleitung mit, damit sie sich nicht wundern und 4D abschießen.

Ich frage mich warum die V14 beim Update von einer älteren Datenbank nicht automatisch ein UUID-Feld anlegt und dieses zum Primärschlüssel macht, ohne zu meckern, ohne Umstände und sich den Assistenten ganz spart.

Noch ein Tipp für die Anleitung des Kunden! 4D ist nach diesem Durchgang so ausgelaugt, oder ist es der Speicher, das es gerne crashed. Starten Sie 4D neu und arbeiten Sie weiter.

Ich würde so vorgehen

  1. wie beschrieben Primärschlüssel vom Typ UUID noch in V12/V13 anlegen
  2. ein Wartungs-Update rausschicken
  3. die Daten aller Kunden-Anwendungen automatisch auf den neuen Stand bringen
  4. die Anwendung auf V14 updaten und den Kunden diesen Feature-Update anbieten

Ein Update in einem Rutsch funktioniert auch. Der Kunde hat eine V12/V13-Datenbank und bekommt den V14-Update mit definierten Primärschlüsseln, dann wird 4D V14 beim Updaten der Daten auch die Primärschlüssel anlegen und prüfen. Vorzugehen in den 4 Schritten wie beschrieben, sollte unerwünschte Nebeneffekte minimieren.

Von jetzt an

Überprüfen Sie in den 4D Einstellungen V14 diejenige zum Primärschlüssel. Ich habe diese:

v14_pk_prefs

Das xxx ersetze ich durch das Tabellen-Akronym, denn ich will nicht zig gleichlautende Feldnamen haben.

Dazu bitte auch den Beitrag von Keisuke Miyako and 4D v14 and Primary Keys lesen


lieber auf deutsch
Preliminary

For ages I’m using longint-fields as primary keys for the records in my own 4D-solutions. Some day while still in V12/V13 I set those keys as primary keys. A whole different story when supporting customers-databases. Primary key-concepts are pretty heterogenous and those databases are prone for trouble.

This essay describes the best solution I know of, developed with feedback from customers and their databases and in discussion with my colleagues*.

Stumbling into

There are quite a lot of 4D-solutions out there which still need to be updated to V14. Starting with V14 primary keys are necessary for every table to be logged to run a logfile between full-backups. No logfile is no option.

A freshly converted database shows a list of tables where primary keys are missing. Most are not missing. Reason 4D complains is, 4D doesn’t know which field contains the primary key and is to be treated as this.
pk_Hinweis

An assistant promises help. Start the assistant from this dialog and get all the options you can think of. For every table decide to use an existing field, either the one proposed or another one. Or create a new field, either of type UUID or longint. Final option: no primary key and omit logging for this table. Decisions, decisions, …

pk_Assistent

Don’t do that!

Saving a couple of bytes per record makes no sense compared to the price of storage, both platter or SSD. You don’t want to irritate your customer about not properly filled records, containing doubles, especially doubles of emptiness.

pk_impossible_enOmit that assistant completely. Even before updating to V14 make sure, every table has a UUID-field and Auto UUID is checked. Now fill in unique data to every record before setting the field as primary key. Otherwise you’ll see the complaint by 4D.

Same procedure for every table. It’s a pity there is no command in Structure Access-theme for your convenience.

Don’t even start thinking about how to update your customers databases. How to install the new version with primary key at your customers site, how to have unique field-content? Two-step update seems as an option. Nope!

Here is better

The necessity of a primary key is a SQL-principle. Maybe this is the reason you need to dig into 4D SQL-commands to create that primary key for every table by code. Use this SQL-Statement
$statement_t:=„ALTER TABLE [„+$tableName_t+„] ADD „+$fieldName+“ UUID AUTO_GENERATE PRIMARY KEY;“
and execute
Begin SQL
EXECUTE IMMEDIATE:$statement_t;
End SQL
This will take some time depending on record-counts. Besides adding that field to a table, 4D will fill that field for existing records with a unique UUID. I should recapitulate that, because this unusual: 4D adds a field to a structure and updates existing records with unique IDs automatically. This is the only occurence that a structure-change updates existing data in 4D. Other structure-updates leave the data alone until a record gets touched and saved again.

Back to usual

When this barrier is broken down, I’m back to my trustful and forgiving behavior of 4D. Are primary keys created as described, 4D will take care of the rest. When delivering a new version to the customer, 4D will check the customers data and fill in missing UUIDs. Done! I’d be happy, feedback from 4D would be more telling, besides update-windows where nothing happens. Not really nothing just hardly recognizable, the name of the field processed changes. Send your customer some notes, not to have them get confused and killing 4D. They always know how to kill an app, do they?

I’m wondering why 4D doesn’t behave like that automatically while updating an older database: no complains, no irritation, no misleading assistant.

You might also want to add this tipp to the notes for the customer. „Please quit 4D when done. 4D is exhausted or the memory is. After a fresh restart, 4D is ready and waiting for your input.“

I would act like this

  1. create primary keys of type UUID while in V12/V13 as described
  2. deliver a maintenance-update
  3. let 4D update customers data automatically
  4. update the 4D-solution to V14 and offering this feature-update to the customers

An update in one go will work, too. The customer gets a V14-update with primary keys defined, then his V12/V13-data will get updated and V14 creates and checks the primary keys. Proceeding in the four steps described might omit unwanted side-effects.

Epilogue

While you are at it: check the 4D preferences. This is my primary key-settings:

v14_pk_prefs

I replace the xxx with the table-acronym, because I don’t like the same field name all over the place.

Please do read Keisuke Miyako and 4D v14 and Primary Keys . Thanks!

 

Same Discussion in 4D Forum

Primary key before converting

Définir la clé primaire en v12 pour la migration v14 ↩︎