10b — Triggers: Vessel Identity

ABSD_OVGE · ABSD_OVNA · ABSD_OVTY · ABSD_OVCA · ABSD_OVCS · ABSD_OVDOC · ABSD_OVSMC

1. ABSD_OVGE — ABSD_OVGE_Update

Vessel general fields: callsign, official number, navigation aids, fishing number, publication status, builder info, SATCOM, DOB restriction, SBLDR cross-check

Fire condition: FOR UPDATE, INSERT on ABSD_OVGE — guarded by TRIGGER_DISABLE.
Source file: Triggers/dbo.ABSD_OVGE.ABSD_OVGE_Update.sql (~1,230 lines)

Field Validation Rules

FieldGroupValidationExtra rule
A01_EFDA01 publicationvalStandard4_new (YYMMDD)
A01_SRCEA01 publicationvalStandard8 (numeric)
A03_EFDA03 suppressvalStandard9new (YYYYMMDD)
A03_PUBSTA03 suppressMust be IN ('D','U','Y','S','X','Z')
B01_EFDCallsignvalStandard4_new (YYMMDD)
B01_SRCECallsignvalStandard8 (numeric)
B01_VERCallsignvalStandard1 (confidence: C/D/E/G/L/X)
B01_CCCallsignvalStandard2 (2-char alpha)
B01_CALLSIGNCallsignCallsign range validation (see below)Also updates SUPPLEMENTAL_ABSD_HIFL
B02_EFDOfficial no.valStandard4_new (YYMMDD)
B02_SRCEOfficial no.valStandard8 (numeric)
B02_VEROfficial no.valStandard1 (confidence)
B02_OFFNOOfficial no.No hyphen if flag=PAN (see below)
B03_EFDNav aidsvalStandard4_new (YYMMDD)
B03_VERNav aidsvalStandard1 (confidence)
B03_SRCENav aidsvalStandard8 (numeric)
B03_NA1B03_NA12Nav aidsvalStandard2NoNull (2-char, blank fails)All 12 individually validated
B10_EFDFishing no.valStandard4_new (YYMMDD)
B10_SRCEFishing no.valStandard8 (numeric)
B10_VERFishing no.valStandard1 (confidence)
B11_EFDSATCOMvalStandard4_new (YYMMDD)
B11_SRCESATCOMvalStandard8 (numeric)
B11_VERSATCOMvalStandard1 (confidence)
B11_SATCOMSATCOMIN ('Y','N','U') OR ISNUMERIC(@val)=1ISNUMERIC allows numeric SATCOM codes
B11_ANSBK_CODESATCOMvalStandardAlpha (alpha chars only)
B12_EFDB12 groupvalStandard9new (YYYYMMDD)
B12_SRCEB12 groupvalStandard8 (numeric)
B12_VERB12 groupvalStandard1 (confidence)
F01_EFDBuild detailsvalStandard4_new (YYMMDD)
F01_SRCEBuild detailsvalStandard8 (numeric)
F01_BLT_TO_MKBuild detailsMust be IN ('R','+','*')Build-to-mark indicator
F01_EQPT_CHKBuild detailsMust be IN ('1','E','N','-')Equipment check flag
SBLDR_CMPBuilderMust match ABSD_CBSB (KEYC+KEYG+KEYN+KEYX)Validated via ABSD_CBSB lookup
VERGeneralvalStandard1 (confidence)
DOBDate of buildFuture date blocked for in-service vessels (see below)Cross-check with ABSD_HIST

Business Rule: DOB Future Date Restriction

The Date of Build (DOB) cannot be set to a future date if the vessel's current status indicates it is already in service or has completed its lifecycle:

-- Enforced in ABSD_HIST_Update too (primary check location):
IF (select count(*) from absd_ovge a, inserted b where a.lrno = b.lrno and b.seqno = '00'
    and b.a02_sts NOT IN ('P','O','U','F','E','N','X','Z','A')
    and a.dob > (select substring(convert(varchar, getdate(), 112),1,6))) > 0
BEGIN
    RAISERROR('Cannot change status as the Date of Build is set to a date in the future.', 16, 1)
    ROLLBACK TRANSACTION
    RETURN
END
Statuses P, O, U, F, E, N, X, Z, A are pre-delivery / newbuilding statuses where a future DOB is valid. Any other status (including S=in service, T=to be broken up, D=broken up, W=total loss, etc.) must have a past DOB.

Business Rule: A03_PUBST Valid Values

CodeMeaning
DConfirmed Will Not Publish
UContinues Publishing
YSuppressed Will Not Publish
SConfirmed Never Was
XConfirmed Never Was (alternate)
ZSuppressed Confirmed Never Was

Business Rule: Callsign Validation

Callsign ranges are validated against EDM.DBO.T_REF_COUNTRY_CALL_SIGN_RANGES (updated March 2026 — previously used local Callsign_range table).

  • Standard countries: First 2 characters of callsign matched against the range start/end values.
  • Special countries (3-char prefix): Countries SZI, FIJ, EGY, SUD use the first 3 characters of the callsign for the range check. These countries have overlapping 2-char ranges that require the additional character to disambiguate.
-- Simplified callsign validation logic:
IF (SELECT B04_CNTY FROM ABSD_HIFL WHERE LRNO = @LRNO AND SEQNO = '00')
    IN ('SZI','FIJ','EGY','SUD')
BEGIN
    -- Use first 3 chars of callsign
    IF NOT EXISTS (SELECT 1 FROM EDM.DBO.T_REF_COUNTRY_CALL_SIGN_RANGES
        WHERE LEFT(@callsign, 3) BETWEEN RANGE_START AND RANGE_END
          AND COUNTRY_CODE = @flag)
        RAISERROR('Callsign range invalid', 16, 1) ...
END
ELSE
BEGIN
    -- Use first 2 chars of callsign
    IF NOT EXISTS (SELECT 1 FROM EDM.DBO.T_REF_COUNTRY_CALL_SIGN_RANGES
        WHERE LEFT(@callsign, 2) BETWEEN RANGE_START AND RANGE_END
          AND COUNTRY_CODE = @flag)
        RAISERROR('Callsign range invalid', 16, 1) ...
END

Cascade on B01_CALLSIGN change: When the callsign is updated on SEQNO='00', the trigger also updates the SUPPLEMENTAL table:

UPDATE SUPPLEMENTAL_ABSD_HIFL
SET CALLSIGN = (SELECT B01_CALLSIGN FROM inserted)
WHERE LRNO = @LRNO AND SEQNO = '00'

Business Rule: Panama Official Number

B02_OFFNO (official number) cannot contain a hyphen ('-') character when the vessel's flag is Panama (B04_CNTY = 'PAN'):

IF (SELECT B04_CNTY FROM ABSD_HIFL WHERE LRNO = @LRNO AND SEQNO = '00') = 'PAN'
    AND CHARINDEX('-', @B02_OFFNO) > 0
BEGIN
    RAISERROR('B02_OFFNO cannot contain a hyphen for Panama-flagged vessels', 16, 1)
    ROLLBACK TRANSACTION
    RETURN
END

Business Rule: SBLDR_CMP Builder Code

The builder/shipbuilder company code must match a record in ABSD_CBSB. The lookup combines four key columns:

IF NOT EXISTS (SELECT 1 FROM ABSD_CBSB
    WHERE KEYC + KEYG + KEYN + KEYX = @SBLDR_CMP)
BEGIN
    RAISERROR('SBLDR_CMP does not match a record in ABSD_CBSB', 16, 1) ...
END

Staging

-- ABSD_OVGE_UPDATES staging (no cursor needed — OVGE is one row per LRNO)
DELETE FROM ABSD_OVGE_UPDATES WHERE LRNO IN (SELECT LRNO FROM inserted)
INSERT ABSD_OVGE_UPDATES SELECT * FROM ABSD_OVGE WHERE LRNO IN (SELECT LRNO FROM inserted)

ABSD_SHIP_SEARCH Updates (set-based)

-- Callsign, official number, fishing number — set-based when those fields change
IF UPDATE(B01_CALLSIGN)
    UPDATE ABSD_SHIP_SEARCH SET CALLSIGN = i.B01_CALLSIGN
    FROM ABSD_SHIP_SEARCH JOIN inserted i ON ABSD_SHIP_SEARCH.LRNO = i.LRNO

IF UPDATE(B02_OFFNO)
    UPDATE ABSD_SHIP_SEARCH SET OFFICIALNO = i.B02_OFFNO
    FROM ABSD_SHIP_SEARCH JOIN inserted i ON ABSD_SHIP_SEARCH.LRNO = i.LRNO

IF UPDATE(B10_FISHNO)
    UPDATE ABSD_SHIP_SEARCH SET FISHINGNO = i.B10_FISHNO
    FROM ABSD_SHIP_SEARCH JOIN inserted i ON ABSD_SHIP_SEARCH.LRNO = i.LRNO

-- LUPD (last update date) — when J06_LNCHDATE changes
IF UPDATE(J06_LNCHDATE)
    UPDATE ABSD_SHIP_SEARCH SET LUPD = GETDATE()
    FROM ABSD_SHIP_SEARCH JOIN inserted i ON ABSD_SHIP_SEARCH.LRNO = i.LRNO

Primary Annotations (tblChanges)

Fields with primary annotations: B01_CALLSIGN, B02_OFFNO, B10_FISHNO, DOB

Secondary Annotation Groups (tblAnnotationLogGeneral)

Group name (from indAnnotation_SecondaryGroupings)Trigger conditionFields covered
Build/ShipyardIF UPDATE on D_BldShp, Yard_no, or SBLDR_CMPBuild ship, yard number, builder company
F01 groupIF UPDATE on any F01_* fieldF01_EFD, F01_SRCE, F01_BLT_TO_MK, F01_EQPT_CHK
B12 groupIF UPDATE on any B12_* fieldB12_EFD, B12_SRCE, B12_VER + B12 sub-fields
B10 fishingIF UPDATE on any B10_* fieldB10_EFD, B10_SRCE, B10_VER, B10_FISHNO
Callsign (B01)IF UPDATE on any B01_* fieldB01_CALLSIGN, B01_EFD, B01_SRCE, B01_VER, B01_CC
Official no. (B02)IF UPDATE on any B02_* fieldB02_OFFNO, B02_EFD, B02_SRCE, B02_VER
Nav aids (B03)IF UPDATE on B03_NA7–NA9 or B03_NA10–NA12Navigation aid codes
SATCOM (B11)IF UPDATE on any B11_* fieldB11_SATCOM, B11_ANSBK_CODE, B11_EFD, etc.
A01 groupIF UPDATE on any A01_* fieldA01_EFD, A01_SRCE + A01 sub-fields
A03 groupIF UPDATE on any A03_* fieldA03_EFD, A03_PUBST + A03 sub-fields
B03 nav aids (NA1–6, NA10–12)IF UPDATE on B03 EFD/na1–na6/na10–na12Nav aid codes group 1

2. ABSD_OVNA — ABSD_OVNA_Update

Vessel name records: name validation, upper-case enforcement, uniqueness constraints, flag/type sync, GRT length check

Fire condition: FOR UPDATE, INSERT on ABSD_OVNA — guarded by TRIGGER_DISABLE.
Source file: Triggers/dbo.ABSD_OVNA.ABSD_OVNA_Update.sql (~791 lines)

Key table structure: ABSD_OVNA has composite key LRNO + SEQ_NO (char(2) — note: SEQ_NO not SEQNO). The primary name record is SEQ_NO='00'; all history is SEQ_NO='01', '02', etc. in descending date order.

Field Validation Rules

FieldValidationNotes
GRT_LLEN must be ≤ 7 charactersGross register tonnage, longitudinal
INV_GRT_LLEN must be ≤ 7 charactersInternational GRT, longitudinal
G01_EFDvalStandard4_new (YYMMDD); cannot be null ('X' guard)Effective date is mandatory
G01_VERvalStandard1 (confidence code)
G01_HULL_SECMust match ABSD_CBUB1 FLDI='42' (case-sensitive: SQL_Latin1_General_CP1_CS_AS)Hull section code
G01_LNCHD_ASvalStandardYN (Y/N/null)Launched-as indicator
G01_COMP_ASvalStandardYN (Y/N/null)Completed-as indicator
G01_ORIG_NAMEvalStandardYN (Y/N/null)Original name indicator

Business Rule: G01_EFD Cross-Check with ABSD_STSE

The name effective date (G01_EFD) for the current record (SEQ_NO='00') cannot be prior to the vessel's steel section completion date (C01_EFD from ABSD_STSE), unless there are historical status records indicating the vessel was laid down before the current record:

-- G01_EFD for SEQNO='00' must not be before ABSD_STSE.C01_EFD
-- Exception: allowed if ABSD_STSE.SEQNO > '01' exists for this vessel
IF (SELECT COUNT(*) FROM inserted WHERE SEQ_NO = '00') > 0
BEGIN
    IF (SELECT G01_EFD FROM inserted WHERE SEQ_NO='00') <
       (SELECT C01_EFD FROM ABSD_STSE WHERE LRNO = @LRNO AND SEQNO = '00')
       AND NOT EXISTS (SELECT 1 FROM ABSD_STSE WHERE LRNO = @LRNO AND SEQNO > '01')
    BEGIN
        RAISERROR('G01_EFD cannot be prior to C01_EFD in ABSD_STSE', 16, 1) ...
    END
END

Business Rule: G01_NAME Must Be All Upper Case (SEQNO='00')

The current vessel name must be stored in all upper case. The trigger uses a VARBINARY comparison (not UPPER() function) to detect any mixed-case characters — this is a deliberate design to prevent case-normalisation from hiding data quality issues:

-- Binary case check — not a collation comparison
IF CAST(G01_NAME AS VARBINARY) != CAST(UPPER(G01_NAME) AS VARBINARY)
BEGIN
    RAISERROR('G01_NAME must be all upper case for current record (SEQNO=00)', 16, 1) ...
END

Business Rule: G01_NAME No Trailing Spaces (SEQNO='00')

IF RIGHT(G01_NAME, 1) = ' '
BEGIN
    RAISERROR('G01_NAME cannot have trailing spaces', 16, 1) ...
END

Business Rule: G01_NAME Not Equal to Latest Ex-Name (SEQNO='00')

The current name cannot match the most recent historical name (the ex-name at minimum SEQ_NO ≠ '00'), to prevent accidental "rename to same name" operations:

IF EXISTS (SELECT 1 FROM ABSD_OVNA prev
    WHERE prev.LRNO = @LRNO
      AND prev.SEQ_NO = (SELECT MIN(SEQ_NO) FROM ABSD_OVNA WHERE LRNO = @LRNO AND SEQ_NO != '00')
      AND UPPER(prev.G01_NAME) = UPPER(@G01_NAME))
BEGIN
    RAISERROR('Current name cannot be same as the latest historical name', 16, 1) ...
END

Business Rule: Consecutive Name Duplicate Check

A name at SEQ_NO N cannot equal the name at SEQ_NO N±1 (consecutive names must differ):

-- Check the immediately adjacent sequence records for duplicate names
IF EXISTS (SELECT 1 FROM ABSD_OVNA adj
    WHERE adj.LRNO = @LRNO
      AND (adj.SEQ_NO = CAST(@SEQ_NO_INT - 1 AS CHAR(2)) OR adj.SEQ_NO = CAST(@SEQ_NO_INT + 1 AS CHAR(2)))
      AND UPPER(adj.G01_NAME) = UPPER(@G01_NAME))
BEGIN
    RAISERROR('Consecutive name records cannot have the same name', 16, 1) ...
END

Business Rule: G01_LNCHD_AS='Y' Uniqueness

Only one name record per LRNO may have G01_LNCHD_AS='Y' (the name used at vessel launch):

IF (SELECT COUNT(*) FROM ABSD_OVNA WHERE LRNO = @LRNO AND G01_LNCHD_AS = 'Y'
    AND SEQ_NO != @SEQ_NO) > 0
BEGIN
    RAISERROR('Only one LNCHD_AS=Y record is allowed per vessel', 16, 1) ...
END

Business Rule: G01_COMP_AS='Y' Uniqueness

Only one name record per LRNO may have G01_COMP_AS='Y' (the name at vessel completion).

Business Rule: G01_ORIG_NAME Must Have At Least One 'Y' or 'U' Per LRNO

Every vessel must have at least one name record with G01_ORIG_NAME='Y' or 'U'. If the current update would leave zero such records, it is rejected:

IF (SELECT COUNT(*) FROM ABSD_OVNA WHERE LRNO = @LRNO AND G01_ORIG_NAME IN ('Y','U')) = 0
BEGIN
    RAISERROR('At least one name record must have ORIG_NAME = Y or U', 16, 1) ...
END

J06 Audit (written to ABSD_OVGE)

ABSD_OVNA does not have its own J06 fields. The J06_AUTHOR and J06_LNCHDATE are written to the linked ABSD_OVGE record instead:

UPDATE ABSD_OVGE
SET J06_AUTHOR = UPPER(LEFT(RIGHT(system_user, LEN(system_user) - CHARINDEX('\',system_user)), 3)),
    J06_LNCHDATE = ...
WHERE ABSD_OVGE.LRNO IN (SELECT LRNO FROM inserted)

Staging

DELETE FROM ABSD_OVNA_UPDATES WHERE LRNO IN (SELECT LRNO FROM inserted)
INSERT ABSD_OVNA_UPDATES SELECT * FROM ABSD_OVNA WHERE LRNO IN (SELECT LRNO FROM inserted)

AWSH Updates

-- AWSH: G01 column set to 'Y'
UPDATE ABSD_AWSH_UPDATES SET G01='Y' WHERE LRNO IN (SELECT LRNO FROM inserted)

ABSD_SHIP_SEARCH Update

-- VESSELNAME: only updated for SEQ_NO = '00' (current name)
IF (SELECT COUNT(*) FROM inserted WHERE SEQ_NO = '00') > 0
    UPDATE ABSD_SHIP_SEARCH SET VESSELNAME = (SELECT G01_NAME FROM inserted WHERE SEQ_NO = '00')
    WHERE LRNO = @LRNO

Primary Annotations (tblChanges)

G01_NAME — annotated only if the name value actually changed (INSERT count check: the count of inserted rows for this LRNO is not exactly 1, indicating the name differs between old and new). This prevents annotation spam when only metadata fields like EFD or VER change.

Secondary Annotation Groups

Group trigger conditionFields
G01 fields groupG01_EFD, G01_SRCE, G01_HULL_SEC, G01_LNCHD_AS, G01_COMP_AS, G01_ORIG_NAME, G01_NAME, G01_RB_SEQ
ship_typ groupSHIP_TYP field (denormalized type from OVTY)
DOB groupDOB changes (cross-trigger awareness)
Misc groupcurr_n_ind, flag_cde, key_name, lrno, lrno_name, orig_n_ind

3. ABSD_OVTY — ABSD_OVTY_Update

Vessel type: 20-byte type code validation, Berthed/Decked cross-check, STAT5CODE validation, star rating reset, OVNA sync

Fire condition: FOR UPDATE, INSERT on ABSD_OVTY — guarded by TRIGGER_DISABLE.
Source file: Triggers/dbo.ABSD_OVTY.ABSD_OVTY_Update.sql (~324 lines)

Key structure: ABSD_OVTY has composite key LRNO + SEQ_NO. Type fields: D01_INT_BASIC (4 chars) + D01_TYP_A through D01_TYP_E (each 2 chars each, forming the full 20-char = 4+2+2+2+2+2+6 type code; the trailing 6 chars come from other fields).

Field Validation Rules

FieldValidationNotes
D01_EFDvalStandard4_new (YYMMDD)
D01_INT_BASICMust match ABSD_CBSD.INBAS_SUBInternal basic ship type code (4-char)
D01_TYP_AD01_TYP_ESingle space ' ' is NOT allowedThe 2-char type modifiers — a blank space specifically is rejected; empty string or meaningful codes allowed

Business Rule: 20-Byte Ship Type Combo Validation

The complete 20-byte type combination (D01_INT_BASIC + TYP_A + TYP_B + TYP_C + TYP_D + TYP_E) must exist in tblMasterShipTypeXref with the correct STAT5CODE from SUPPLEMENTAL_ABSD_OVTY:

-- Exception: if the combined type = '19000990' (unknown/unclassified), skip validation
IF @fullType != '19000990'
BEGIN
    DECLARE @stat5 VARCHAR(10)
    SELECT @stat5 = STAT5CODE FROM SUPPLEMENTAL_ABSD_OVTY WHERE LRNO = @LRNO AND SEQ_NO = @SEQ_NO

    IF NOT EXISTS (
        SELECT 1 FROM tblMasterShipTypeXref
        WHERE TypeCode = @fullType
          AND STAT5CODE = @stat5)
    BEGIN
        RAISERROR('The ship type combination does not match tblMasterShipTypeXref for this STAT5CODE', 16, 1)
        ROLLBACK TRANSACTION
        RETURN
    END
END

Business Rule: Berthed / Decked Cross-Check

The BERTHED and DECKED flags constrain the value of D01_INT_BASIC at specific character positions:

BERTHEDDECKEDConstraint on INITBASIC
11Position 3 of INITBASIC must be '1' AND position 5 must be '4'
10Position 3 of INITBASIC must be '1'
01Position 5 of INITBASIC must be '4'
00No constraint
IF @BERTHED = 1 AND @DECKED = 1
BEGIN
    IF SUBSTRING(@INITBASIC,3,1) != '1' OR SUBSTRING(@INITBASIC,5,1) != '4'
        RAISERROR('BERTHED+DECKED requires INITBASIC pos3=1 and pos5=4', 16, 1) ...
END
ELSE IF @BERTHED = 1
BEGIN
    IF SUBSTRING(@INITBASIC,3,1) != '1'
        RAISERROR('BERTHED requires INITBASIC pos3=1', 16, 1) ...
END
ELSE IF @DECKED = 1
BEGIN
    IF SUBSTRING(@INITBASIC,5,1) != '4'
        RAISERROR('DECKED requires INITBASIC pos5=4', 16, 1) ...
END

Business Rule: Star Rating Reset on Type Change

When the vessel type changes on the current record (SEQ_NO='00') and the vessel has a star rating above 1, the star rating is automatically reset to 1:

IF UPDATE(D01_INT_BASIC) AND @SEQ_NO = '00'
BEGIN
    IF (SELECT CHStars FROM tblStars WHERE LRNO = @LRNO) > 1
    BEGIN
        UPDATE tblStars
        SET CHStars = 1,
            CHStarsLUpd = GETDATE(),
            CHStarsUser = @Initials
        WHERE LRNO = @LRNO
    END
END
Rationale: When a vessel changes ship type, the star rating (data quality indicator) is reset because the quality assessment is specific to the vessel type. A change in type invalidates the previous rating.

J06 Audit

Writes to ABSD_OVGE (same pattern as all vessel triggers).

Post-Update Cascade: ABSD_OVNA.SHIP_TYP

After the type is updated on SEQ_NO='00', the trigger updates the denormalized type string on the OVNA record:

-- Sync SHIP_TYP to ABSD_OVNA for current record
IF @SEQ_NO = '00'
    UPDATE ABSD_OVNA
    SET SHIP_TYP = @fullType  -- concatenated D01_INT_BASIC + TYP_A through TYP_E
    WHERE LRNO = @LRNO AND SEQ_NO = '00'

Staging

DELETE FROM ABSD_OVTY_UPDATES WHERE LRNO IN (SELECT LRNO FROM inserted)
INSERT ABSD_OVTY_UPDATES SELECT * FROM ABSD_OVTY WHERE LRNO IN (SELECT LRNO FROM inserted)

ABSD_SHIP_SEARCH Update

-- SEQNO='00' only
-- VESSELTYPE = ABSD_CBSD.DECODE_A where INBAS_SUB = D01_INT_BASIC
-- TWENTYBYTESHIPTYPE = concatenated 20-byte type code
IF (SELECT COUNT(*) FROM inserted WHERE SEQ_NO = '00') > 0
BEGIN
    UPDATE ABSD_SHIP_SEARCH
    SET VESSELTYPE = (SELECT DECODE_A FROM ABSD_CBSD WHERE INBAS_SUB = @INT_BASIC),
        TWENTYBYTESHIPTYPE = @fullType
    WHERE LRNO = @LRNO
END

Primary Annotations (tblChanges)

D01_INT_BASIC + TYP_A–E combined — the entire type combination is annotated as a single change record. For non-'00' SEQ_NO records: Notes='Made historical' (if new record) or 'Historical amendment' (if update to existing historical record).

Secondary Annotation Groups

D01_EFD group — fires unconditionally (regardless of which field changed). Covers all D01_* fields.

4. ABSD_OVCA — ABSD_OVCA_Update

Casualty annotation record: F14_EFD date validation, casualty notes

Fire condition: FOR UPDATE, INSERT on ABSD_OVCA — guarded by TRIGGER_DISABLE.
Source file: Triggers/dbo.ABSD_OVCA.ABSD_OVCA_Update.sql (~123 lines)

Key structure: ABSD_OVCA has composite key LRNO + SEQ_NO. The current casualty notation is at SEQ_NO='01' (note: SEQ_NO='00' is not typically used; casualty notations start at '01'). Created/managed by spMakeNewCas which re-sequences DESC.

Field Validation Rules

FieldValidationNotes
F14_EFDvalStandardYMD — flexible date formatNote: uses valStandardYMD (not valStandard4_new). This is a different SP for casualty dates which have less strict formatting requirements.
F14_SRCEvalStandard8 (numeric string)Source code

Commented-Out Business Rule: F14_NOTES Not Null When Vessel Lost

The following cross-check was written but disabled in the source (SDG comment: "can't get it to work — on the to do list"):

/* REMMED OUT — NOT ACTIVE
When A02_STS IN ('T','B','D','W','H') AND A03_PUBST IN ('D','Y') AND F14_NOTES IS NULL:
    RAISERROR('When A03_PUBST is D or Y and A02_STS is T B D W or H
               then F14_NOTES cannot be null. Enter a casualty note', 16, 1)
*/
Unimplemented rule: When a vessel is in a "lost" or "off-register" status and suppressed from publication, a casualty note should be mandatory. This validation was written but disabled and may be re-enabled in future.

J06 Audit + Staging

UPDATE ABSD_OVGE SET J06_AUTHOR=..., J06_LNCHDATE=... WHERE LRNO IN (SELECT LRNO FROM inserted)

DELETE FROM ABSD_OVCA_UPDATES WHERE LRNO IN (SELECT LRNO FROM inserted)
INSERT ABSD_OVCA_UPDATES SELECT * FROM ABSD_OVCA WHERE LRNO IN (SELECT LRNO FROM inserted)

No Primary Annotations

ABSD_OVCA_Update does not write primary annotations to tblChanges.

Secondary Annotation Group

Group: looked up from indAnnotation_SecondaryGroupings for Tablename='ABSD_OVCA', Fieldname='F14_EFD'. Fires unconditionally for every OVCA update.

5. ABSD_OVCS — ABSD_OVCS_Update

Classification society codes: CODE must match CBUB1 table 57 (case-sensitive)

Fire condition: FOR UPDATE, INSERT on ABSD_OVCS — guarded by TRIGGER_DISABLE.
Source file: Triggers/dbo.ABSD_OVCS.ABSD_OVCS_Update.sql (~85 lines)

Field Validation Rules

FieldValidationNotes
DATE_OVCvalStandard4 (YYMMDD — older version, not valStandard4_new)Observation: this trigger still uses the older valStandard4 SP, not the updated one used by most other triggers
CODEMust match ABSD_CBUB1 FLDI='57' (case-sensitive collation)Classification society code — codebook table 57

Business Rule: Classification Society Code (CBUB1 Table 57)

The CODE must have a matching record in ABSD_CBUB1 where FLDI='57'. The comparison is case-sensitive (SQL_Latin1_General_CP1_CS_AS collation):

IF UPDATE(CODE)
BEGIN
    IF NOT (SELECT COUNT(*)
        FROM ABSD_OVCS
        INNER JOIN ABSD_CBUB1 ON ABSD_OVCS.CODE COLLATE SQL_Latin1_General_CP1_CS_AS = ABSD_CBUB1.CODE
            AND ABSD_CBUB1.FLDI = '57'
        WHERE LRNO IN (SELECT LRNO FROM INSERTED)) > 0
    BEGIN
        RAISERROR('The code in CODE does not match a record in table 57 of CBUB1', 16, 1)
        ROLLBACK TRANSACTION
        RETURN
    END
END

J06 Audit + Staging

UPDATE ABSD_OVGE SET J06_AUTHOR=..., J06_LNCHDATE=... WHERE LRNO IN (SELECT LRNO FROM inserted)

DELETE FROM ABSD_OVCS_UPDATES WHERE LRNO IN (SELECT LRNO FROM inserted)
INSERT ABSD_OVCS_UPDATES SELECT * FROM ABSD_OVCS WHERE LRNO IN (SELECT LRNO FROM inserted)

Secondary Annotation Group

Group: looked up from indAnnotation_SecondaryGroupings for Tablename='ABSD_OVCS', Fieldname='CODE'. Fires unconditionally.

6. ABSD_OVDOC — ABSD_OVDOC_Update

Document of Compliance (DOC) issuing company: OWCODE annotation, DOCCOMPANY SHIP_SEARCH update

Fire condition: FOR UPDATE, INSERT on ABSD_OVDOC — guarded by TRIGGER_DISABLE.
Source file: Triggers/dbo.ABSD_OVDOC.ABSD_OVDOC_Update.sql (~169 lines)

Key structure: ABSD_OVDOC has composite key LRNO + SeqNo. Current DOC record is at SeqNo='00'. Contains: OWCODE (issuing company), EffectiveDate, Source, EDIT_DATE.

No Field Validation

ABSD_OVDOC_Update does not validate individual field values (no valXxx calls). All validation is handled at the application level before insert/update.

IsNew / IsCurrent / Notes Logic

Condition@Notes value
New record (no deleted), SeqNo='00''DOC Added'
Existing record updated, SeqNo='00''DOC Updated'
New record (no deleted), SeqNo≠'00''Made historical'
Existing record updated, SeqNo≠'00''Historical amendment'

J06 Audit (with J06_LNCHTIME)

ABSD_OVDOC additionally sets J06_LNCHTIME (HHMMSS) — one of the few triggers that does so:

IF UPDATE(OWCODE) OR UPDATE(SEQNO)
    UPDATE ABSD_OVGE
    SET J06_AUTHOR   = LEFT(@Initials, 3),
        J06_LNCHDATE = ...,
        J06_LNCHTIME = CAST(REPLICATE('0', 2-LEN(DATEPART(hour,   GETDATE()))) AS VARCHAR(2)) + CAST(DATEPART(hour,   GETDATE()) AS VARCHAR(2))
                     + CAST(REPLICATE('0', 2-LEN(DATEPART(minute, GETDATE()))) AS VARCHAR(2)) + CAST(DATEPART(minute, GETDATE()) AS VARCHAR(2))
                     + CAST(REPLICATE('0', 2-LEN(DATEPART(second, GETDATE()))) AS VARCHAR(2)) + CAST(DATEPART(second, GETDATE()) AS VARCHAR(2))
    FROM inserted WHERE ABSD_OVGE.LRNO = INSERTED.LRNO

Note: J06 only fires when OWCODE or SEQNO changes — not for any metadata field change.

ABSD_SHIP_SEARCH Update (cursor-based)

When OWCODE changes for SeqNo='00', the trigger updates the SHIP_SEARCH denormalized columns from the ABSD_OWGE company table:

-- SEQNO='00' only
IF UPDATE(OWCODE)
    UPDATE ABSD_SHIP_SEARCH
    SET DOCCODE    = INSERTED.OWCODE,
        DOCCOMPANY = ABSD_OWGE.SHNAME,    -- company short name
        DOCCOD     = ABSD_OWGE.NATY1      -- company nationality/flag
    FROM ABSD_SHIP_SEARCH
        INNER JOIN INSERTED ON ABSD_SHIP_SEARCH.LRNO = INSERTED.LRNO AND INSERTED.SEQNO = '00'
        INNER JOIN ABSD_OWGE ON INSERTED.OWCODE = ABSD_OWGE.OWCODE

Primary Annotations (tblChanges)

Triggers on OWCODE or SEQNO change. Uses spGetEnglishFieldName for label. The Source field has the TECH override: SOURCE = Case @Source when 'TECH' then i.Source else @Source end

OldValue logic:

  • IsNew=1, IsCurrent=1: null (brand new DOC record)
  • IsNew=1, IsCurrent=0: i.OWCODE (treating the new historical value as the "old" value)
  • IsNew=0: d.OWCODE (previous OWCODE from deleted pseudo-table)

Secondary Annotation

Only fires IF UPDATE(EDIT_DATE) — this field is set only by manual edits (not electronic/automated updates which set their own annotation). Purpose: distinguish manual data entry from automated electronic updates.

7. ABSD_OVSMC — ABSD_OVSMC_Update

Safety Management Certificate (SMC) issuing company: OWCODE annotation, historical sequencing

Fire condition: FOR UPDATE, INSERT on ABSD_OVSMC — guarded by TRIGGER_DISABLE.
Source file: Triggers/dbo.ABSD_OVSMC.ABSD_OVSMC_Update.sql (~187 lines)

Key structure: ABSD_OVSMC has composite key LRNO + SEQNO. Current SMC record is at SEQNO='00'. Contains: OWCODE (issuing company), date_issued, date_expires, Source, EDIT_DATE, and SMC detail fields.

No Field Validation

ABSD_OVSMC_Update does not call any valXxx SPs. No field-level validation enforced in trigger.

IsNew / IsCurrent / Notes Logic

Condition@Notes value
New record (no deleted), SEQNO='00''SMC Added'
New record (no deleted), SEQNO≠'00''Made historical'
Existing record updated, SEQNO≠'00''Historical amendment'
Note: Unlike OVDOC which has 'DOC Updated' for an existing SeqNo='00' update, OVSMC has only 'SMC Added' for any SeqNo='00' insert. Updates to existing SEQNO='00' records do not get a specific Notes — they will have @Notes = 'SMC Added' (not 'SMC Updated'). This may be a defect or intentional simplification.

J06 Audit (with J06_LNCHTIME)

Like OVDOC, OVSMC also sets J06_LNCHTIME. Fires when OWCODE or date_issued changes:

IF UPDATE(OWCODE) OR UPDATE(date_issued)
    UPDATE ABSD_OVGE
    SET J06_AUTHOR   = LEFT(@Initials, 3),
        J06_LNCHDATE = ...,
        J06_LNCHTIME = ... (HHMMSS)
    FROM inserted WHERE ABSD_OVGE.LRNO = INSERTED.LRNO

No ABSD_SHIP_SEARCH Update

The SHIP_SEARCH update code was present in the original trigger but was explicitly removed (commented out with note "Removed to OVDOC 06/03/2007 REJ"). SMC issuer data is no longer maintained in SHIP_SEARCH — only the DOC issuer is (via ABSD_OVDOC_Update).

Primary Annotations (tblChanges)

Triggers on OWCODE or SEQNO change. Same Source TECH override as OVDOC. OldValue logic same as OVDOC.

Secondary Annotation Group

Fires unconditionally for every update — no IF UPDATE gate. Group looked up from indAnnotation_SecondaryGroupings for Tablename='ABSD_OVSMC', Fieldname='LRNO'.