Section 12d
Stored Procedures — Ownership, Annotation & Fleet  ·  2026-05-03

12d Stored Procedures — Ownership, Annotation & Fleet

SPs covering the annotation/change-tracking system, ownership statistics recompute, Fairplay data integration, GROUP_FLEET pipeline, and the ABSD_SHIP_SEARCH/owner-search rebuild infrastructure.

Annotation System Overview

The ABSD database has two annotation tables (see Section 10 for trigger-level detail). The SP layer provides read/write/search/cleanup access to them:

tblChanges — Primary Annotations

One row per field change. Columns: LRNo, CompanyNo, EffDate, ChangeType (English field name), UserInitials, Source, SourceRef, FilingRef, OldValue, NewValue, Notes, ExtraData.

Written by: every ABSD_ trigger (via direct INSERT), spAnnotateChange, spWriteAnnotation*.

tblAnnotationLogGeneral — Secondary

Grouped annotations — one entry per field grouping (e.g. "Main Engine Details" covers 20 HIMO fields as one annotation). ChangeType is the group name, not individual field.

Written by: triggers using the "secondary annotation" step (step 8 of the universal trigger pattern).

spAnnotateChange — Field-Level Change Logging

spAnnotateChange @Tablename varchar(255), @Fieldname varchar(255), @IDNo char(7), @IDFieldname varchar(255), @IsNew bit, @NewValue varchar(1012), @OldValue varchar(1012)=null, @Initials varchar(10), @Source varchar(30), @SourceRef varchar(100), @FilingRef varchar(100), @ExtraData varchar(255)=null

Inserts one row into tblChanges for a single field change. Key implementation detail: the ChangeType column is not the raw field name but the English human-readable name looked up via spGetEnglishFieldName(@Tablename, @Fieldname). Special case: when ChangeType='Name' and @IsNew=1, ChangeType becomes 'New Name'; when @IsNew=0, ChangeType becomes 'Name should be'.

The INSERT is built dynamically with sp_executesql to handle embedded single-quotes in values (double-single-quote escaping applied to all varchar parameters).

Dynamic SQL: The SP uses dynamic SQL via sp_executesql. All string parameters are single-quote-escaped before inclusion. The SP is called indirectly — UI and triggers both call it, but batch imports (TIP/MIS) call trigger-driven annotations rather than this SP directly.

spWriteAnnotation* Family

spWriteAnnotation @Tablename, @Fieldname, @LRNO, @IsNew bit, @NewValue, @OldValue, @Initials, @Source, @SourceRef, @FilingRef
spWriteAnnotationNewType @Tablename, @Fieldname, @LRNO, @ChangeType varchar(100), @NewValue, @OldValue, @Initials, @Source, @SourceRef, @FilingRef
spWriteAnnotationNewTypeForLrno @LRNO, @ChangeType, @NewValue, @OldValue, @Initials, @Source
spWriteNarrativeAnnotation @LRNO, @NarrativeText varchar(4000), @Initials, @Source
spWriteNarrativeStyleAnnos @LRNO, @GroupingName varchar(100), @NarrativeText varchar(4000)

Wrapper family around spAnnotateChange and direct tblChanges/tblAnnotationLogGeneral inserts:

SPPurpose
spWriteAnnotationThin wrapper around spAnnotateChange — same params, simpler call signature
spWriteAnnotationNewTypeBypasses spGetEnglishFieldName: passes ChangeType directly. Used when the "English name" is contextual (e.g. 'Scrap Price Calculated')
spWriteAnnotationNewTypeForLrnoMinimal signature — only LRNO, type, old/new value, initials, source. For trigger-context writes
spWriteNarrativeAnnotationInserts a long free-text narrative into tblChanges as ChangeType='Narrative'
spWriteNarrativeStyleAnnosInserts into tblAnnotationLogGeneral with a GroupingName heading (for secondary annotation style output)
spInsertAnnotationNarrativeInserts APS narrative text as a tblChanges 'APS Narrative' entry

spSearchAnnotations* Family

spSearchAnnotations_Primary @LRNO varchar(7), @FromDate datetime=NULL, @ToDate datetime=NULL, @ChangeType varchar(100)=NULL
spSearchAnnotations_General @LRNO varchar(7), @FromDate datetime=NULL, @ToDate datetime=NULL
spSearchAnnotations_GeneralOwnership @OWCODE varchar(7), @FromDate datetime=NULL, @ToDate datetime=NULL
spSearchAnnotationsOwners_Primary @OWCODE varchar(7), @FromDate datetime=NULL, @ToDate datetime=NULL

Retrieves annotation history for the annotation viewer UI. All variants return ordered by EffDate DESC. The _BR3Migration variants are transition versions used during the BR3 system migration (kept for reference).

SPSource tableFilter
spSearchAnnotations_PrimarytblChangesBy LRNO ± date range ± change type
spSearchAnnotations_PrimarySGtblChangesLRNO, Seaweb/Global output filter
spSearchAnnotations_GeneraltblAnnotationLogGeneralBy LRNO ± date range
spSearchAnnotations_GeneralOwnershiptblAnnotationLogGeneralBy OWCODE
spSearchAnnotationsOwners_PrimarytblChangesBy OWCODE (CompanyNo column)
spSecondaryAnnotationstblAnnotationLogGeneralAll secondary annotations for LRNO, most recent first

Companion read SPs: spGetOldValue (retrieves OldValue for a specific ChangeType from tblChanges), spGetAnnoLookupValue (lookup from annotation audit for field-level revert).

spBackfillAnnotations / spBackfillSpanFromAnnos

spBackfillAnnotations @LRNO varchar(7)=NULL
spBackfillSpanFromAnnos @LRNO varchar(7)
spNewBackfillSpanFromAnnos @LRNO varchar(7)

spBackfillAnnotations — Retrospectively creates tblChanges entries from the current ABSD_ field values for a vessel where annotation records are missing (typically after data imports that bypassed the annotation system). Takes optional @LRNO; if NULL, processes all vessels. Slow batch SP — not for real-time use.

spBackfillSpanFromAnnos — Rebuilds ABSD_SPAN (annotation span records that group related changes) from the existing tblChanges history. Used after bulk data corrections to restore the span structure.

spCleanAnnotations / spCleanSecondaryAnnotations

spCleanAnnotations @LRNO varchar(7)=NULL, @DaysToKeep int=180
spCleanSecondaryAnnotations @DaysToKeep int=365

Purge SPs for annotation table maintenance. spCleanAnnotations removes tblChanges rows older than @DaysToKeep (default 180 days) for the given LRNO (or all LRNOs if NULL). spCleanSecondaryAnnotations purges tblAnnotationLogGeneral older than @DaysToKeep. Run by scheduled maintenance jobs. spTidyShipAnnos / spTidyNarrativeAnnoForLrno are variants that deduplicate and tidy annotation text.

spGetEnglishFieldName

spGetEnglishFieldName @Tablename varchar(255), @Fieldname varchar(255), @EnglishName varchar(255) OUTPUT

Looks up the human-readable field label from tblEnglishFieldNames (keyed by Tablename + Fieldname). Returns NULL if no mapping exists. Used by spAnnotateChange to translate technical column names (e.g. 'B01_CALLSIGN') to UI-visible labels (e.g. 'Callsign'). tblEnglishFieldNames must be maintained when new fields are added to the schema.

spRecomputeABSD_OWST — Ownership Statistics

spRecomputeABSD_OWST (no parameters — batch rebuild)

Rebuilds the entire ABSD_OWST table from scratch. ABSD_OWST stores aggregate fleet statistics per OWCODE: vessel counts by ownership role and vessel status. The computation joins ABSD_HIOW (registered owner), ABSD_HISM (ISM manager), ABSD_HIMA (ship manager), ABSD_OWSH (ownership-ship links), and ABSD_HIST (status) using the vwABSD_OWXR_EDM view as the ownership role resolution layer.

Five-part OWST calculation (from source):

ColumnDefinition
OWNCOUNT_CNTCount where ABSD_OWSH.REL1_1/2/3 = 'RC' (Registered Owner) AND vessel status is active (S,L,T,R,B,C,V,J,P,O,U,A,F,E)
MANCOUNT_CNTCount where company appears in ABSD_HISM (ISM ship manager) AND status active
PARTONE_CNTCount where REL1_1='IRP' (Indirect Registered P&I) relationship
PARTTWO_CNTCount where REL1_2='RP' (Registered P&I)
PARTTHREE_CNTCount where REL1_3='P' (P&I)
PARTFOUR_CNTFourth-tier party count (charterer/operator role)
PARTFIVE_CNTFifth-tier party count (agent role)
IRP_AGENTFORSum of PART1+2+3+4+5 — total "indirect responsible parties"
RP_AGENTFORSum of PART2+3+4+5
P_AGENTFORSum of PART3+5 — P&I related

Implementation: builds a #ABSD_OWST_TEMP temp table, LEFT OUTER JOINs each count as a subquery keyed by OWCODE, then does a final MERGE/UPDATE into ABSD_OWST. Takes several minutes to run on the full ~280,000 company dataset.

The ABSD_HIST trigger calls a single-LRNO variant of this logic; spRecomputeABSD_OWST is for full rebuild (e.g. after bulk ownership imports).

spRecomputeABSD_OWST_Diffs

spRecomputeABSD_OWST_Diffs

Compares the newly computed OWST (from a temp computation) against the current ABSD_OWST and writes a diff report. Used to verify the correctness of OWST after bulk imports without immediately committing changes. Returns rows where any count differs between computed and stored values.

spUpdateOWNA / spOWNAFullNameWithIndex

spUpdateOWNA @OWCODE varchar(7), @NewName varchar(100), @Initials varchar(10)
spOWNAFullNameWithIndex @OWCODE varchar(7)

spUpdateOWNA — Updates the company name in ABSD_OWNA (current record, SEQNO='00') and writes a tblChanges annotation. Triggers ABSD_OWNA_Update which cascades to update ABSD_SHIP_SEARCH for all vessels linked to this company.

spOWNAFullNameWithIndex — Returns the full company name plus OWCODE for a given company, formatted for display in the UI owner search index. Used by the quick-search type-ahead in the company lookup field.

spFairplay* — Fairplay Data Integration

SPPurpose
spFairplayCurrentOwnershipReturns current ownership data in Fairplay output format (for FP data exchange)
spFairplayCurrentOwnershipEmulateEmulates FP ownership format output for testing/comparison
spFairplayCurrentOwnershipEmulateSLSame but filtered to Status=S/L (active fleet)
spFairplayOwnershipEmulateHistorical ownership in FP format
spFairplayShipnameCompareCompares ABSD ship names against Fairplay names using fnTidyShipname + similarity scoring
spFairplayTblShipSelectSelects vessels for inclusion in the FP tblShip export table
spFPABFleetCompareCompares ABSD fleet data against FP Absolute Register for discrepancy reporting
spFPAutoUpdateOWGEBatchBatch-updates ABSD_OWGE from Fairplay company data feed
spFPAutoUpdateOWNABatchBatch-updates ABSD_OWNA names from Fairplay

spFPL* — Fairplay Link Owner Update Pipeline

7-SP pipeline for importing Fairplay owner data and merging it into ABSD company records:

SPStage
spFPLPrepareFPLOWNTEMP1 — Loads raw FP owner records into FPLOWNTEMP staging table
spFPLAddressPreCompact2 — Normalises addresses in FPLOWNTEMP (remove double-spaces, clean special chars)
spFPLAddressPreCompactFP3 — FP-specific address normalization rules
spFPLNewOwners4 — Identifies FP records with no ABSD match → creates new ABSD company records
spFPLNewOwnersFP4b — FP variant of new-owner creation
spFPLOwnerUpdates5 — Applies FP owner data updates to existing ABSD records
spFPLOwnerUpdatesFP5b — FP variant of owner updates
spFPLUpdateOwnersPersonnel6 — Updates personnel records linked to FP-sourced companies
spFPLKludgeShipNamesCleanup — corrects ship name mismatches introduced by FP import

spCoMatch* — Company Matching

spCoMatchFleetList @OWCODE varchar(7)
spCoMatchFleetPercent @OWCODE1 varchar(7), @OWCODE2 varchar(7)
spCoMatchABSDFleetOwnerSummary @OWCODE varchar(7)
spCoMatchABSDFleetManagerSummary @OWCODE varchar(7)
spCoMatchABSDFleetParentSummary @OWCODE varchar(7)

Fleet overlap analysis SPs used when merging duplicate company records:

Supporting SP: spReplaceandDeleteOwcode — merges all references from one OWCODE to another then deletes the source OWCODE. Used after confirming two records are duplicates.

spBestAddress / spFiveLinesofAddress

spBestAddress @OWCODE varchar(7)
spFiveLinesofAddress @OWCODE varchar(7)

spBestAddress — Returns the "best" address for a company by applying a priority ranking to available ABSD_OWAD1/2 records (prefer registered office, then head office, then first available address). Returns the top-ranked address as a structured result set.

spFiveLinesofAddress — Formats the best address into exactly 5 display lines (standard postal format for print output). Handles country code → country name expansion, concatenation of address fields, and trimming. Used by the APS narrative and register book output.

spAddressTRF / spAddressTRFJapAudit

spAddressTRF @OWCODE varchar(7), @AddressType varchar(2)='RO'
spAddressTRFJapAudit @OWCODE varchar(7)

spAddressTRF — Transfers/copies address data between ABSD_OWAD1 records for a company, typically when an address type changes (e.g. registered office becomes correspondence address). Uses spCopyAddressComms for the comms record copy.

spAddressTRFJapAudit — Japan-specific audit variant that logs address transfers to a separate audit table for regulatory compliance.

GROUP_FLEET Pipeline — Overview

The GROUP_FLEET system computes fleet ownership relationships for the Seaweb/ISR group-fleet product. It identifies which vessels belong to the same corporate group by traversing ownership and management chains. The pipeline runs as a scheduled job and writes results to the GROUP_FLEET table.

Architecture: The pipeline uses a work_owners temp-like table as a staging area. All 7 pipeline SPs populate or read from work_owners before the final UPDATE to GROUP_FLEET.

sp_GROUP_FLEET_p_parallel — Master Runner

sp_GROUP_FLEET_p_parallel (no parameters)

Orchestrates the full GROUP_FLEET pipeline by calling the 7 sub-SPs in order. Called by the SQL Agent job. Runtime: typically 2–4 hours on the full fleet.

GROUP_FLEET Pipeline Steps

Companion: sp_GROUP_FLEET_p_date_update_temp / sp_GROUP_FLEET_p_date1_update_temp / sp_GROUP_FLEET_p_wsg_update — temporary/debug variants used for incremental testing.

spUpdateOwnerSearch (no parameters)

Rebuilds the ABSD owner search index table (used by the company quick-search UI). Joins ABSD_OWGE + ABSD_OWNA + ABSD_OWST to produce a denormalized search-friendly record per company. The _PreEDMEntityChanges variant is a frozen pre-migration snapshot kept for rollback reference.

spABSD_SHIP_SEARCH_SYNC — Full Search Index Rebuild

spABSD_SHIP_SEARCH_SYNC (no parameters)

9-step full rebuild of the ABSD_SHIP_SEARCH denormalized index table (one row per vessel, ~200 columns). Called after bulk data imports or when search results are suspected to be out of sync. Steps:

  1. Populate LRNO and name fields from ABSD_OVNA (SEQNO='00')
  2. Join ABSD_OVTY for type codes (INTBASIC, TYPA-E)
  3. Join ABSD_HIFL for flag state and home port
  4. Join ABSD_HIOW, HIMA, HISM, HIOP for current ownership parties
  5. Join ABSD_HITL for gross/net tonnage and LDT
  6. Join ABSD_HIDR for DWT and draft
  7. Join ABSD_HIST for status code
  8. Join ABSD_HIMO for main engine type and kW
  9. Join SUPPLEMENTAL_ABSD_OVGE for MMSI

Runtime: 15–30 minutes. Companion SP: spPostUpdateABSD_SHIP_SEARCH (incremental post-update sync for a specific LRNO), spUpdateABSD_SHIP_SEARCH (single-vessel targeted update).

Section 12d  ·  LR Maritime Database Documentation  ·  2026-05-03