23ai: Flexible Domains
Einleitung
In vergangenen Blogbeiträgen haben wir Ihnen bereits die Domains im allgemeinen sowie die Enumeration Domains als Variante vorgestellt. Damit lässt sich schon eine ganze Menge anfangen, aber es gibt auch kompliziertere Situationen. Nehmen wir als Beispiel eine Postadresse. Je nach Region bzw. Land sind verschiedene Werte erforderlich, z.B. das Bundesstaat in den USA. Weiterhin gibt es verschiedene Definitionen der Postleitzahl was die Länge und Zusammenstellung betrifft. Hier kommt man mit einer der bisher erklärten Domains nicht so recht weiter. Abhilfe schaffen aber die Flexible Domains. Diese bieten die Möglichkeit, mit einer übergeordneten Domain anhand eines Kriteriums zu entscheiden, welche untergeordnete Domain tatsäch zur Anwendung kommen soll. Für unser Beispiel legt man also eine Domain für jedes Adressformat an und erstellt eine übergeordnete Domain, die die Unterscheidung vornimmt.
Einrichtung
Gehen wir also an die Umsetzung. Zuerst werden drei Domains definiert, einmal für das deutsche Adressformat mit 5-stelliger Postleitzahl, einmal für die USA mit dem Bundesstaat als Pflichtfeld und dem dortigen Format für Postleitzahlen und einmal allgemein für den Rest der Welt.
Beginnen wir mit der Domain für deutsche Adressen.
MARCO @ DB23AI:PDB1:>create domain dom_addr_ger as (
2 address_line_1 as varchar2(50),
3 address_line_2 as varchar2(50),
4 city as varchar2(50),
5 postcode as varchar2(10),
6 state as varchar2(30),
7 country as varchar2(30)
8 )
9 constraint dom_addr_ger_chk check (address_line_1 is not null and
10 city is not null and
11 postcode is not null and
12* length(postcode) = 5);
Domain DOM_ADDR_GER created.
Hier sind also Straße (address_line_1), Stadt und Postleitzahl erforderlich und die Postleitzahl muss genau 5 Stellen haben.
Weiter geht es mit der Domain für die Vereinigten Staaten, die Datenfelder müssen dabei jeweils identisch sein.
MARCO @ DB23AI:PDB1:>create domain dom_addr_us as (
2 address_line_1 as varchar2(50),
3 address_line_2 as varchar2(50),
4 city as varchar2(50),
5 postcode as varchar2(10),
6 state as varchar2(30),
7 country as varchar2(30)
8 )
9 constraint dom_addr_us_chk check (address_line_1 is not null and
10 city is not null and
11 state is not null and
12 postcode is not null and
13* regexp_like(postcode, '[0-9]{5}(-[0-9]{4})?') );
Domain DOM_ADDR_US created.
Hier ist nun zusätzlich der Bundesstaat (state) zwingend erforderlich und die Postleitzahl wird auf ein anderes Format geprüft.
Zum Schluss noch die allgemeine Domain für den Rest der Welt.
MARCO @ DB23AI:PDB1:>create domain dom_addr_def as (
2 address_line_1 as varchar2(50),
3 address_line_2 as varchar2(50),
4 city as varchar2(50),
5 postcode as varchar2(10),
6 state as varchar2(30),
7 country as varchar2(30)
8 )
9 constraint dom_addr_def_chk check (address_line_1 is not null and
10 city is not null and
11* postcode is not null);
Domain DOM_ADDR_DEF created.
Hier sind die Prüfungen entsprechend einfach und allgemein gehalten.
Wie bringt man nun diese Domains zusammen? Das erledigt die Flexible Domain, die anhand des Wertes der Spalte "country" entscheidet, welche Sub-Domain angewendet werden soll.
MARCO @ DB23AI:PDB1:>create flexible domain dom_address_flex (address_line_1, address_line_2, city, postcode, state, country)
2 choose domain using (country_code varchar2(5))
3 from case
4 when country_code in ('DE','GER') then dom_addr_ger(address_line_1, address_line_2, city, postcode, state, country)
5 when country_code in ('US','USA') then dom_addr_us(address_line_1, address_line_2, city, postcode, state, country)
6 else dom_addr_def(address_line_1, address_line_2, city, postcode, state, country)
7* end;
Flexible DOMAIN created.
Implementierung
Die Anwendung dieser Flexible Domain ist dann analog zu den bereits vorgestellten Varianten. Es wird eine Tabelle erstellt, die alle Spalten enthält und die Domain referenziert.
MARCO @ DB23AI:PDB1:>create table addresses (
2 id number,
3 address_line_1 varchar2(50),
4 address_line_2 varchar2(50),
5 city varchar2(50),
6 postcode varchar2(10),
7 state varchar2(30),
8 country varchar2(30),
9 country_code varchar2(5),
10 domain dom_address_flex(address_line_1, address_line_2, city, postcode, state, country)
11 using (country_code)
12* );
Table ADDRESSES created.
Zum Test füge ich nun eine deutsche Adresse in die Tabelle ein.
MARCO @ DB23AI:PDB1:>insert into addresses (
2 address_line_1, city, postcode, country_code
3 ) values (
4 'Strasse', 'Dresden', '01189', 'DE'
5* );
1 row inserted.
Wie erwartet, wird die Zeile eingefügt, das sie allen Kriterien entspricht. Fügt man die gleiche Adresse aber als amerikanische Adresse ein, passiert folgendes:
MARCO @ DB23AI:PDB1:>insert into addresses (
2 address_line_1, city, postcode, country_code
3 ) values (
4 'Strasse', 'Dresden', '01189', 'US'
5* );
Error starting at line : 1 in command -
insert into addresses (
address_line_1, city, postcode, country_code
) values (
'Strasse', 'Dresden', '01189', 'US'
)
Error report -
ORA-11534: check constraint (MARCO.SYS_C008436) involving columns ADDRESS_LINE_1, CITY, POSTCODE, STATE, COUNTRY_CODE due to domain constraint MARCO.SYS_DOMAIN_C0057 of domain MARCO.DOM_ADDRESS_FLEX violated
Da nun die Domain zur Prüfung amerikanischer Adressen angewendet wird, fehlt die Angabe des Bundesstaates und somit wird ein Fehler produziert. Gebe ich also zusätzlich "Sachsen" als Bundesstaat an, dann kann auch diese Adresse eingefügt werden.
MARCO @ DB23AI:PDB1:>insert into addresses (
2 address_line_1, city, postcode, state, country_code
3 ) values (
4 'Strasse', 'Dresden', '01189', 'Saxony', 'US'
5* );
1 row inserted.
Damit ist sicher, dass tatsächlich die verschiedenen Domains abhängig vom Land (country) ausgewählt und angewendet werden.
Fazit
Diese komplexe Variante, Domains zu kombinieren, stellt ein durchaus mächtiges Werkzeug zur Vereinheitlichung und Zentralisierung von Regeln zur Datenintegrität dar und ergänzt die bereits erklärten Varianten der Domains.
Kommentare
Keine Kommentare