Skip to main content

Column roles

Every column is classified into one of these roles:
RoleDescriptionExample
PKPrimary key — globally unique identifierGIFT_KEY
FKForeign key — references a primary key in another tableCONTACT_KEY
IdentifierNon-key internal numeric ID (not for joins)GIFT_ID
Date/TimeTimestamp or date fieldGIFT_DATE_UTC
FlagBoolean true/false fieldGIFT_IS_DELETED
SystemSnowflake sync metadata columnSF__ROW_SYNCED_DATE_TIME_UTC
AttributeAll other business data columnsAMOUNT, NAME

Key column conventions

_KEY vs _ID

SuffixTypeUse for joins?Notes
_KEYTEXTYes — always use thisGlobal hash-based key; stable across environments
_IDNUMBERNoVirtuous internal numeric ID; not reliable for cross-table joins

_IS_DELETED

Every table has an ENTITY_IS_DELETED flag. Always filter WHERE ENTITY_IS_DELETED = FALSE — soft-deleted records are retained in the table but should be excluded from reports.

SF__ prefix

Columns prefixed with SF__ are Snowflake sync metadata (e.g. SF__ROW_SYNCED_DATE_TIME_UTC). Use SF__ROW_SYNCED_DATE_TIME_UTC to check data freshness. These columns are not business data and can be ignored in most queries.

Core tables quick reference

TableGrainPrimary KeyKey foreign keys
CONTACTSOne row per contact (household or org)CONTACT_KEY
CONTACT_INDIVIDUALSOne row per person within a contactCONTACT_INDIVIDUAL_KEYCONTACT_KEY
GIFTSOne row per gift transactionGIFT_KEYCONTACT_KEY, SEGMENT_KEY
GIFT_DESIGNATIONSOne row per project split within a giftGIFT_DESIGNATION_KEYGIFT_KEY, PROJECT_KEY
PROJECTSOne row per fund or programPROJECT_KEY
CAMPAIGNSOne row per campaignCAMPAIGN_KEY
COMMUNICATIONSOne row per channel within a campaignCOMMUNICATION_KEYCAMPAIGN_KEY
SEGMENTSOne row per audience subgroup within a communicationSEGMENT_KEYCOMMUNICATION_KEY
RECURRING_GIFTSOne row per recurring giving commitmentRECURRING_GIFT_KEYCONTACT_KEY
RECURRING_GIFT_PAYMENTSOne row per recurring payment instanceRECURRING_GIFT_PAYMENT_KEYRECURRING_GIFT_KEY, GIFT_KEY
PLEDGESOne row per pledge commitmentPLEDGE_KEYCONTACT_KEY, GIFT_ASK_KEY
PLEDGE_PAYMENTSOne row per pledge installmentPLEDGE_PAYMENT_KEYPLEDGE_KEY, GIFT_KEY
GIFT_ASKSOne row per formal gift solicitationGIFT_ASK_KEYCONTACT_KEY, PROJECT_KEY
TASKSOne row per task associated with a contactTASK_KEYCONTACT_KEY
RECEIPTSOne row per receipt issued to a contactRECEIPT_KEYCONTACT_KEY
TYPE_REFERENCESOne row per valid code value
All tables above are in the CRM_RAW table group. In Snowflake SQL, reference them as [database].[schema].TABLE_NAME.

Finding columns with numeric codes

To identify every column in the schema that may need a decode lookup:
SELECT
    TABLE_NAME,
    COLUMN_NAME,
    DATA_TYPE,
    COMMENT AS DESCRIPTION
FROM [database].INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = '[schema]'
    AND (
        COLUMN_NAME LIKE '%STATUS%'
        OR COLUMN_NAME LIKE '%TYPE%'
        OR COLUMN_NAME LIKE '%FREQUENCY%'
    )
    AND COLUMN_NAME NOT LIKE '%_KEY'
    AND COLUMN_NAME NOT LIKE '%_ID'
ORDER BY TABLE_NAME, COLUMN_NAME;
Cross-reference the results against Lookup values to find the correct ENTITY and PROPERTY values for the decode join.
Data freshness: These tables sync continuously from Virtuous CRM. Typical lag is under 4 hours. To check when a record was last updated, inspect the SF__ROW_SYNCED_DATE_TIME_UTC column on any table.
Last modified on May 22, 2026