Initialen Implementierungsplan hinzugefügt
This commit is contained in:
266
CLAUDE.md
Normal file
266
CLAUDE.md
Normal file
@@ -0,0 +1,266 @@
|
||||
# CLAUDE.md — Oracle Database
|
||||
|
||||
## Projektbeschreibung
|
||||
|
||||
Projekt für verschiedene Oracle-Datenbank Entwicklungen.
|
||||
Enthält Tabellendefinitionen, PL/SQL-Packages, ORDS-Endpunkte, Views, Trigger etc.
|
||||
|
||||
## SQL / PL/SQL Guidelines
|
||||
|
||||
### Formatierung
|
||||
|
||||
**Keywords immer klein:**
|
||||
```sql
|
||||
select, from, where, insert into, create table, begin, end, exception, ...
|
||||
```
|
||||
|
||||
**Tab-Ausrichtung in mehrzeiligen Statements:**
|
||||
|
||||
Schlüsselwort + Tab, dann Inhalt. Erste Spalte und alle nachfolgenden Kommas stehen auf
|
||||
demselben Tab-Stop (eine Fluchtlinie). Komma direkt vor dem Spaltennamen ohne Leerzeichen.
|
||||
|
||||
```sql
|
||||
select order_id
|
||||
,principal_order_number
|
||||
,total_amount
|
||||
from fgt_order
|
||||
where status = 'COMPLETE'
|
||||
```
|
||||
|
||||
```sql
|
||||
insert into fgt_order (
|
||||
order_id
|
||||
,principal_order_number
|
||||
,total_amount
|
||||
) values (
|
||||
fgt_order_seq.nextval
|
||||
,p_order_number
|
||||
,p_total_amount
|
||||
);
|
||||
```
|
||||
|
||||
**Block-Keywords in eigener Zeile (lineup bracing):**
|
||||
|
||||
`loop`, `then`, `exception` und ihre schließenden `end`-Varianten stehen auf gleicher
|
||||
Einrückungsebene wie der Block-Öffner:
|
||||
|
||||
```sql
|
||||
for rec in cur_open_orders
|
||||
loop
|
||||
l_count := l_count + 1;
|
||||
end loop;
|
||||
|
||||
if l_count > 0
|
||||
then
|
||||
do_something();
|
||||
elsif l_count < 0
|
||||
then
|
||||
handle_negative();
|
||||
end if;
|
||||
|
||||
begin
|
||||
l_result := do_something();
|
||||
exception
|
||||
when e_not_found
|
||||
then
|
||||
l_result := null;
|
||||
when others
|
||||
then
|
||||
raise;
|
||||
end;
|
||||
```
|
||||
|
||||
**`end`-Anweisungen immer mit Label:**
|
||||
```sql
|
||||
end my_procedure;
|
||||
end my_package;
|
||||
```
|
||||
|
||||
**Indentation:** 4 Spaces innerhalb von Blöcken.
|
||||
|
||||
---
|
||||
|
||||
### Benennungskonventionen
|
||||
|
||||
| Objekt | Konvention | Beispiel |
|
||||
|---|---|---|
|
||||
| Tabellen | Modulabhängiger Präfix, z.B.`adr_`, **Singular**, Dateiendung `.tab` | `sy_parameter`, `adr_adresse_zuweisung`, |
|
||||
| Views | `v_` Präfix | `v_adr_adresse_zuweisung` |
|
||||
| Packages | `pck_` Präfix, Separate header und body Dateien mit den Endungen `.pkh` und `.pkb` | `pck_system` |
|
||||
| Prozeduren | `p_`-Präfix | `p_insert_order`, `p_delete_folder` |
|
||||
| Funktionen | `f_`-Präfix | `f_get_order`, `f_build_url` |
|
||||
| Lokale Variablen | `l_`-Präfix | `l_order_id`, `l_count` |
|
||||
| Parameter (Input) | `i_`-Präfix | `i_json`, `i_order_id` |
|
||||
| Package-globale Variablen | `g_`-Präfix | `g_default_currency` |
|
||||
| Konstanten | `c_`-Präfix | `c_max_retries` |
|
||||
| Cursor | `cur_`-Präfix | `cur_open_orders` |
|
||||
| Exceptions | `e_`-Präfix | `e_not_found`, `e_duplicate` |
|
||||
| Views | `_v`-Suffix | `fgt_order_v` |
|
||||
| Trigger | `trg_`-Präfix | `trg_fgt_order_created_at` |
|
||||
| Sequences | `<zweck>_seq` | `fgt_order_id_seq` |
|
||||
| Primary Key (Spalte) | `<tabellenname>_id` | `order_id`, `shipment_id` |
|
||||
| Foreign Key (Constraint) | `<beschreibung>_fk` | `fgt_order_bill_addr_fk` |
|
||||
|
||||
---
|
||||
|
||||
### PL/SQL-Struktur
|
||||
|
||||
- `as` für Package-Spec/Body-Header, `is` für Prozedur-/Funktionskörper innerhalb eines Packages
|
||||
- Implizite Cursor-FOR-Loops bevorzugen gegenüber expliziten Cursors
|
||||
- `is null` / `is not null` verwenden — niemals `= null` / `!= null`
|
||||
- Explizite Formatmasken in `to_date`, `to_char`, `to_timestamp`
|
||||
- `commit` nur im äußersten Aufrufer — nie in Sub-Prozeduren
|
||||
|
||||
```sql
|
||||
create or replace package body pck_orders as
|
||||
|
||||
procedure insert_order (i_json in clob, i_run_id in varchar2)
|
||||
is
|
||||
l_order_id number;
|
||||
l_status varchar2(20);
|
||||
begin
|
||||
-- Implementierung
|
||||
l_order_id := bet_order_id_seq.nextval;
|
||||
end insert_order;
|
||||
|
||||
end fgt_orders;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Exception Handling
|
||||
|
||||
- **Niemals** `when others then null` — Exceptions nie stillschweigend schlucken
|
||||
- Exceptions mit `e_`-Präfix benennen und im Deklarationsteil definieren
|
||||
- `sqlerrm` und `sqlcode` für Fehlerinformationen nutzen
|
||||
|
||||
```sql
|
||||
declare
|
||||
e_invalid_status exception;
|
||||
l_status varchar2(20);
|
||||
begin
|
||||
if l_status not in ('COMPLETE', 'INCOMPLETE')
|
||||
then
|
||||
raise e_invalid_status;
|
||||
end if;
|
||||
exception
|
||||
when e_invalid_status
|
||||
then
|
||||
-- gezielt behandeln
|
||||
log_error('Ungültiger Status: ' || l_status);
|
||||
when others
|
||||
then
|
||||
-- sqlcode / sqlerrm immer loggen, nie schlucken
|
||||
log_error(sqlerrm);
|
||||
raise;
|
||||
end;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Audit-Spalten
|
||||
|
||||
Jede Tabelle bekommt am Ende vier Audit-Spalten:
|
||||
|
||||
```sql
|
||||
create table bet_order (
|
||||
bet_order_id number generated by default as identity not null enable
|
||||
, ...
|
||||
,bet_mit_id_angelegt NUMBER(10) not null,
|
||||
,bet_datum_angelegt DATE not null,
|
||||
,bet_mit_id_geaendert NUMBER(10) not null,
|
||||
,bet_datum_geaendert DATE not null,
|
||||
);
|
||||
```
|
||||
|
||||
Befüllt werden sie über einen `before insert or update`-Trigger pro Tabelle.
|
||||
Namenskonvention: `trg_<tabellenname>_audit`.
|
||||
|
||||
```sql
|
||||
create or replace editionable trigger trg_fgt_order_audit
|
||||
before
|
||||
insert or update on fgt_order
|
||||
referencing
|
||||
new as new
|
||||
old as old
|
||||
for each row
|
||||
declare
|
||||
l_user varchar2(100 byte) := substr(upper(coalesce(
|
||||
sys_context('apex$session', 'app_user'),
|
||||
sys_context('userenv', 'os_user'),
|
||||
sys_context('userenv', 'session_user'))), 1, 100);
|
||||
l_now date := cast(current_timestamp at time zone 'Europe/Berlin' as date);
|
||||
begin
|
||||
if inserting
|
||||
then
|
||||
:new.created_at := l_now;
|
||||
:new.created_by := l_user;
|
||||
end if;
|
||||
:new.changed_at := l_now;
|
||||
:new.changed_by := l_user;
|
||||
end trg_fgt_order_audit;
|
||||
```
|
||||
|
||||
Der Benutzername wird bevorzugt aus der APEX-Session gelesen, mit Fallback auf OS- bzw. DB-Session-User.
|
||||
|
||||
---
|
||||
|
||||
### Tabellenänderungen (Migrations-Skripte)
|
||||
|
||||
Tabellen können von SQLcl Projects nicht gedropt und neu erstellt werden, wenn sie Daten enthalten.
|
||||
Änderungen an bestehenden Tabellen werden deshalb als `alter table`-Statements **am Ende der
|
||||
jeweiligen Tabellendatei** ergänzt — nach dem `create table` und dem Primary-Key-Constraint,
|
||||
aber **vor** dem `-- sqlcl_snapshot`-Kommentar.
|
||||
|
||||
So kann die gesamte Datei als Skript auf eine bestehende Datenbank angewendet werden:
|
||||
Das `create table` schlägt fehl (Tabelle existiert schon), aber die `alter table`-Statements
|
||||
laufen durch und bringen die Tabelle auf den aktuellen Stand.
|
||||
|
||||
```sql
|
||||
create table fgt_order ( ... );
|
||||
|
||||
alter table fgt_order
|
||||
add constraint pk_fgt_order primary key (order_id)
|
||||
using index enable;
|
||||
|
||||
-- Migrationsscript — hinzugefügt am 2026-03-30
|
||||
alter table fgt_order add (
|
||||
status varchar2(16 char) default 'COMPLETE' not null
|
||||
,run_id varchar2(36 char)
|
||||
);
|
||||
|
||||
-- sqlcl_snapshot { ... }
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Planungsdokumente
|
||||
|
||||
Für komplexere Features/Packages wird ein Planungsdokument als `.md`-Datei im Projektverzeichnis
|
||||
abgelegt (z.B. `plan_pck_net_storage.md`). Der Plan wird während der Umsetzung aktuell gehalten —
|
||||
jede Änderung an Architektur oder Schnittstelle wird sofort im Plan nachgeführt.
|
||||
|
||||
---
|
||||
|
||||
### Kommentare
|
||||
|
||||
- Beschreibungen auf **Deutsch**, Code (außer Fachbegriffe der Anwendungsdomäne) auf **Englisch**
|
||||
- Block-Kommentar zu Beginn Prozedur/Funktion mit Zweck und Parametern
|
||||
- Inline-Kommentare mit `--` nur für nicht-offensichtliche Logik
|
||||
|
||||
```sql
|
||||
procedure insert_order (i_json in clob, i_run_id in varchar2)
|
||||
/*Kopf------------------------------------------------------------------------------------------------
|
||||
-- Beschreibung: Fügt einen verarbeiteten Auftrag in die Datenbank ein.
|
||||
------------------------------------------------------------------------------------------------------
|
||||
-- Parameter: i_json Klippa-Ergebnis als JSON-String
|
||||
-- i_run_id Ausführungs-Korrelations-ID des Verarbeitungslaufs
|
||||
------------------------------------------------------------------------------------------------------
|
||||
-- Rückgabe: <nur bei funktionen, nicht bei procedures>
|
||||
------------------------------------------------------------------------------------------------------
|
||||
-- MA Datum Änderung
|
||||
-- SCK 2026-04-07 Funktion erstellt
|
||||
------------------------------------------------------------------------------------------------Kopf*/
|
||||
is
|
||||
...
|
||||
```
|
||||
Reference in New Issue
Block a user