execsql2 1.130.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,639 @@
1
+ -- ss_compare.sql
2
+ --
3
+ -- PURPOSE
4
+ -- Generate MS-SQL-Server-specific SQL to compare the attributes (non-PK columns)
5
+ -- in a staging table to the equivalently-named base table.
6
+ --
7
+ -- NOTES
8
+ -- 1. The scripts contained in this file that are intended to be called
9
+ -- directly by the user are:
10
+ -- COMPARE_COMMON : Produces SQL that represents comparison
11
+ -- results as categories of "Same", "Different",
12
+ -- "Old", and "New".
13
+ -- COMPARE_COMMON_VALS : Produces SQL that shows both base and
14
+ -- staging values in adjacent columns.
15
+ -- COMPARE_CHANGES : Produces SQL that shows all primary keys in
16
+ -- the staging table plus a column named "changes"
17
+ -- that identifiers whether that row in the
18
+ -- staging table is new, is a changed version of
19
+ -- an existing row, or is identical to an
20
+ -- existing row.
21
+ -- COMPARE_CHANGED : Produces SQL that shows all primary keys in
22
+ -- the base table plus a column named "changed"
23
+ -- that identifiers whether that row exists in
24
+ -- the staging table, has different data in the
25
+ -- staging table, or has identical data in the
26
+ -- staging table.
27
+ -- 2. These scripts query the information schema to obtain
28
+ -- the information needed to generate SQL.
29
+ -- 3. Temporary tables and views created by these scripts all
30
+ -- begin with "cmp_".
31
+ -- 4. This script requires SQL Server 2017 or later.
32
+ --
33
+ -- AUTHOR
34
+ -- Dreas Nielsen (RDN)
35
+ --
36
+ -- COPYRIGHT AND LICENSE
37
+ -- Copyright (c) 2020 R.Dreas Nielsen
38
+ -- This program is free software: you can redistribute it and/or modify
39
+ -- it under the terms of the GNU General Public License as published by
40
+ -- the Free Software Foundation, either version 3 of the License, or
41
+ -- (at your option) any later version.
42
+ -- This program is distributed in the hope that it will be useful,
43
+ -- but WITHOUT ANY WARRANTY; without even the implied warranty of
44
+ -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
45
+ -- GNU General Public License for more details.
46
+ -- The GNU General Public License is available at <http://www.gnu.org/licenses/>
47
+ --
48
+ -- VERSION
49
+ -- 1.1.1
50
+ --
51
+ -- HISTORY
52
+ -- Date Remarks
53
+ -- ---------- -----------------------------------------------------
54
+ -- 2020-02-29 Created from v. 1.1.1 for Postgres. RDN.
55
+ -- 2020-03-01 Modified for SQL Server. RDN.
56
+ -- ==================================================================
57
+
58
+
59
+ -- ################################################################
60
+ -- Script COMPARE_COMMON
61
+ -- ===============================================================
62
+ --
63
+ -- Generate SQL to compare the attributes of base and staging
64
+ -- tables for only those primary keys in common. This uses an
65
+ -- inner join between the tables, and does not include any rows
66
+ -- with a primary key that is in one table and not the other.
67
+ --
68
+ -- The output includes a column for every column in the base
69
+ -- table (except those explicitly excluded). Primary key
70
+ -- columns are populated with primary key values. Attribute
71
+ -- columns are populated with one of the following tags:
72
+ -- Same : The value in base and staging tables
73
+ -- are the same.
74
+ -- Different : The values in base and staging tables
75
+ -- are different.
76
+ -- Old : There is a value in the base table but
77
+ -- no value (i.e., null) in the staging table.
78
+ -- New : There is a value in the staging table
79
+ -- but no value (i.e., null) in the base table.
80
+ --
81
+ -- Required input arguments:
82
+ -- base_schema : The name of the base table schema.
83
+ -- staging : The name of the staging schema.
84
+ -- table : The name of the table to compare.
85
+ -- The table must have the same name
86
+ -- in base and staging schemas.
87
+ --
88
+ -- Optional input arguments:
89
+ -- include_cols : Contains a comma-separated list of single-quoted
90
+ -- column names in the base table that are the
91
+ -- *only* attribute columns to be compared.
92
+ -- exclude_cols : Contains a comma-separated list of single-quoted
93
+ -- column names in the base table that are not to
94
+ -- be compared. If 'include_cols' is provided,
95
+ -- 'exclude_cols' is ignored.
96
+ --
97
+ -- Required output arguments:
98
+ -- sql_var : The name of the variable into which
99
+ -- the generated SQL will be stored
100
+ --
101
+ -- Notes
102
+ -- 1. The generated SQL is not terminated with a semicolon.
103
+ -- ===============================================================
104
+ -- !x! BEGIN SCRIPT COMPARE_COMMON with parameters (base_schema, staging, table, sql_var)
105
+
106
+ -- Create a table of primary key columns for the table
107
+ if object_id('tempdb..#cmp_primary_key_columns') is not null drop table #cmp_primary_key_columns;
108
+ select k.column_name, k.ordinal_position
109
+ into #cmp_primary_key_columns
110
+ from information_schema.table_constraints as tc
111
+ inner join information_schema.key_column_usage as k
112
+ on tc.constraint_type = 'PRIMARY KEY'
113
+ and tc.constraint_name = k.constraint_name
114
+ and tc.constraint_catalog = k.constraint_catalog
115
+ and tc.constraint_schema = k.constraint_schema
116
+ and tc.table_schema = k.table_schema
117
+ and tc.table_name = k.table_name
118
+ and tc.constraint_name = k.constraint_name
119
+ where
120
+ k.table_name = '!!#table!!'
121
+ and k.table_schema = '!!#base_schema!!'
122
+ order by k.ordinal_position
123
+ ;
124
+
125
+ -- !x! if(not hasrows(#cmp_primary_key_columns)) { halt message "Table !!#table!! has no primary key columns." }
126
+
127
+ -- Populate a (temporary) table with the names of the attribute columns
128
+ -- that are to be compared.
129
+ -- Include only those columns from the staging table that are also in the base table.
130
+ -- !x! sub_empty ~col_sel
131
+ -- !x! if(sub_defined(#include_cols))
132
+ -- !x! sub ~col_sel and s.column_name in (!!#include_cols!!)
133
+ -- !x! elseif(sub_defined(#exclude_cols))
134
+ -- !x! sub ~col_sel and s.column_name not in (!!#exclude_cols!!)
135
+ -- !x! endif
136
+ if object_id('tempdb..#cmp_cols') is not null drop table #cmp_cols;
137
+ select s.column_name
138
+ into #cmp_cols
139
+ from information_schema.columns as s
140
+ inner join information_schema.columns as b on s.column_name=b.column_name
141
+ left join #cmp_primary_key_columns as pk on pk.column_name = s.column_name
142
+ where
143
+ s.table_schema = '!!#staging!!'
144
+ and s.table_name = '!!#table!!'
145
+ and b.table_schema = '!!#base_schema!!'
146
+ and b.table_name = '!!#table!!'
147
+ and pk.column_name is null
148
+ !!~col_sel!!
149
+ order by s.ordinal_position;
150
+
151
+ -- Create the SQL to select primary key columns from the base table.
152
+ if object_id('tempdb..#cmp_pkexpr') is not null drop table #cmp_pkexpr;
153
+ select
154
+ string_agg('b.' + column_name, ', ') as pksel
155
+ into
156
+ #cmp_pkexpr
157
+ from
158
+ #cmp_primary_key_columns;
159
+ -- !x! subdata ~pkcolexpr #cmp_pkexpr
160
+
161
+
162
+ -- Create the SQL for each column to compare the base (b) and staging (s) tables.
163
+ alter table #cmp_cols add sqlcmd varchar(max);
164
+ update #cmp_cols
165
+ set sqlcmd =
166
+ 'case when b.' + column_name + ' is null then case when s.' + column_name + ' is null then ''Same'' else ''New'' end else case when s.' + column_name + ' is null then ''Old'' else case when b.' + column_name + ' = s.' + column_name + ' then ''Same'' else ''Different'' end end end as ' + column_name
167
+ ;
168
+
169
+ -- Create the comparison expression for all columns.
170
+ if object_id('tempdb..#cmp_compexpr') is not null drop table #cmp_compexpr;
171
+ select
172
+ string_agg(sqlcmd, ', ') as attcomp
173
+ into
174
+ #cmp_compexpr
175
+ from
176
+ #cmp_cols;
177
+ -- !x! subdata ~compexpr #cmp_compexpr
178
+
179
+ -- Create a join expression for primary key columns of the base (b) and
180
+ -- staging (s) tables.
181
+ if object_id('tempdb..#cmp_joinexpr') is not null drop table #cmp_joinexpr;
182
+ select
183
+ string_agg('b.' + column_name + ' = s.' + column_name, ' and ') as joinexpr
184
+ into
185
+ #cmp_joinexpr
186
+ from
187
+ #cmp_primary_key_columns;
188
+ -- !x! subdata ~joinexpr #cmp_joinexpr
189
+
190
+
191
+ -- Create and assign the entire SQL.
192
+ -- !x! sub !!#sql_var!! select !!~pkcolexpr!!, !!~compexpr!! from !!#base_schema!!.!!#table!! as b inner join !!#staging!!.!!#table!! as s on !!~joinexpr!!
193
+
194
+
195
+
196
+ -- !x! END SCRIPT COMPARE_COMMON
197
+
198
+ -- #################### End of COMPARE_COMMON ###################
199
+ -- ################################################################
200
+
201
+
202
+
203
+ -- ################################################################
204
+ -- Script COMPARE_COMMON_VALS
205
+ -- ===============================================================
206
+ --
207
+ -- Generate SQL to compare the attributes of base and staging
208
+ -- tables for only those primary keys in common. This uses an
209
+ -- inner join between the tables, and does not include any rows
210
+ -- with a primary key that is in one table and not the other.
211
+ --
212
+ -- The output includes two columns for every attribute column in
213
+ -- the base table (except those explicitly excluded), plus a column
214
+ -- for every primary key column. Primary key
215
+ -- columns are populated with primary key values. The two output
216
+ -- columns for each attribute column in the base table have names that
217
+ -- match the base table column name plus a suffix of either "_old",
218
+ -- representing the base table, or "_new", representing the staging
219
+ -- table.
220
+ --
221
+ -- Required input arguments:
222
+ -- base_schema : The name of the base table schema.
223
+ -- staging : The name of the staging schema.
224
+ -- table : The name of the table to compare.
225
+ -- The table must have the same name
226
+ -- in base and staging schemas.
227
+ --
228
+ -- Optional input arguments:
229
+ -- include_cols : Contains a comma-separated list of single-quoted
230
+ -- column names in the base table that are the
231
+ -- *only* attribute columns to be compared.
232
+ -- exclude_cols : Contains a comma-separated list of single-quoted
233
+ -- column names in the base table that are not to
234
+ -- be compared. If 'include_cols' is provided,
235
+ -- 'exclude_cols' is ignored.
236
+ --
237
+ -- Required output arguments:
238
+ -- sql_var : The name of the variable into which
239
+ -- the generated SQL will be stored
240
+ --
241
+ -- Notes
242
+ -- 1. The generated SQL is not terminated with a semicolon.
243
+ -- ===============================================================
244
+ -- !x! BEGIN SCRIPT COMPARE_COMMON_VALS with parameters (base_schema, staging, table, sql_var)
245
+
246
+ -- Create a table of primary key columns for the table
247
+ if object_id('tempdb..#cmp_primary_key_columns') is not null drop table #cmp_primary_key_columns;
248
+ select k.column_name, k.ordinal_position
249
+ into #cmp_primary_key_columns
250
+ from information_schema.table_constraints as tc
251
+ inner join information_schema.key_column_usage as k
252
+ on tc.constraint_type = 'PRIMARY KEY'
253
+ and tc.constraint_name = k.constraint_name
254
+ and tc.constraint_catalog = k.constraint_catalog
255
+ and tc.constraint_schema = k.constraint_schema
256
+ and tc.table_schema = k.table_schema
257
+ and tc.table_name = k.table_name
258
+ and tc.constraint_name = k.constraint_name
259
+ where
260
+ k.table_name = '!!#table!!'
261
+ and k.table_schema = '!!#base_schema!!'
262
+ order by k.ordinal_position
263
+ ;
264
+
265
+ -- !x! if(not hasrows(#cmp_primary_key_columns)) { halt message "Table !!#table!! has no primary key columns." }
266
+
267
+ -- Populate a (temporary) table with the names of the attribute columns
268
+ -- that are to be compared.
269
+ -- Include only those columns from the staging table that are also in the base table.
270
+ -- !x! sub_empty ~col_sel
271
+ -- !x! if(sub_defined(#include_cols))
272
+ -- !x! sub ~col_sel and s.column_name in (!!#include_cols!!)
273
+ -- !x! elseif(sub_defined(#exclude_cols))
274
+ -- !x! sub ~col_sel and s.column_name not in (!!#exclude_cols!!)
275
+ -- !x! endif
276
+ if object_id('tempdb..#cmp_cols') is not null drop table #cmp_cols;
277
+ select s.column_name
278
+ into #cmp_cols
279
+ from information_schema.columns as s
280
+ inner join information_schema.columns as b on s.column_name=b.column_name
281
+ left join #cmp_primary_key_columns as pk on pk.column_name = s.column_name
282
+ where
283
+ s.table_schema = '!!#staging!!'
284
+ and s.table_name = '!!#table!!'
285
+ and b.table_schema = '!!#base_schema!!'
286
+ and b.table_name = '!!#table!!'
287
+ and pk.column_name is null
288
+ !!~col_sel!!
289
+ order by s.ordinal_position;
290
+
291
+ -- Create the SQL to select primary key columns from the base table.
292
+ if object_id('tempdb..#cmp_pkexpr') is not null drop table #cmp_pkexpr;
293
+ select
294
+ string_agg('b.' + column_name, ', ') as pkexpr
295
+ into
296
+ #cmp_pkexpr
297
+ from
298
+ #cmp_primary_key_columns;
299
+ -- !x! subdata ~pkcolexpr #cmp_pkexpr
300
+
301
+
302
+ -- Create the SQL for each column to compare the base (b) and staging (s) tables.
303
+ alter table #cmp_cols add sqlcmd varchar(max);
304
+ update #cmp_cols
305
+ set sqlcmd =
306
+ 'b.' + column_name + ' as ' + column_name + '_old, s.' + column_name + ' as ' + column_name + '_new'
307
+ ;
308
+
309
+ -- Create the comparison expression for all columns.
310
+ if object_id('tempdb..#cmp_compexpr') is not null drop table #cmp_compexpr;
311
+ select
312
+ string_agg(sqlcmd, ', ') as compexpr
313
+ into
314
+ #cmp_compexpr
315
+ from
316
+ #cmp_cols;
317
+ -- !x! subdata ~compexpr #cmp_compexpr
318
+
319
+ -- Create a join expression for primary key columns of the base (b) and
320
+ -- staging (s) tables.
321
+ if object_id('tempdb..#cmp_joinexpr') is not null drop table #cmp_joinexpr;
322
+ select
323
+ string_agg('b.' + column_name + ' = s.' + column_name, ' and ') as joinexpr
324
+ into
325
+ #cmp_joinexpr
326
+ from
327
+ #cmp_primary_key_columns;
328
+ -- !x! subdata ~joinexpr #cmp_joinexpr
329
+
330
+
331
+ -- Create and assign the entire SQL.
332
+ -- !x! sub !!#sql_var!! select !!~pkcolexpr!!, !!~compexpr!! from !!#base_schema!!.!!#table!! as b inner join !!#staging!!.!!#table!! as s on !!~joinexpr!!
333
+
334
+
335
+
336
+ -- !x! END SCRIPT COMPARE_COMMON_VALS
337
+
338
+ -- ############### End of COMPARE_COMMON_VALS ###################
339
+ -- ################################################################
340
+
341
+
342
+
343
+
344
+
345
+ -- ################################################################
346
+ -- Script COMPARE_CHANGES
347
+ -- ===============================================================
348
+ --
349
+ -- Generate SQL to characterize every row of the staging table
350
+ -- data as either a new row, a row with changed data, or a row
351
+ -- with data that are unchanged relative to the base table.
352
+ --
353
+ -- The output includes a column for every primary key plus a
354
+ -- column named "changes" with one of the following tags:
355
+ -- NewRow : The primary key is in the staging table
356
+ -- but not in the base table.
357
+ -- Changed : At least one of the attribute values is
358
+ -- different in the staging table.
359
+ -- Unchanged : All attribute values are the same in the
360
+ -- staging and base tables.
361
+ --
362
+ -- Required input arguments:
363
+ -- base_schema : The name of the base table schema.
364
+ -- staging : The name of the staging schema.
365
+ -- table : The name of the table to compare.
366
+ -- The table must have the same name
367
+ -- in base and staging schemas.
368
+ --
369
+ -- Optional input arguments:
370
+ -- include_cols : Contains a comma-separated list of single-quoted
371
+ -- column names in the base table that are the
372
+ -- *only* attribute columns to be compared.
373
+ -- exclude_cols : Contains a comma-separated list of single-quoted
374
+ -- column names in the base table that are not to
375
+ -- be compared. If 'include_cols' is provided,
376
+ -- 'exclude_cols' is ignored.
377
+ --
378
+ -- Required output arguments:
379
+ -- sql_var : The name of the variable into which
380
+ -- the generated SQL will be stored
381
+ --
382
+ -- Notes
383
+ -- 1. The generated SQL is not terminated with a semicolon.
384
+ -- ===============================================================
385
+ -- !x! BEGIN SCRIPT COMPARE_CHANGES with parameters (base_schema, staging, table, sql_var)
386
+
387
+ -- Create a table of primary key columns for the table
388
+ if object_id('tempdb..#cmp_primary_key_columns') is not null drop table #cmp_primary_key_columns;
389
+ select k.column_name, k.ordinal_position
390
+ into #cmp_primary_key_columns
391
+ from information_schema.table_constraints as tc
392
+ inner join information_schema.key_column_usage as k
393
+ on tc.constraint_type = 'PRIMARY KEY'
394
+ and tc.constraint_name = k.constraint_name
395
+ and tc.constraint_catalog = k.constraint_catalog
396
+ and tc.constraint_schema = k.constraint_schema
397
+ and tc.table_schema = k.table_schema
398
+ and tc.table_name = k.table_name
399
+ and tc.constraint_name = k.constraint_name
400
+ where
401
+ k.table_name = '!!#table!!'
402
+ and k.table_schema = '!!#base_schema!!'
403
+ order by k.ordinal_position
404
+ ;
405
+
406
+ -- !x! if(not hasrows(#cmp_primary_key_columns)) { halt message "Table !!#table!! has no primary key columns." }
407
+
408
+ -- Populate a (temporary) table with the names of the attribute columns
409
+ -- that are to be compared.
410
+ -- Include only those columns from the staging table that are also in the base table.
411
+ -- !x! sub_empty ~col_sel
412
+ -- !x! if(sub_defined(#include_cols))
413
+ -- !x! sub ~col_sel and s.column_name in (!!#include_cols!!)
414
+ -- !x! elseif(sub_defined(#exclude_cols))
415
+ -- !x! sub ~col_sel and s.column_name not in (!!#exclude_cols!!)
416
+ -- !x! endif
417
+ if object_id('tempdb..#cmp_cols') is not null drop table #cmp_cols;
418
+ select s.column_name
419
+ into #cmp_cols
420
+ from information_schema.columns as s
421
+ inner join information_schema.columns as b on s.column_name=b.column_name
422
+ left join #cmp_primary_key_columns as pk on pk.column_name = s.column_name
423
+ where
424
+ s.table_schema = '!!#staging!!'
425
+ and s.table_name = '!!#table!!'
426
+ and b.table_schema = '!!#base_schema!!'
427
+ and b.table_name = '!!#table!!'
428
+ !!~col_sel!!
429
+ order by s.ordinal_position;
430
+
431
+ -- Create the SQL to select primary key columns from the staging table.
432
+ if object_id('tempdb..#cmp_pkexpr') is not null drop table #cmp_pkexpr;
433
+ select
434
+ string_agg('s.' + column_name, ', ') as pkexpr
435
+ into
436
+ #cmp_pkexpr
437
+ from
438
+ #cmp_primary_key_columns;
439
+ -- !x! subdata ~pkcolexpr #cmp_pkexpr
440
+
441
+
442
+ -- Create the SQL for each column to compare the base (b) and staging (s) tables.
443
+ -- This generates a value of 1 when there are differences and 0 when there are not.
444
+ alter table #cmp_cols add sqlcmd varchar(max);
445
+ update #cmp_cols
446
+ set sqlcmd =
447
+ 'case when b.' + column_name + ' is null then case when s.' + column_name + ' is null then 0 else 1 end else case when s.' + column_name + ' is null then 1 else case when b.' + column_name + ' = s.' + column_name + ' then 0 else 1 end end end'
448
+ ;
449
+
450
+ -- Create the expression to determine whether there is a difference for any column.
451
+ if object_id('tempdb..#cmp_compexpr') is not null drop table #cmp_compexpr;
452
+ select
453
+ string_agg(sqlcmd, ' + ') as compexpr
454
+ into
455
+ #cmp_compexpr
456
+ from
457
+ #cmp_cols;
458
+ -- !x! subdata ~compexpr #cmp_compexpr
459
+ -- !x! sub ~diffexpr case when !!~compexpr!! = 0 then 'Unchanged' else 'Changed' end
460
+
461
+ -- Create a join expression for primary key columns of the base (b) and
462
+ -- staging (s) tables.
463
+ if object_id('tempdb..#cmp_joinexpr') is not null drop table #cmp_joinexpr;
464
+ select
465
+ string_agg('b.' + column_name + ' = s.' + column_name, ' and ') as joinexpr
466
+ into
467
+ #cmp_joinexpr
468
+ from
469
+ #cmp_primary_key_columns;
470
+ -- !x! subdata ~joinexpr #cmp_joinexpr
471
+
472
+ -- Get the name of a single primary key column, aliased to the base table,
473
+ -- to test for row existence in the base table.
474
+ -- !x! subdata pkcol1 #cmp_primary_key_columns
475
+
476
+ -- Create the SQL to display either the row tag or the comparison tag.
477
+ -- !x! sub ~changeexpr case when b.!!pkcol1!! is null then 'NewRow' else !!~diffexpr!! end as changes
478
+
479
+ -- Create and assign the entire SQL.
480
+ -- !x! sub !!#sql_var!! select !!~pkcolexpr!!, !!~changeexpr!! from !!#staging!!.!!#table!! as s left join !!#base_schema!!.!!#table!! as b on !!~joinexpr!!
481
+
482
+
483
+
484
+ -- !x! END SCRIPT COMPARE_CHANGES
485
+
486
+ -- ################### End of COMPARE_CHANGES ###################
487
+ -- ################################################################
488
+
489
+
490
+
491
+
492
+
493
+
494
+ -- ################################################################
495
+ -- Script COMPARE_CHANGED
496
+ -- ===============================================================
497
+ --
498
+ -- Generate SQL to characterize every row of the base table
499
+ -- depending on whether there is a matching row in the staging
500
+ -- table, whether a matching row has new data, or whether a
501
+ -- matching row has identical data.
502
+ --
503
+ -- The output includes a column for every primary key plus a
504
+ -- column named "changed" with one of the following tags:
505
+ -- NoNewRow : The primary key is in the base table
506
+ -- but not in the staging table.
507
+ -- Changed : At least one of the attribute values is
508
+ -- different in the staging table.
509
+ -- Unchanged : All attribute values are the same in the
510
+ -- staging and base tables.
511
+ --
512
+ -- Required input arguments:
513
+ -- base_schema : The name of the base table schema.
514
+ -- staging : The name of the staging schema.
515
+ -- table : The name of the table to compare.
516
+ -- The table must have the same name
517
+ -- in base and staging schemas.
518
+ --
519
+ -- Optional input arguments:
520
+ -- include_cols : Contains a comma-separated list of single-quoted
521
+ -- column names in the base table that are the
522
+ -- *only* attribute columns to be compared.
523
+ -- exclude_cols : Contains a comma-separated list of single-quoted
524
+ -- column names in the base table that are not to
525
+ -- be compared. If 'include_cols' is provided,
526
+ -- 'exclude_cols' is ignored.
527
+ --
528
+ -- Required output arguments:
529
+ -- sql_var : The name of the variable into which
530
+ -- the generated SQL will be stored
531
+ --
532
+ -- Notes
533
+ -- 1. The generated SQL is not terminated with a semicolon.
534
+ -- ===============================================================
535
+ -- !x! BEGIN SCRIPT COMPARE_CHANGED with parameters (base_schema, staging, table, sql_var)
536
+
537
+ -- Create a table of primary key columns for the table
538
+ if object_id('tempdb..#cmp_primary_key_columns') is not null drop table #cmp_primary_key_columns;
539
+ select k.column_name, k.ordinal_position
540
+ into #cmp_primary_key_columns
541
+ from information_schema.table_constraints as tc
542
+ inner join information_schema.key_column_usage as k
543
+ on tc.constraint_type = 'PRIMARY KEY'
544
+ and tc.constraint_name = k.constraint_name
545
+ and tc.constraint_catalog = k.constraint_catalog
546
+ and tc.constraint_schema = k.constraint_schema
547
+ and tc.table_schema = k.table_schema
548
+ and tc.table_name = k.table_name
549
+ and tc.constraint_name = k.constraint_name
550
+ where
551
+ k.table_name = '!!#table!!'
552
+ and k.table_schema = '!!#base_schema!!'
553
+ order by k.ordinal_position
554
+ ;
555
+
556
+ -- !x! if(not hasrows(#cmp_primary_key_columns)) { halt message "Table !!#table!! has no primary key columns." }
557
+
558
+ -- Populate a (temporary) table with the names of the attribute columns
559
+ -- that are to be compared.
560
+ -- Include only those columns from the staging table that are also in the base table.
561
+ -- !x! sub_empty ~col_sel
562
+ -- !x! if(sub_defined(#include_cols))
563
+ -- !x! sub ~col_sel and s.column_name in (!!#include_cols!!)
564
+ -- !x! elseif(sub_defined(#exclude_cols))
565
+ -- !x! sub ~col_sel and s.column_name not in (!!#exclude_cols!!)
566
+ -- !x! endif
567
+ if object_id('tempdb..#cmp_cols') is not null drop table #cmp_cols;
568
+ select s.column_name
569
+ into #cmp_cols
570
+ from information_schema.columns as s
571
+ inner join information_schema.columns as b on s.column_name=b.column_name
572
+ left join #cmp_primary_key_columns as pk on pk.column_name = s.column_name
573
+ where
574
+ s.table_schema = '!!#staging!!'
575
+ and s.table_name = '!!#table!!'
576
+ and b.table_schema = '!!#base_schema!!'
577
+ and b.table_name = '!!#table!!'
578
+ !!~col_sel!!
579
+ order by s.ordinal_position;
580
+
581
+ -- Create the SQL to select primary key columns from the base table.
582
+ if object_id('tempdb..#cmp_pkexpr') is not null drop table #cmp_pkexpr;
583
+ select
584
+ string_agg('b.' + column_name, ', ') as pkexpr
585
+ into
586
+ #cmp_pkexpr
587
+ from
588
+ #cmp_primary_key_columns;
589
+ -- !x! subdata ~pkcolexpr #cmp_pkexpr
590
+
591
+
592
+ -- Create the SQL for each column to compare the base (b) and staging (s) tables.
593
+ -- This generates a value of 1 when there are differences and 0 when there are not.
594
+ alter table #cmp_cols add sqlcmd varchar(max);
595
+ update #cmp_cols
596
+ set sqlcmd =
597
+ 'case when b.' + column_name + ' is null then case when s.' + column_name + ' is null then 0 else 1 end else case when s.' + column_name + ' is null then 1 else case when b.' + column_name + ' = s.' + column_name + ' then 0 else 1 end end end'
598
+ ;
599
+
600
+ -- Create the expression to determine whether there is a difference for any column.
601
+ if object_id('tempdb..#cmp_compexpr') is not null drop table #cmp_compexpr;
602
+ select
603
+ string_agg(sqlcmd, ' + ') as compexpr
604
+ into
605
+ #cmp_compexpr
606
+ from
607
+ #cmp_cols;
608
+ -- !x! subdata ~compexpr #cmp_compexpr
609
+ -- !x! sub ~diffexpr case when !!~compexpr!! = 0 then 'Unchanged' else 'Changed' end
610
+
611
+ -- Create a join expression for primary key columns of the base (b) and
612
+ -- staging (s) tables.
613
+ if object_id('tempdb..#cmp_joinexpr') is not null drop table #cmp_joinexpr;
614
+ select
615
+ string_agg('b.' + column_name + ' = s.' + column_name, ' and ') as joinexpr
616
+ into
617
+ #cmp_joinexpr
618
+ from
619
+ #cmp_primary_key_columns;
620
+ -- !x! subdata ~joinexpr #cmp_joinexpr
621
+
622
+ -- Get the name of a single primary key column to test for row existence in the
623
+ -- staging table.
624
+ -- !x! subdata pkcol1 #cmp_primary_key_columns
625
+
626
+ -- Create the SQL to display either the row tag or the comparison tag.
627
+ -- !x! sub ~changeexpr case when s.!!pkcol1!! is null then 'NoNewRow' else !!~diffexpr!! end as changed
628
+
629
+ -- Create and assign the entire SQL.
630
+ -- !x! sub !!#sql_var!! select !!~pkcolexpr!!, !!~changeexpr!! from !!#base_schema!!.!!#table!! as b left join !!#staging!!.!!#table!! as s on !!~joinexpr!!
631
+
632
+
633
+
634
+ -- !x! END SCRIPT COMPARE_CHANGED
635
+
636
+ -- ################### End of COMPARE_CHANGED ###################
637
+ -- ################################################################
638
+
639
+