|
| 1 | +USE HDM_Local; |
| 2 | + |
| 3 | + |
| 4 | +SET NOCOUNT ON; |
| 5 | + |
| 6 | +-------------------------------------------------------------------------------- |
| 7 | +-- CONFIG |
| 8 | +-------------------------------------------------------------------------------- |
| 9 | +DECLARE @src_db sysname = N'HDM'; -- source DB to inspect |
| 10 | +DECLARE @src_schema sysname = N'Child_Social'; -- schema to inspect |
| 11 | +DECLARE @fail_on_error bit = 0; -- 1=raise at end, 0=just show results |
| 12 | + |
| 13 | +-------------------------------------------------------------------------------- |
| 14 | +-- RESULTS BUCKET |
| 15 | +-------------------------------------------------------------------------------- |
| 16 | +IF OBJECT_ID('tempdb..#ssd_preflight_issues') IS NOT NULL |
| 17 | + DROP TABLE #ssd_preflight_issues; |
| 18 | + |
| 19 | +CREATE TABLE #ssd_preflight_issues( |
| 20 | + check_label nvarchar(200), |
| 21 | + details nvarchar(max), |
| 22 | + sql_text nvarchar(max) |
| 23 | +); |
| 24 | + |
| 25 | +-------------------------------------------------------------------------------- |
| 26 | +-- FATAL FLAGS (record issues, don't crash) |
| 27 | +-------------------------------------------------------------------------------- |
| 28 | +DECLARE @fatal bit = 0; |
| 29 | + |
| 30 | +-------------------------------------------------------------------------------- |
| 31 | +-- CHECK: db exists? |
| 32 | +-------------------------------------------------------------------------------- |
| 33 | +IF DB_ID(@src_db) IS NULL |
| 34 | +BEGIN |
| 35 | + INSERT #ssd_preflight_issues(check_label, details, sql_text) |
| 36 | + VALUES (N'Environment', N'Db not found: ' + QUOTENAME(@src_db), NULL); |
| 37 | + SET @fatal = 1; |
| 38 | +END; |
| 39 | + |
| 40 | +-------------------------------------------------------------------------------- |
| 41 | +-- CHECK: schema exists in target DB? (record error instead of throwing) |
| 42 | +-------------------------------------------------------------------------------- |
| 43 | +IF @fatal = 0 |
| 44 | +BEGIN |
| 45 | + DECLARE @schema_check_sql nvarchar(max) = |
| 46 | + N'IF NOT EXISTS (SELECT 1 FROM ' + QUOTENAME(@src_db) + N'.sys.schemas WHERE name = @s) |
| 47 | + RAISERROR(''Schema not found: %s.%s'',16,1, @db, @s);'; |
| 48 | + |
| 49 | + BEGIN TRY |
| 50 | + EXEC sp_executesql @schema_check_sql, N'@s sysname, @db sysname', @src_schema, @src_db; |
| 51 | + END TRY |
| 52 | + BEGIN CATCH |
| 53 | + INSERT #ssd_preflight_issues(check_label, details, sql_text) |
| 54 | + VALUES (N'Environment', ERROR_MESSAGE(), NULL); |
| 55 | + SET @fatal = 1; |
| 56 | + END CATCH; |
| 57 | +END; |
| 58 | + |
| 59 | +-------------------------------------------------------------------------------- |
| 60 | +-- ONLY PROCEED TO TABLE/COLUMN CHECKS IF DB+SCHEMA LOOK OK |
| 61 | +-------------------------------------------------------------------------------- |
| 62 | +IF @fatal = 0 |
| 63 | +BEGIN |
| 64 | + ------------------------------------------------------------------------------ |
| 65 | + -- Checklist of required source tables/cols |
| 66 | + ------------------------------------------------------------------------------ |
| 67 | + DECLARE @Checks TABLE( |
| 68 | + id int identity(1,1), |
| 69 | + check_label nvarchar(200), |
| 70 | + table_name sysname, |
| 71 | + column_list nvarchar(max) |
| 72 | + ); |
| 73 | + |
| 74 | +/* ---- ssd_person sources ---- */ |
| 75 | +INSERT @Checks(check_label, table_name, column_list) VALUES |
| 76 | +(N'ssd_person: DIM_PERSON', N'DIM_PERSON', |
| 77 | + N'LEGACY_ID, DIM_PERSON_ID, FORENAME, SURNAME, GENDER_MAIN_CODE, ETHNICITY_MAIN_CODE, BIRTH_DTTM, DOB_ESTIMATED, DEATH_DTTM, NATNL_CODE, EHM_SEN_FLAG, IS_CLIENT'), |
| 78 | +(N'ssd_person: FACT_CONTACTS', N'FACT_CONTACTS', |
| 79 | + N'DIM_PERSON_ID, CONTACT_DTTM'), |
| 80 | +(N'ssd_person: FACT_REFERRALS', N'FACT_REFERRALS', |
| 81 | + N'DIM_PERSON_ID, REFRL_START_DTTM, REFRL_END_DTTM'), |
| 82 | +(N'ssd_person: FACT_903_DATA', N'FACT_903_DATA', |
| 83 | + N'DIM_PERSON_ID, NO_UPN_CODE'), |
| 84 | +(N'ssd_person: FACT_CLA_CARE_LEAVERS', N'FACT_CLA_CARE_LEAVERS', |
| 85 | + N'DIM_PERSON_ID, IN_TOUCH_DTTM'), |
| 86 | +(N'ssd_person: DIM_CLA_ELIGIBILITY', N'DIM_CLA_ELIGIBILITY', |
| 87 | + N'DIM_PERSON_ID, DIM_LOOKUP_ELIGIBILITY_STATUS_DESC'), |
| 88 | +(N'ssd_person: FACT_PERSON_RELATION', N'FACT_PERSON_RELATION', |
| 89 | + N'DIM_PERSON_ID, DIM_PERSON_ID_REL, DIM_LOOKUP_RELTN_TYPE_CODE'); |
| 90 | + |
| 91 | +/* ---- ssd_professionals sources ---- */ |
| 92 | +INSERT @Checks(check_label, table_name, column_list) VALUES |
| 93 | +(N'ssd_professionals: DIM_WORKER', N'DIM_WORKER', |
| 94 | + N'DIM_WORKER_ID, STAFF_ID, FORENAME, SURNAME, WORKER_ID_CODE, JOB_TITLE, DEPARTMENT_NAME, FULL_TIME_EQUIVALENCY'), |
| 95 | +(N'ssd_professionals: FACT_REFERRALS (caseload)', N'FACT_REFERRALS', |
| 96 | + N'DIM_WORKER_ID, REFRL_START_DTTM, REFRL_END_DTTM'); |
| 97 | + |
| 98 | +/* ---- ssd_involvements sources ---- */ |
| 99 | +INSERT @Checks(check_label, table_name, column_list) VALUES |
| 100 | +(N'ssd_involvements: FACT_INVOLVEMENTS', N'FACT_INVOLVEMENTS', |
| 101 | + N'DIM_PERSON_ID, DIM_LOOKUP_INVOLVEMENT_TYPE_CODE, IS_ALLOCATED_CW_FLAG, START_DTTM, END_DTTM, DIM_WORKER_ID'); |
| 102 | + |
| 103 | +/* ---- ssd_permanence sources ---- */ |
| 104 | +INSERT @Checks(check_label, table_name, column_list) VALUES |
| 105 | +(N'ssd_permanence: FACT_CARE_EPISODES', N'FACT_CARE_EPISODES', |
| 106 | + N'FACT_CARE_EPISODES_ID, DIM_PERSON_ID, FACT_CLA_PLACEMENT_ID, FACT_CLA_ID, CARE_REASON_END_CODE, PLACEND'), |
| 107 | +(N'ssd_permanence: FACT_ADOPTION', N'FACT_ADOPTION', |
| 108 | + N'DIM_PERSON_ID, START_DTTM, ADOPTION_ORDER_DATE, ADOPTER_SEX, ADOPTER_NUMBER, ADOPTION_DECISION_DATE'), |
| 109 | +(N'ssd_permanence: FACT_CLA_PLACEMENT', N'FACT_CLA_PLACEMENT', |
| 110 | + N'FACT_CLA_PLACEMENT_ID, FFA_IS_PLAN_DATE, DIM_LOOKUP_PLACEMENT_TYPE_CODE'), |
| 111 | +(N'ssd_permanence: FACT_CLA', N'FACT_CLA', |
| 112 | + N'FACT_CLA_ID, ENTERED_CARE_DATE'); |
| 113 | + |
| 114 | +/* ---- ssd_cp_visits sources ---- */ |
| 115 | +INSERT @Checks(check_label, table_name, column_list) VALUES |
| 116 | +(N'ssd_cp_visits: FACT_CASENOTES', N'FACT_CASENOTES', |
| 117 | + N'FACT_CASENOTE_ID, DIM_PERSON_ID, DIM_LOOKUP_CASNT_TYPE_ID_CODE, EVENT_DTTM, SEEN_FLAG, SEEN_ALONE_FLAG, SEEN_BEDROOM_FLAG'), |
| 118 | +(N'ssd_cp_visits: FACT_CP_VISIT', N'FACT_CP_VISIT', |
| 119 | + N'FACT_CASENOTE_ID, FACT_CP_PLAN_ID'); |
| 120 | + |
| 121 | +/* ---- ssd_assessment_factors sources ---- */ |
| 122 | +INSERT @Checks(check_label, table_name, column_list) VALUES |
| 123 | +(N'ssd_assessment_factors: FACT_SINGLE_ASSESSMENT', N'FACT_SINGLE_ASSESSMENT', |
| 124 | + N'FACT_SINGLE_ASSESSMENT_ID, DIM_PERSON_ID, FACT_REFERRAL_ID, START_DTTM, FACT_FORM_ID, EXTERNAL_ID'), |
| 125 | +(N'ssd_assessment_factors: FACT_FORM_ANSWERS', N'FACT_FORM_ANSWERS', |
| 126 | + N'FACT_FORM_ID, ANSWER_NO, ANSWER, DIM_ASSESSMENT_TEMPLATE_ID_DESC'), |
| 127 | +(N'ssd_assessment_factors: FACT_FORMS', N'FACT_FORMS', |
| 128 | + N'FACT_FORM_ID, DIM_PERSON_ID'); |
| 129 | + |
| 130 | +/* ---- ssd_department sources ---- */ |
| 131 | +INSERT @Checks(check_label, table_name, column_list) VALUES |
| 132 | +(N'ssd_department: DIM_DEPARTMENT', N'DIM_DEPARTMENT', |
| 133 | + N'DIM_DEPARTMENT_ID, NAME, DEPT_ID, DEPT_TYPE_DESCRIPTION'); |
| 134 | + |
| 135 | +/* ---- (optional) extra checks used elsewhere in ssd ---- */ |
| 136 | +INSERT @Checks(check_label, table_name, column_list) VALUES |
| 137 | +(N'ssd_contacts: FACT_CONTACTS', N'FACT_CONTACTS', |
| 138 | + N'FACT_CONTACT_ID, DIM_PERSON_ID, CONTACT_DTTM, DIM_LOOKUP_CONT_SORC_ID, DIM_LOOKUP_CONT_SORC_ID_DESC, OUTCOME_NEW_REFERRAL_FLAG, OUTCOME_EXISTING_REFERRAL_FLAG, OUTCOME_CP_ENQUIRY_FLAG, OUTCOME_NFA_FLAG, OUTCOME_NON_AGENCY_ADOPTION_FLAG, OUTCOME_PRIVATE_FOSTERING_FLAG, OUTCOME_ADVICE_FLAG, OUTCOME_MISSING_FLAG, OUTCOME_OLA_CP_FLAG, OTHER_OUTCOMES_EXIST_FLAG, TOTAL_NO_OF_OUTCOMES, OUTCOME_COMMENTS'), |
| 139 | +(N'ssd_cin_episodes: FACT_REFERRALS', N'FACT_REFERRALS', |
| 140 | + N'FACT_REFERRAL_ID, DIM_PERSON_ID, REFRL_START_DTTM, REFRL_END_DTTM, DIM_LOOKUP_CATEGORY_OF_NEED_CODE, DIM_LOOKUP_CONT_SORC_ID, DIM_LOOKUP_CONT_SORC_ID_DESC, OUTCOME_SINGLE_ASSESSMENT_FLAG, OUTCOME_NFA_FLAG, OUTCOME_STRATEGY_DISCUSSION_FLAG, OUTCOME_CLA_REQUEST_FLAG, OUTCOME_NON_AGENCY_ADOPTION_FLAG, OUTCOME_PRIVATE_FOSTERING_FLAG, OUTCOME_CP_TRANSFER_IN_FLAG, OUTCOME_CP_CONFERENCE_FLAG, OUTCOME_CARE_LEAVER_FLAG, OTHER_OUTCOMES_EXIST_FLAG, TOTAL_NO_OF_OUTCOMES, OUTCOME_COMMENTS, DIM_DEPARTMENT_ID, DIM_WORKER_ID_DESC'), |
| 141 | +(N'ssd_cp_plans: FACT_CP_PLAN', N'FACT_CP_PLAN', |
| 142 | + N'FACT_CP_PLAN_ID, FACT_REFERRAL_ID, FACT_INITIAL_CP_CONFERENCE_ID, DIM_PERSON_ID, START_DTTM, END_DTTM, IS_OLA, INIT_CATEGORY_DESC, CP_CATEGORY_DESC'); |
| 143 | + |
| 144 | + |
| 145 | + ------------------------------------------------------------------------------ |
| 146 | + -- Loop: table exists? then list missing columns (metadata-only; no data reads) |
| 147 | + ------------------------------------------------------------------------------ |
| 148 | + DECLARE |
| 149 | + @i int = 1, @n int = (SELECT COUNT(*) FROM @Checks), |
| 150 | + @label nvarchar(200), @tbl sysname, @cols nvarchar(max), @dsql nvarchar(max), |
| 151 | + @nonce char(36) = CONVERT(char(36), NEWID()); |
| 152 | + |
| 153 | + WHILE @i <= @n |
| 154 | + BEGIN |
| 155 | + SELECT @label = check_label, @tbl = table_name, @cols = column_list |
| 156 | + FROM @Checks WHERE id = @i; |
| 157 | + |
| 158 | + SET @dsql = N' |
| 159 | +IF NOT EXISTS ( |
| 160 | + SELECT 1 |
| 161 | + FROM ' + QUOTENAME(@src_db) + N'.sys.tables t |
| 162 | + JOIN ' + QUOTENAME(@src_db) + N'.sys.schemas s ON s.schema_id = t.schema_id |
| 163 | + WHERE s.name = @sch AND t.name = @tbl |
| 164 | +) |
| 165 | +BEGIN |
| 166 | + INSERT #ssd_preflight_issues(check_label, details, sql_text) |
| 167 | + VALUES ( |
| 168 | + @label, |
| 169 | + N''Table not found: '' + QUOTENAME(@db) + N''.'' + QUOTENAME(@sch) + N''.'' + QUOTENAME(@tbl), |
| 170 | + NULL |
| 171 | + ); |
| 172 | +END |
| 173 | +ELSE |
| 174 | +BEGIN |
| 175 | + -- Split comma-separated @cols into rows via XML (trim spaces) |
| 176 | + DECLARE @xml xml = |
| 177 | + CONVERT(xml, N''<c><i>'' + REPLACE(@cols, N'','', N''</i><i>'') + N''</i></c>''); |
| 178 | +
|
| 179 | + ;WITH want AS ( |
| 180 | + SELECT CAST(LTRIM(RTRIM(T.c.value(''.'', ''nvarchar(4000)''))) AS sysname) AS col |
| 181 | + FROM @xml.nodes(''/c/i'') AS T(c) |
| 182 | + ), |
| 183 | + have AS ( |
| 184 | + SELECT c.name AS col |
| 185 | + FROM ' + QUOTENAME(@src_db) + N'.sys.columns c |
| 186 | + JOIN ' + QUOTENAME(@src_db) + N'.sys.tables t ON t.object_id = c.object_id |
| 187 | + JOIN ' + QUOTENAME(@src_db) + N'.sys.schemas s ON s.schema_id = t.schema_id |
| 188 | + WHERE s.name = @sch AND t.name = @tbl |
| 189 | + ) |
| 190 | + INSERT #ssd_preflight_issues(check_label, details, sql_text) |
| 191 | + SELECT |
| 192 | + @label, |
| 193 | + N''Missing column: '' + w.col, |
| 194 | + N''SELECT '' + @cols + N'' FROM '' + QUOTENAME(@db) + N''.'' + QUOTENAME(@sch) + N''.'' + QUOTENAME(@tbl) + N'' WHERE 1=0;'' |
| 195 | + FROM want w |
| 196 | + LEFT JOIN have h ON h.col = w.col |
| 197 | + WHERE h.col IS NULL |
| 198 | + OPTION (RECOMPILE); |
| 199 | +END'; |
| 200 | + |
| 201 | + -- make text unique per run to avoid stale cached plans |
| 202 | + SET @dsql = @dsql + N' -- ' + @nonce; |
| 203 | + |
| 204 | + EXEC sp_executesql |
| 205 | + @dsql, |
| 206 | + N'@sch sysname, @tbl sysname, @cols nvarchar(max), @label nvarchar(200), @db sysname', |
| 207 | + @src_schema, @tbl, @cols, @label, @src_db; |
| 208 | + |
| 209 | + SET @i += 1; |
| 210 | + END |
| 211 | +END; -- end of @fatal=0 guard |
| 212 | + |
| 213 | +-------------------------------------------------------------------------------- |
| 214 | +-- REPORT (always SELECT details; opt: raise to fail run) |
| 215 | +-------------------------------------------------------------------------------- |
| 216 | +DECLARE @issue_count int = (SELECT COUNT(*) FROM #ssd_preflight_issues); |
| 217 | + |
| 218 | +IF @issue_count > 0 |
| 219 | +BEGIN |
| 220 | + -- if we found any col/table absence issues, show them |
| 221 | + SELECT check_label, details, sql_text |
| 222 | + FROM #ssd_preflight_issues |
| 223 | + ORDER BY check_label, details; |
| 224 | + |
| 225 | + IF @fail_on_error = 1 |
| 226 | + RAISERROR('Pre-flight failed: %d issue(s) found. See result set above.', 16, 1, @issue_count); |
| 227 | + ELSE |
| 228 | + PRINT 'Pre-flight completed with issues. See result set above.'; |
| 229 | +END |
| 230 | +ELSE |
| 231 | +BEGIN |
| 232 | + PRINT 'Pre-flight OK: all required ssd source tables/columns were found.'; |
| 233 | +END |
| 234 | + |
| 235 | + |
0 commit comments