Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Contents

Table of Contents
maxLevel2

Introduction

This document has been prepared as part of a larger initiative that is looking at scalable, economical, and reusable solutions for level 2 validations.  For further context, architecture, and vocabulary refer to the associated Ed-Fi Validation Architecture document.

...

  1. Obtain the Glendale sample database from here  and restore it to a local SQL Server database.
  2. Change to the local SQL Server database.
  3. Create a new schema 'dv' for the data validation objects.

    Code Block
    languagesql
    create schema dv;


  4. Create the Validation API tables and constraints.

    IF
    Code Block
    Code Block
    languagesql
    languagesql

    Create the rules table.

    Code Block
    languagesql

    Create the stored procedure.

    collapsetrue
    -- drop FK(s) at the beginning
    IF (OBJECT_ID('dv.RunValidationRulesFK_ValidationResult_ValidationRunId', 'PF') IS NOT NULL)
    BEGIN
       DROP ALTER PROCTABLE dv.RunValidationRules;ValidationResult DROP CONSTRAINT FK_ValidationResult_ValidationRunId
    END
    go
    
    
    
    -- tracking table for validation runs
    IF OBJECT_ID('dv.ValidationRun', 'U') IS NOT NULL 
    BEGIN
      DROP TABLE dv.ValidationRun; 
    END
      
    
    IF OBJECT_ID('dv.ValidationRun', 'U') IS NOT NULL 
    BEGIN
      DROP TABLE dv.ValidationRun; 
    END
      
    Create table dv.ValidationRun
    	(ValidationRunId int not null identity primary key,
    	ValidationRunStatus varchar(60)  not null,
    	ValidationRunStartDateTime datetime not null default current_timestamp,
          ValidationRunSource varchar(60),
    	ValidationRunFinishDateTime datetime);
    
    --tracking table for validation results
    IF OBJECT_ID('dv.ValidationResult', 'U') IS NOT NULL 
    BEGIN
      DROP TABLE dv.ValidationResult; 
    END
     
    Create table dv.ValidationResult
    	(ValidationResultId int not null identity primary key,
    	ValidationRunId int ,
    	ValidationRuleId Varchar(60) not null,
    	ValidationResourceId varchar(60) not null,
    	ValidationResourceType varchar(60) not null,
        ValidationSeverity varchar(60),
    EducationOrganizationId int,
    NameSpace varchar(255),
    ValidationDetails varchar(2056),
    ValidationCategory varchar(60),
    	ResultCreatedTime datetime default current_timestamp);
    
    
    
    -- foriegn key
    ALTER TABLE dv.ValidationResult 
    	ADD  CONSTRAINT FK_ValidationResult_ValidationRunId FOREIGN KEY(ValidationRunId)
    		REFERENCES dv.ValidationRun (ValidationRunId)
    GO


  5. Create the rules table.

    Code Block
    languagesql
    collapsetrue
    IF OBJECT_ID('dv.ValidationRules', 'U') IS NOT NULL
    BEGIN 
      DROP TABLE dv.ValidationRules; 
     END
    
    create table dv.ValidationRules
    (ValidationRuleId Varchar(60) not null primary key,
    ValidationSQL Varchar(2024) not null,
    ValidationRuleSet	varchar(60),
    ValidationSeverity varchar(60),
    ValidationCategory varchar(60),
    RuleDescription Varchar(2024)
    )
    go


  6. Create the stored procedure.

    Code Block
    languagesql
    collapsetrue
    IF OBJECT_ID('dv.RunValidationRules', 'P') IS NOT NULL
    BEGIN 
      DROP PROC dv.RunValidationRules; 
     END
    go
    
    
    CREATE PROC  dv.RunValidationRules  @ValidationRuleSet varchar(60)
    AS
    	DECLARE @ValidationRuleId  varchar(max);
    	DECLARE @ValidationSQL  varchar(max);
    	DECLARE @ValidationSeverity  varchar(max);
    	DECLARE @ValidationCategory  varchar(max);
    	
    	Declare @RunId INT;
    
    	-- build a cursor that gets all of the validations for a given rule set
    	DECLARE db_cursor CURSOR for 
    		SELECT ValidationRuleId,
    				ValidationSQL,
    				ValidationSeverity,
    				ValidationCategory
    		FROM dv.ValidationRules
    	WHERE ValidationRuleSet = @ValidationRuleSet;
    
    
    	-- insert a row in the tracking table
    	insert into dv.ValidationRun(
    	validationRunStatus, ValidationRunSource) VALUES
    	('Running', @ValidationRuleSet);
    
    	--capture the ID from that insert
    	SELECT @RunId =  SCOPE_IDENTITY() ;
    
    	OPEN db_cursor;
    
    	FETCH NEXT FROM db_cursor INTO @ValidationRuleId,
    				@ValidationSQL,
    				@ValidationSeverity,
    				@ValidationCategory;
    	WHILE @@FETCH_STATUS = 0
    	BEGIN
    		-- sub in the following values
    		set @ValidationSQL= REPLACE(@ValidationSQL,'~SEVERITY~',@ValidationSeverity);
    		set @ValidationSQL= REPLACE(@ValidationSQL,'~VALIDATION_RULE_ID~',@ValidationRuleId);
    		set @ValidationSQL= REPLACE(@ValidationSQL,'~VALIDATION_CATEGORY~',@ValidationCategory);
    		set @ValidationSQL= REPLACE(@ValidationSQL,'~VALIDATION_RUN_ID~',@RunId);
    		set @ValidationSQL = concat('
    			INSERT into dv.ValidationResult
    				(ValidationRunId, ValidationRuleId, ValidationResourceId, ValidationResourceType, ValidationSeverity,
    				EducationOrganizationId, Namespace, ValidationCategory, ValidationDetails) 
    				 ', @ValidationSQL);
    	
    		print(@ValidationSQL);
    		exec(@ValidationSQL);
    				
    	FETCH NEXT FROM db_cursor INTO @ValidationRuleId,
    				@ValidationSQL,
    				@ValidationSeverity,
    				@ValidationCategory;
    
    	-- Tell the tracking table we are done
    	
    	update dv.validationRun
    	set ValidationRunStatus = 'Finished',
    		ValidationRunFinishDateTime = current_timestamp
    	where ValidationRunId = @RunId;
    	END
    
    	close db_cursor
    	DEALLOCATE db_cursor
    go


  7. Insert the sample rules into the rules table.

    Code Block
    languagesql
    collapsetrue
    INSERT INTO dv.ValidationRules (ValidationRuleId, 
    ValidationSQL,
    ValidationRuleSet,
    ValidationSeverity,
    ValidationCategory,
    RuleDescription)
    VALUES
    ('1.1',
    'SELECT top(10)
    	~VALIDATION_RUN_ID~ ValidationRunId,
    	''~VALIDATION_RULE_ID~'' ValidationRuleId,
    	StudentUniqueId as ValidationResourceId,
    	''Student'' as ValidationResourceType,
    	''~SEVERITY~'' as ValidationSeverity,
    	SchoolId as EducationOrganizationId,
    	'''' Namespace,
    	''~VALIDATION_CATEGORY~'' ValidationCategory,
    	'''' ValidationDetails
    FROM (	
    	select DISTINCT
    		c.StudentUniqueId ,
    		SchoolId
    	from edfi.student c
    	JOIN edfi.StudentSchoolAssociation on c.studentUSI = StudentSchoolAssociation.StudentUSI
    	LEFT JOIN 
    		(SELECT studentUSI, b.CodeValue
    		FROM edfi.studentAddress a
    			JOIN edfi.AddressType b	on a.AddressTypeId = b.addressTypeId
    		and b.CodeValue in ( ''Physical'', ''Home'') 
    		) d on c.studentUSI = d.studentUSI
    		)e',
    'nightly',
    'Warning',
    'Student',
    'Raise a validation warning for every student that does not have a physical address specified. Limit result set to 10.');
    
    
    
    INSERT INTO dv.ValidationRules (ValidationRuleId, 
    ValidationSQL,
    ValidationRuleSet,
    ValidationSeverity,
    ValidationCategory,
    RuleDescription)
    VALUES
    ('1.2',
    'SELECT top(10)
    	~VALIDATION_RUN_ID~ ValidationRunId,
    	''~VALIDATION_RULE_ID~'' ValidationRuleId,
    	StudentUniqueId as ValidationResourceId,
    	''Student'' as ValidationResourceType,
    	''~SEVERITY~'' as ValidationSeverity,
    	SchoolId as EducationOrganizationId,
    	'''' Namespace,
    	''~VALIDATION_CATEGORY~'' ValidationCategory,
    	ValidationDetails
    FROM (
    SELECT distinct studentUniqueId, SchoolId,
    concat(''exit date '',ExitWithdrawDate) ValidationDetails
    from edfi.studentSchoolAssociation JOIN
         edfi.Student on student.StudentUSI = StudentSchoolAssociation.StudentUSI
    where ExitWithdrawDate is not null
    and ExitWithdrawTypeDescriptorId is null) tab',
    'nightly',
    'Major Validation Error',
    'Student',
    'Raise a major validation error for every StudentSchoolAssociation where there is an ExitWithdrawDate specified but not an ExitWithdrawDescriptor specified. Limit result set to 10.');


  8. Run the stored procedure and check out the results.


    Code Block
    languagesql
    exec dv.RunValidationRules 'Nightly';
    Select * from dv.ValidationRun;
    Select * from dv.ValidationResult;


...