3.3 ENIVERSPIMS — Sicherheitsgespräche

Stand: 2026-03-05

Übergeordnet: PIMS-Architektur — Gesamtübersicht Verwandt: 3.1 Prüfwesen | 3.2 Arbeitsaufträge

Ausgangslage: Zwei parallele Systeme

Sicherheitsgespräche / SIL-Bewertungen werden in zwei getrennten Legacy-Systemen geführt:

Merkmal AMED EZASichGesp ENIVERS tblSicherheitGespraech
Datensätze 5.862 Zeilen 60 Zeilen
Spaltenanzahl 73 59
Primärschlüssel IDEZA (FK → EZAMASTER) idSicherheitGespraech
Verknüpfung pro EZA-Objekt (Instrument/Sensor) pro Anlage/Schutzziel (fiSigBetrieb)
Risikodimensionen SCHADENAUSMASS, AUFENTHALTSDAUER, GEFAHRENABWEICHUNG, EINTRITTSWAHRSCHEINL intSigAusmassSchaden, intSigAufenthaltGefahrBereich, intSigVermeidungGefahr, intSigEintrittWahrscheinlichkeit
SIL-Feld SIL (tinyint) strSbWertSIL (via tblSicherheitBaum)
Klassifizierung Klassif_A/B/C/X (bits), Risikoklasse strSbKennbuchstaben, Klassifizierung, Status
Rechtl. Anforderungen 10 bit-Flags (Dampfk_V, VAWS, VBF, …) bln*-Felder
Aktor/Sensor-Daten 8×(Schalt_Klassi, Kontakt, Grenzwert) — denormalisiert tblSicherheitGespraechAktorSensor (normalisiert)
Unterschriften — (nicht vorhanden) tblSicherheitUnterschrift
Alarmschwellen — (nicht vorhanden) strSigMinVoralarm … strSigMaxAbschaltung2
Schutzziel-Freitext — (nicht vorhanden) memSigSchutzziel (nvarchar MAX)

Kernunterschiede

  • AMED EZASichGesp = Sicherheitsgespräch pro EZA-Instrument/Aktor (Mikroebene).

Fokus: Klassifikation (A/B/C/X), gesetzliche Anforderungen, Risikoklasse, SIL-Ergebnis.

  • ENIVERS tblSicherheitGespraech = SIL-Bewertung pro Schutzziel (Makroebene).

Fokus: Schutzziel-Freitext, Alarmschwellen, strukturierte AktorSensor-Liste, Unterschriften.

Beide basieren auf derselben 4-dimensionalen Risikomatrix (Schadensausmaß × Aufenthaltsdauer × Vermeidbarkeit × Eintrittswahrscheinlichkeit → SIL).

Merge-Strategie: "Must Have" ohne Datenverlust

Prinzip: gemeinsame Tabelle + conversation_type-Unterscheidung

Ein Merge ist möglich, weil der strukturelle Kern identisch ist. Quell-spezifische Felder werden erhalten — entweder als echte Spalten oder als JSON.

AMED EZASichGesp   ──►  safety.conversation (type='EZA')
                                  │
                         conversation_actor_sensor
                         (aus 8×denorm. Spalten normalisiert)

ENIVERS tblSgEspr  ──►  safety.conversation (type='SCHUTZZIEL')
                                  │
                         conversation_actor_sensor
                         (aus tblSicherheitGespraechAktorSensor)
                                  │
                         conversation_justification
                         (aus tblSicherheitGespraechBegruendung)
                                  │
                         conversation_signature
                         (aus tblSicherheitUnterschrift)

Migration ohne Datenverlust

  • Alle legacy_id + legacy_source bleiben erhalten → bidirektionale Traceability
  • Denormalisierte Spalten (EZASichGesp.Schalt_Klassi1–8 × 3 = 24 Spalten) → normalisiert in conversation_actor_sensor (max. 8 Zeilen pro Gespräch)
  • Quell-spezifische Felder ohne Entsprechung auf der anderen Seite → extended_data NVARCHAR(MAX) als JSON

safety.conversation

CREATE TABLE safety.conversation (
    id                  INT           NOT NULL IDENTITY PRIMARY KEY,
    conversation_type   VARCHAR(20)   NOT NULL,    -- 'EZA' | 'SCHUTZZIEL'
    -- Verknüpfung
    item_id             INT           NULL,         -- FK → ENIVERSCAFM.asset.item (für EZA)
    branch_id           INT           NULL,         -- FK → ENIVERSCAFM.org.branch (für SCHUTZZIEL)
    -- Identifikation
    bau_nummer          NVARCHAR(20)  NULL,          -- Bau-/RI-Nummer
    ri_fliessbild_nr    NVARCHAR(20)  NULL,          -- R&I-Fließbild Nummer (tblSgEspr: strSigRiFliessbild)
    blatt_nummer        INT           NULL,          -- Blattnummer
    anlage_teil         NVARCHAR(50)  NULL,
    bezeichnung         NVARCHAR(200) NULL,
    schutzziel          NVARCHAR(MAX) NULL,          -- Schutzziel-Freitext (nur tblSgEspr)
    -- Risikomatrix (beide Systeme, 4 Dimensionen)
    risk_damage         SMALLINT      NULL,          -- Schadensausmaß
    risk_presence       SMALLINT      NULL,          -- Aufenthaltsdauer
    risk_avoidance      SMALLINT      NULL,          -- Gefahrenvermeidung/-abweichung
    risk_probability    SMALLINT      NULL,          -- Eintrittswahrscheinlichkeit
    -- Ergebnis
    sil_required        TINYINT       NULL,          -- geforderter SIL (aus Risikomatrix)
    sil_achieved        TINYINT       NULL,          -- erreichter SIL (aus MSR-Maßnahmen)
    risk_class          NVARCHAR(5)   NULL,          -- Risikoklasse
    classification      NVARCHAR(5)   NULL,          -- A / B / C / X
    -- Klassif.-bits (EZA): als JSON gespeichert
    klassif_a           BIT           NULL,
    klassif_b           BIT           NULL,
    klassif_c           BIT           NULL,
    klassif_x           BIT           NULL,
    -- Gesetzliche Anforderungen (EZA: 10 bit-Flags → JSON)
    legal_flags         NVARCHAR(MAX) NULL,
    -- Technische Ausführung MSR
    techn_msr_notes     NVARCHAR(MAX) NULL,
    -- Alarmschwellen (tblSgEspr: 4 Werte → JSON)
    alarm_thresholds    NVARCHAR(MAX) NULL,
    -- Funktionsbeschreibung (EZASichGesp.Funktion)
    function_desc       NVARCHAR(MAX) NULL,
    -- Abschluss
    done_at             DATETIME2     NULL,
    -- Erweiterungs-JSON (quell-spezifische Felder ohne allg. Entsprechung)
    extended_data       NVARCHAR(MAX) NULL,
    -- Migration
    legacy_id           INT           NULL,
    legacy_source       VARCHAR(20)   NULL,          -- 'AMED_EZA' | 'ENIVERS_LD'
    -- Audit
    created_at          DATETIME2     NOT NULL DEFAULT SYSUTCDATETIME(),
    updated_at          DATETIME2     NOT NULL DEFAULT SYSUTCDATETIME(),
    created_by          INT           NULL,
    updated_by          INT           NULL
)

safety.conversation_actor_sensor

Normalisiert die denormalisierten EZASichGesp-Spalten (Schalt_Klassi1–8, Kontakt1–8, Grenzwert1–8) und tblSicherheitGespraechAktorSensor in eine gemeinsame Tabelle:

CREATE TABLE safety.conversation_actor_sensor (
    id                  INT           NOT NULL IDENTITY PRIMARY KEY,
    conversation_id     INT           NOT NULL,   -- FK → safety.conversation
    sort_order          SMALLINT      NOT NULL DEFAULT 0,
    -- Identifikation
    plt_stelle          NVARCHAR(100) NULL,        -- PLT-Stelle / Funktionsbezeichnung
    typ                 NVARCHAR(50)  NULL,        -- Aktor- oder Sensortyp
    nummer              NVARCHAR(50)  NULL,        -- Geräte-/KKS-Nummer
    -- Aktor-Wirkung (aus tblSgEspr)
    aktor_wirkung       NVARCHAR(100) NULL,
    aktor_stellung      NVARCHAR(100) NULL,
    -- Sensor-Messbereich (aus tblSgEspr)
    messbereich_von     DECIMAL(10,4) NULL,
    messbereich_bis     DECIMAL(10,4) NULL,
    einheit             NVARCHAR(20)  NULL,
    -- Klassifizierung (aus EZASichGesp Schalt_Klassi1–8)
    klassifizierung     NVARCHAR(10)  NULL,
    kontakt             NVARCHAR(10)  NULL,
    grenzwert           NVARCHAR(20)  NULL,
    grenzwert_einheit   NVARCHAR(10)  NULL,
    -- Belegung (aus tblSgEspr.fiSgasBelegung)
    belegung_id         INT           NULL,
    -- Sonstiges
    zusatz_info         NVARCHAR(500) NULL
)

safety.conversation_signature

CREATE TABLE safety.conversation_signature (
    id              INT           NOT NULL IDENTITY PRIMARY KEY,
    conversation_id INT           NOT NULL,   -- FK → safety.conversation
    sort_order      INT           NOT NULL,
    name            NVARCHAR(150) NULL,
    title           NVARCHAR(150) NULL,
    signed_at       DATETIME2     NULL
)

safety.conversation_justification

Begründungsstruktur aus tblSicherheitGespraechBegruendung (SIL-Stufenbegründung):

CREATE TABLE safety.conversation_justification (
    id              INT            NOT NULL IDENTITY PRIMARY KEY,
    conversation_id INT            NOT NULL,   -- FK → safety.conversation
    level_code      VARCHAR(5)     NULL,        -- Stufe (intSbStufe / strSbText)
    text            NVARCHAR(1024) NULL
)

tblSicherheitBaum — Risikomatrix-Lookup

Die LD-Tabelle tblSicherheitBaum ist ein Lookup für die 4-dimensionale Risikomatrix (Schadensausmaß × Aufenthaltsdauer × Vermeidbarkeit × Eintrittswahrscheinlichkeit → SIL-Wert). Sie wird als seed data in shared.list_item oder als separate kleine Tabelle migriert:

CREATE TABLE safety.risk_matrix (
    id                  INT          NOT NULL IDENTITY PRIMARY KEY,
    damage_code         VARCHAR(5)   NOT NULL,
    presence_code       VARCHAR(5)   NULL,
    avoidance_code      VARCHAR(5)   NULL,
    probability_code    VARCHAR(5)   NOT NULL,
    sil_label           VARCHAR(10)  NULL,   -- 'SIL 1', 'SIL 2', 'SIL 3', 'k'
    ak_label            VARCHAR(10)  NULL,   -- Anforderungsklasse
    UNIQUE (damage_code, presence_code, avoidance_code, probability_code)
)
-- Migration: alle Zeilen aus tblSicherheitBaum

Migrations-SQL-Skizze

-- 1. AMED EZASichGesp → safety.conversation (type='EZA')
INSERT INTO safety.conversation (
    conversation_type, item_id, risk_damage, risk_presence, risk_avoidance, risk_probability,
    sil_required, risk_class, klassif_a, klassif_b, klassif_c, klassif_x,
    techn_msr_notes, function_desc, done_at, legal_flags,
    legacy_id, legacy_source, created_at, updated_at
)
SELECT
    'EZA',
    i.id,   -- asset.item.id via IDEZA → EZAMASTER → APPMASTER → asset.item (legacy_id)
    e.Schadenausmass_kurz, e.Aufenthaltsdauer_kurz, e.Gefahrenabweichung_kurz, e.Eintrittswahrscheinlichkeit_kurz,
    e.SIL, e.Risikoklasse, e.Klassif_A, e.Klassif_B, e.Klassif_C, e.Klassif_X,
    e.TECHN_AUSFUHR_MSR, e.Funktion, e.Done,
    -- legal_flags als JSON aus den 10 bit-Spalten:
    (SELECT e.Dampfk_V AS dampfk_v, e.VAWS AS vaws, e.VBF AS vbf, e.Gasbrenner AS gasbrenner,
            e.Stoerf_V AS stoerf_v, e.Einleitb AS einleitb, e.UVV_VBG AS uvv_vbg,
            e.Druckb_V AS druckb_v, e.Genehmigungsb AS genehmigungsb, e.Sonst_V AS sonst_v
     FOR JSON PATH, WITHOUT_ARRAY_WRAPPER),
    e.IDEZA, 'AMED_EZA', e.dtmEsgCreated, e.dtmEsgUpdated
FROM [AMED].[dbo].[EZASichGesp] e
LEFT JOIN ENIVERSCAFM.asset.item i ON i.legacy_id = CAST(
    -- IDEZA → EZAMASTER.erwAppNr → asset.item.legacy_id
    (SELECT CAST(m.erwAppNr AS VARCHAR) FROM [AMED].[dbo].[EZAMASTER] m WHERE m.IDEZA = e.IDEZA)
    AS VARCHAR) AND i.legacy_source = 'AMED';
 
-- 2. Denormalisierte Aktor-Spalten in conversation_actor_sensor auffalten
-- (Schalt_Klassi1..8 × Kontakt1..8 × Grenzwert1..8 → 8 Zeilen pro Gespräch)
INSERT INTO safety.conversation_actor_sensor (conversation_id, sort_order, klassifizierung, kontakt, grenzwert, grenzwert_einheit)
SELECT c.id, v.ord, v.klassi, v.kont, v.grenz, v.grenzeinh
FROM safety.conversation c
JOIN [AMED].[dbo].[EZASichGesp] e ON e.IDEZA = c.legacy_id AND c.legacy_source = 'AMED_EZA'
CROSS APPLY (VALUES
  (1, e.Schalt_Klassi1, e.Kontakt1, e.Grenzwert1, e.Grenzwerteinh1),
  (2, e.Schalt_Klassi2, e.Kontakt2, e.Grenzwert2, e.Grenzwerteinh2),
  -- ... bis 8
  (8, e.Schalt_Klassi8, e.Kontakt8, e.Grenzwert8, e.Grenzwerteinh8)
) AS v(ord, klassi, kont, grenz, grenzeinh)
WHERE COALESCE(v.klassi, v.kont, v.grenz) IS NOT NULL;
Zuletzt geändert: den 05.03.2026 um 22:06