1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
167.
168.
169.
170.
171.
172.
173.
174.
175.
176.
177.
178.
179.
180.
181.
182.
183.
184.
185.
186.
187.
188.
189.
190.
191.
192.
193.
194.
195.
196.
197.
198.
199.
200.
201.
202.
203.
204.
205.
206.
207.
208.
209.
210.
211.
212.
213.
214.
215.
216.
217.
218.
219.
220.
221.
222.
223.
224.
225.
226.
227.
228.
229.
230.
231.
232.
233.
234.
235.
236.
237.
238.
239.
240.
241.
242.
243.
244.
245.
246.
247.
248.
249.
250.
251.
252.
253.
254.
255.
256.
257.
258.
259.
260.
261.
262.
263.
264.
265.
266.
267.
268.
269.
270.
271.
272.
273.
274.
275.
276.
277.
278.
279.
280.
281.
282.
283.
284.
285.
286.
287.
288.
289.
290.
291.
292.
293.
294.
295.
296.
297.
298.
299.
300.
301.
302.
303.
304.
305.
306.
307.
308.
309.
310.
311.
312.
313.
314.
315.
316.
317.
318.
319.
320.
321.
322.
323.
324.
325.
326.
327.
328.
329.
330.
331.
332.
333.
334.
335.
336.
337.
338.
339.
340.
341.
342.
343.
344.
345.
346.
347.
348.
349.
350.
351.
352.
353.
354.
355.
356.
357.
358.
359.
360.
361.
362.
363.
364.
365.
366.
367.
368.
369.
370.
371.
372.
373.
374.
375.
376.
377.
378.
379.
380.
381.
382.
383.
384.
385.
386.
387.
388.
389.
390.
391.
392.
393.
394.
395.
396.
397.
398.
399.
400.
401.
402.
403.
404.
405.
406.
407.
408.
409.
410.
411.
412.
413.
414.
415.
416.
417.
418.
419.
420.
421.
422.
423.
424.
425.
426.
427.
428.
429.
430.
431.
432.
433.
434.
435.
436.
437.
438.
439.
440.
441.
442.
443.
444.
445.
446.
447.
448.
449.
450.
451.
452.
453.
454.
455.
456.
457.
458.
459.
460.
461.
462.
463.
464.
465.
466.
467.
468.
469.
470.
471.
472.
473.
474.
475.
476.
477.
478.
479.
480.
481.
482.
483.
484.
485.
486.
487.
488.
489.
490.
491.
492.
493.
494.
495.
496.
497.
498.
499.
500.
501.
502.
503.
504.
505.
506.
507.
508.
509.
510.
511.
512.
513.
514.
515.
516.
517.
518.
519.
520.
521.
522.
523.
524.
525.
526.
527.
528.
529.
530.
531.
532.
533.
534.
535.
536.
537.
538.
539.
540.
541.
542.
543.
544.
545.
546.
547.
548.
549.
550.
551.
552.
553.
554.
555.
556.
557.
558.
559.
560.
561.
562.
563.
564.
565.
566.
567.
568.
569.
570.
571.
572.
573.
574.
575.
576.
577.
578.
579.
580.
581.
582.
583.
584.
585.
586.
587.
588.
589.
590.
591.
592.
593.
594.
595.
596.
597.
598.
599.
600.
601.
602.
603.
604.
605.
606.
607.
608.
609.
610.
611.
612.
613.
614.
615.
616.
617.
618.
619.
620.
621.
622.
623.
624.
625.
626.
627.
628.
629.
630.
631.
632.
633.
634.
635.
636.
637.
638.
639.
640.
641.
642.
643.
644.
645.
646.
647.
648.
649.
650.
651.
652.
653.
654.
655.
656.
657.
658.
659.
660.
661.
662.
663.
664.
665.
666.
667.
668.
669.
670.
671.
672.
673.
674.
675.
676.
677.
678.
679.
680.
681.
682.
683.
684.
685.
686.
687.
688.
689.
690.
691.
692.
693.
694.
695.
696.
697.
698.
699.
700.
701.
702.
703.
704.
705.
706.
707.
708.
709.
710.
711.
712.
713.
714.
715.
716.
717.
718.
719.
720.
721.
722.
723.
724.
725.
726.
727.
728.
729.
730.
731.
732.
733.
734.
735.
736.
737.
738.
739.
740.
741.
742.
743.
744.
745.
746.
747.
748.
749.
750.
751.
752.
753.
754.
755.
756.
757.
758.
759.
760.
761.
762.
763.
764.
765.
766.
767.
768.
769.
770.
771.
772.
773.
774.
775.
776.
777.
778.
779.
780.
781.
782.
783.
784.
785.
786.
787.
788.
789.
790.
791.
792.
793.
794.
795.
796.
797.
798.
799.
800.
801.
802.
803.
804.
805.
806.
807.
808.
809.
810.
811.
812.
813.
814.
815.
816.
817.
818.
819.
820.
821.
822.
823.
824.
825.
826.
827.
828.
829.
830.
831.
832.
833.
834.
835.
836.
837.
838.
839.
840.
841.
842.
843.
844.
845.
846.
847.
848.
849.
850.
851.
852.
853.
854.
855.
856.
857.
858.
859.
860.
861.
862.
863.
864.
865.
866.
867.
868.
869.
870.
871.
872.
873.
874.
875.
876.
877.
878.
879.
880.
881.
882.
883.
884.
885.
886.
887.
888.
889.
890.
891.
892.
893.
894.
895.
896.
897.
898.
899.
900.
901.
902.
903.
904.
905.
906.
907.
908.
909.
910.
911.
912.
913.
914.
915.
916.
917.
918.
919.
920.
921.
922.
923.
924.
925.
926.
927.
928.
929.
930.
931.
932.
933.
934.
935.
936.
937.
938.
939.
940.
941.
942.
943.
944.
945.
946.
947.
948.
949.
950.
951.
952.
953.
954.
955.
956.
957.
958.
959.
960.
961.
962.
963.
964.
965.
966.
967.
968.
969.
970.
971.
972.
973.
974.
975.
976.
977.
978.
979.
980.
981.
982.
983.
984.
985.
986.
987.
988.
989.
990.
991.
992.
993.
994.
995.
996.
997.
998.
999.
1000.
1001.
1002.
1003.
1004.
1005.
1006.
1007.
1008.
1009.
1010.
1011.
1012.
1013.
1014.
1015.
1016.
1017.
1018.
1019.
1020.
1021.
1022.
1023.
1024.
1025.
1026.
1027.
1028.
1029.
1030.
1031.
1032.
1033.
1034.
1035.
1036.
1037.
1038.
1039.
1040.
1041.
1042.
1043.
1044.
1045.
1046.
1047.
1048.
1049.
1050.
1051.
1052.
1053.
1054.
1055.
1056.
1057.
1058.
1059.
1060.
1061.
1062.
1063.
1064.
1065.
1066.
1067.
1068.
1069.
1070.
1071.
1072.
1073.
1074.
1075.
1076.
1077.
1078.
1079.
1080.
1081.
1082.
1083.
1084.
1085.
1086.
1087.
1088.
1089.
1090.
1091.
1092.
1093.
1094.
1095.
1096.
1097.
1098.
1099.
1100.
1101.
1102.
1103.
1104.
1105.
1106.
1107.
1108.
1109.
1110.
1111.
1112.
1113.
1114.
1115.
1116.
1117.
1118.
1119.
1120.
1121.
1122.
1123.
1124.
1125.
1126.
1127.
1128.
1129.
1130.
1131.
1132.
1133.
1134.
1135.
1136.
1137.
1138.
1139.
1140.
1141.
1142.
1143.
1144.
1145.
1146.
1147.
1148.
1149.
1150.
1151.
1152.
1153.
1154.
1155.
1156.
1157.
1158.
1159.
1160.
1161.
1162.
1163.
1164.
1165.
1166.
1167.
1168.
1169.
1170.
1171.
1172.
1173.
1174.
1175.
1176.
1177.
1178.
1179.
1180.
1181.
1182.
1183.
1184.
1185.
1186.
1187.
1188.
1189.
1190.
1191.
1192.
1193.
1194.
1195.
1196.
1197.
1198.
1199.
1200.
1201.
1202.
1203.
1204.
1205.
1206.
1207.
1208.
1209.
1210.
1211.
1212.
1213.
1214.
1215.
1216.
1217.
1218.
1219.
1220.
1221.
1222.
1223.
1224.
1225.
1226.
1227.
1228.
1229.
1230.
1231.
1232.
1233.
1234.
1235.
1236.
1237.
1238.
1239.
1240.
1241.
1242.
1243.
1244.
1245.
1246.
1247.
1248.
1249.
1250.
1251.
1252.
1253.
1254.
1255.
1256.
1257.
1258.
1259.
1260.
1261.
1262.
1263.
1264.
1265.
1266.
1267.
1268.
1269.
1270.
1271.
1272.
1273.
1274.
1275.
1276.
1277.
1278.
1279.
1280.
1281.
1282.
1283.
1284.
1285.
1286.
1287.
1288.
1289.
1290.
1291.
1292.
1293.
1294.
1295.
1296.
1297.
1298.
1299.
1300.
1301.
1302.
1303.
1304.
1305.
1306.
1307.
1308.
1309.
1310.
1311.
1312.
1313.
1314.
1315.
1316.
1317.
1318.
1319.
1320.
1321.
1322.
1323.
1324.
1325.
1326.
1327.
1328.
1329.
1330.
1331.
1332.
1333.
1334.
1335.
1336.
1337.
1338.
1339.
1340.
1341.
1342.
1343.
1344.
1345.
1346.
1347.
1348.
1349.
1350.
1351.
1352.
1353.
1354.
1355.
1356.
1357.
1358.
1359.
1360.
1361.
1362.
1363.
1364.
1365.
1366.
1367.
1368.
1369.
1370.
1371.
1372.
1373.
1374.
1375.
1376.
1377.
1378.
1379.
1380.
1381.
1382.
1383.
1384.
1385.
1386.
1387.
1388.
1389.
1390.
1391.
1392.
1393.
1394.
1395.
1396.
1397.
1398.
1399.
1400.
1401.
1402.
1403.
1404.
1405.
1406.
1407.
1408.
1409.
1410.
1411.
1412.
1413.
1414.
1415.
1416.
1417.
1418.
1419.
1420.
1421.
1422.
1423.
1424.
1425.
1426.
1427.
1428.
1429.
1430.
1431.
1432.
1433.
1434.
1435.
1436.
1437.
1438.
1439.
1440.
1441.
1442.
1443.
1444.
1445.
1446.
1447.
1448.
1449.
1450.
1451.
1452.
1453.
1454.
1455.
1456.
1457.
1458.
1459.
1460.
1461.
1462.
1463.
1464.
1465.
1466.
1467.
1468.
1469.
1470.
1471.
1472.
1473.
1474.
1475.
1476.
1477.
1478.
1479.
1480.
1481.
1482.
1483.
1484.
1485.
1486.
1487.
1488.
1489.
1490.
1491.
1492.
1493.
1494.
1495.
1496.
1497.
1498.
1499.
1500.
1501.
1502.
1503.
1504.
1505.
1506.
1507.
1508.
1509.
1510.
1511.
1512.
1513.
1514.
1515.
1516.
1517.
1518.
1519.
1520.
1521.
1522.
1523.
1524.
1525.
1526.
1527.
1528.
1529.
1530.
1531.
1532.
1533.
1534.
1535.
1536.
1537.
1538.
1539.
1540.
1541.
1542.
1543.
1544.
1545.
1546.
1547.
1548.
1549.
1550.
1551.
1552.
1553.
1554.
1555.
1556.
1557.
1558.
1559.
1560.
1561.
1562.
1563.
1564.
1565.
1566.
1567.
1568.
1569.
1570.
1571.
1572.
1573.
1574.
1575.
1576.
1577.
1578.
1579.
1580.
1581.
1582.
1583.
1584.
1585.
1586.
1587.
1588.
1589.
1590.
1591.
1592.
1593.
1594.
1595.
1596.
1597.
1598.
1599.
1600.
1601.
1602.
1603.
1604.
1605.
1606.
1607.
1608.
1609.
1610.
1611.
1612.
1613.
1614.
1615.
1616.
1617.
1618.
1619.
1620.
1621.
1622.
1623.
1624.
1625.
1626.
1627.
1628.
1629.
1630.
1631.
1632.
1633.
1634.
1635.
1636.
1637.
1638.
1639.
1640.
1641.
1642.
1643.
1644.
1645.
1646.
1647.
1648.
1649.
1650.
1651.
1652.
1653.
1654.
1655.
1656.
1657.
1658.
1659.
1660.
1661.
1662.
1663.
1664.
1665.
1666.
1667.
1668.
1669.
1670.
1671.
1672.
1673.
1674.
1675.
1676.
1677.
1678.
1679.
1680.
1681.
1682.
1683.
1684.
1685.
1686.
1687.
1688.
1689.
1690.
1691.
1692.
1693.
1694.
1695.
1696.
1697.
1698.
1699.
1700.
1701.
1702.
1703.
1704.
1705.
1706.
1707.
1708.
1709.
1710.
1711.
1712.
1713.
1714.
1715.
1716.
1717.
1718.
1719.
1720.
1721.
1722.
1723.
1724.
1725.
1726.
1727.
1728.
1729.
1730.
1731.
1732.
1733.
1734.
1735.
1736.
1737.
1738.
1739.
1740.
1741.
1742.
1743.
1744.
1745.
1746.
1747.
1748.
1749.
1750.
1751.
1752.
1753.
1754.
1755.
1756.
1757.
1758.
1759.
1760.
1761.
1762.
1763.
1764.
1765.
1766.
1767.
1768.
1769.
1770.
1771.
1772.
1773.
1774.
1775.
1776.
1777.
1778.
1779.
1780.
CREATE PROCEDURE [sp_depersonalization]
as
begin
/*----------------------------------------------------------------------
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[sp_depersonalization]') AND type in (N'P', N'PC')) DROP PROCEDURE [dbo].[sp_depersonalization]
GO
--
-- Процедура : dbo.sp_depersonalization
--
-- Аргументы : нет
--
-- Описание : Формирует список (таблица + поле + персональные данные Replace на другие персональные данные) для их обезличивания. Разрабатывалось для Microsoft SQL Server 2014
--
-- Используется : для ручного запуска
--
-- Возвращает : список UPDATE(ов) для формироваться подмены данных по всей базе (в разумных пределах иначе процедура будет работать очень долго)
--
-- История : 07.07.2021 - Андрей Львович Антонов, создал
--
-- Пример вызова: можно запускать несколько экземпляров процедуры для более быстрой проработки данных
-- EXEC dbo.sp_depersonalization
-- в данной примере данные берутся из таблицы t_user
-- из трех полей
-- t_user.s_U_FamilyName
-- t_user.s_U_FirstName
-- t_user.s_U_LastName
-- эти поля являются Ф.И.О, которые будут перемешаны. Но по логике лучше обрабатывать отдельно сначала Фамилии потом Имена и отдельно Отчества
Анализ (промежуточных) результатов:
select top 100 * from w_getdate (nolock) order by date_time desc /* трассировка по времени */
select top 100 * from w_getdate (nolock) where num > 1 order by sec desc /* максимальное временя */
select Count (*) from w_depersonalization_table_8 (nolock) /* сколько найдено таблица + поле которые имеют персональные данные */
select Count (*) from w_depersonalization_pole_1 (nolock) /* сколько всего проверено запросов */
select Count (*) from w_depersonalization_pole_2 (nolock) /* проверено */
select Count (*) from w_depersonalization_pole_3 (nolock) /* проверено */
select Count (*) from w_depersonalization_table_12 (nolock) /* нужно проверить */
select * from w_depersonalization_table_12 where pole_5 not in (select pole_5 from w_depersonalization_table_12 where occupied > 2 )
select pole_1, Count (*) from w_depersonalization_pole_3 (nolock) GROUP BY pole_1 HAVING Count (pole_1) > 1 /* проверка на наличие запросов которые попали дважды (должно быть пусто) */
select pole_1, Count (*) from w_depersonalization_pole_1 (nolock) GROUP BY pole_1 HAVING Count (pole_1) > 1 /* проверка на наличие запросов которые попали дважды (должно быть пусто) */
select object_name(id) table_name, rows from sysindexes (nolock) where indid in (0,1) and rows > 100000000 /* таблицы где записей более 100 миллионов */
/* статистика обработки записей по часам для второго этапа */
select top 1000 datediff(dd, '19000101', diff) [Дни], datepart(hh, diff) [Часы], Count (*) [Обработано] from (select (SELECT Max (date_time) FROM w_getdate (nolock) where num = 28) - date_time as diff from w_getdate (nolock) where num = 28) r group by datediff(dd, '19000101', diff), datepart(hh, diff) order by [Дни] asc, [Часы] asc
/* статистика обработки записей по минутам для второго этапа */
select datediff(dd, '19000101', diff) [Дни], datepart(hh, diff) [Часы], datepart(mi, diff) [Минуты], Count (*) [Обработано] from (select (SELECT Max (date_time) FROM w_getdate (nolock) where num = 28) - date_time diff from w_getdate (nolock) where num = 28) r group by datediff(dd, '19000101', diff), datepart(hh, diff), datepart(mi, diff) order by [Дни] desc, [Часы] desc, [Минуты] desc
/* статистика обработки записей по дням */
select datediff(dd, '19000101', diff) [Дни], Count (*) [Обработано] from (select (SELECT Max (date_time) FROM w_getdate (nolock) where num = 28) - date_time diff from w_getdate (nolock) where num = 28) r group by datediff(dd, '19000101', diff) order by [Дни] desc
/* поиск по всем процедурам */
select distinct so.xtype, so.name from syscomments sc (nolock) inner join sysobjects so (nolock) on sc.id = so.id where sc.text like '%текст для поиска%' order by so.xtype, so.name
/* Заполненность tempdb */
select convert(numeric(10,2),round(sum(data_pages)*8/1024.,2)) as user_object_reserved_MB
from tempdb.sys.allocation_units a
inner join tempdb.sys.partitions b on a.container_id = b.partition_id
inner join tempdb.sys.objects c on b.object_id = c.object_id
go
-------------------------------------------------------------------------*/
declare @pole_1 nvarchar (4000) /* Поиск полей для обезличивания */
declare @pole_2 nvarchar (1000) /* Создание индекса */
declare @pole_3 nvarchar (1000) /* Удаление индекса */
declare @pole_4 nvarchar (100) /* "таблица + поле" - идентификатор индекса */
declare @pole_5 nvarchar (100) /* "таблица + поле + имя" - идентификатор запроса */
declare @pole_6 nvarchar (100) /* поисковое слово по слогам длиной - @int_num */
declare @pole_11 nvarchar (4000)
declare @pole_22 nvarchar (1000)
declare @pole_33 nvarchar (1000)
declare @pole_44 nvarchar (100)
declare @pole_55 nvarchar (100)
declare @exec_pole nvarchar (4000)
declare @DATA_TYPE varchar (255)
declare @CHARACTER_MAXIMUM_LENGTH int
declare @occupied_01 int
declare @occupied_02 int = 2
declare @id_identity int
declare @id_identity_old int
declare @row_count int
declare @occupied_10 int
declare @occupied_11 int
declare @occupied_12 int
declare @occupied_13 int
declare @occupied_14 int
declare @occupied_15 int
declare @occupied_16 int
declare @row_table_13 int
declare @RowCount_table_10 int
declare @RowCount_table_13 int
declare @user_name varchar(50) /* select @user_name = user_name() */
select @user_name = user_name()
-- if user_name() = @user_name DELETE FROM w_getdate
if object_id('w_getdate', 'u') is null
BEGIN
/* это стационарная таблица в которой накапливаются поля и значения которые были обработаны для varchar полей */
CREATE TABLE w_getdate
(
num int NULL,
spid int NULL,
date_time datetime NULL,
sec int NULL,
descr varchar (255) NULL
)
CREATE INDEX isx_w_getdate_date_time_spid ON w_getdate (date_time, spid)
END
if user_name() = @user_name INSERT INTO w_getdate ( num, spid, date_time, sec, descr) SELECT 1, @@spid, GetDate (), IsNull(DATEDIFF(ms, Max (date_time), GetDate ()), 0), 'запуск процедуры' FROM w_getdate with (nolock, index(isx_w_getdate_date_time_spid)) WHERE spid = @@spid
/* скрипт расставляет приоритеты поиска для каждого слова поделив по три символа */
declare @int_num int
/* ищем таблицы где есть персональные данные при минимальном количестве запросов */
/*************************************************************************************************************************************************/
set @int_num = 4 -- Переменная отвечающая насколько символов в слоге делить Ф.И.О. пользователей, чтобы сократить число запросов, где нужно искать персональные данные.
-- Можно сделать по 2 -(57 / 303 183), можно по 3 - (276 / 1 468 044), можно по 4 - (575 / 3 058 425), можно по 5 - (841 / 4 473 279), можно по 6- (880/4 680 720),
-- из 1722 персональных имени на нашей базе которые создадут 9 159 318 запросов только по varchar полям, а еще есть XML которые работают еще медленнее.
-- Это дает возможность найти таблицы, где есть персональные данные, но при УМЕНЬШЕНИЕ цифры @int_num чаще попадают таблицы в которых нет персональных данных и так как
-- это случайные совпадения, это увеличивает время конечного поиска по всем найденным ТАБЛИЦАМ умножены ПОЛЯ умножены 1722 уникальных имени, которые будет делаться позже.
/**********************************************************************************************************************************************************/
if object_id('tempdb..#table_01', N'U') is not null drop table #table_01
if object_id('tempdb..#table_02', N'U') is not null drop table #table_02
if object_id('tempdb..#table_name_1', N'U') is NOT null drop table #table_name_1
if object_id('tempdb..#table_11',N'u') is not null drop table #table_11
if object_id('tempdb..#table_12',N'u') is not null drop table #table_12
if object_id('tempdb..#table_pre_12',N'u') is not null drop table #table_pre_12
if object_id('tempdb..#table_pre_13',N'u') is not null drop table #table_pre_13
if object_id('tempdb..#table_pre_14',N'u') is not null drop table #table_pre_14
if object_id('tempdb..#table_pre_15',N'u') is not null drop table #table_pre_15
if object_id('tempdb..#table_03_VAR',N'u') is not null drop table #table_03_VAR
-- if object_id('tempdb..##table_10',N'u') is not null drop table ##table_10
/* таблица для создания списка фамилий, имен, отчеств */
create table #table_01 ( id_identity int identity, name_1 VARCHAR(128) primary key, name_2 VARCHAR(128) NULL)
/* таблица для создания подменяемого списка клиентов */
create table #table_02 ( id_identity int identity, name_1 VARCHAR(128) NULL, name_2 VARCHAR(128) NULL)
/* список всех таблиц базы и их размер */
create table #table_name_1 ( id_identity int identity, table_name VARCHAR(128) primary key, rows_1 int null, rows_2 int null)
create table #table_pre_12 ( name_1 varchar (10) null, row_1 int null )
create table #table_pre_13 ( name_1 varchar (10) null )
/* таблица для всех VARCHAR полей базы данных */
create table #table_03_VAR
(
id_identity int identity,
TABLE_SCHEMA varchar (255) NULL,
table_name varchar (255) NULL,
COLUMN_NAME varchar (255) NULL,
DATA_TYPE varchar (255) NULL,
CHARACTER_MAXIMUM_LENGTH int NULL
)
/* таблица куда собираются все используемые сочетания Ф.И.О. по 3 или 4 символа в зависимости от @int_num переменной. */
/* name_2 только ПЕРВОЕ ИМЯ!!! Таких (похожих) имен может быть много. */
create table #table_pre_15
(
name_1 varchar (10) null,
name_2 varchar (128) null
)
/* таблица для создания весов слогов по три четыре или пять символов */
create table #table_pre_14 (
id_identity int identity,
pole_name VARCHAR(128) primary key,
row_1 int null ,
name_1 varchar (10) null,
n_01 varchar (10) null,
n_02 varchar (10) null,
n_03 varchar (10) null,
n_04 varchar (10) null,
n_05 varchar (10) null,
n_06 varchar (10) null,
n_07 varchar (10) null,
n_08 varchar (10) null,
n_09 varchar (10) null,
n_10 varchar (10) null,
n_11 varchar (10) null,
n_12 varchar (10) null,
n_13 varchar (10) null,
n_14 varchar (10) null,
n_15 varchar (10) null,
n_16 varchar (10) null,
n_17 varchar (10) null,
n_18 varchar (10) null,
n_19 varchar (10) null,
n_20 varchar (10) null
)
create table #table_12
(
id_identity int identity,
TABLE_SCHEMA varchar (255) NULL,
table_name varchar (255) NULL,
COLUMN_NAME varchar (255) NULL,
name_1 varchar (255) NULL,
name_2 varchar (255) NULL,
DATA_TYPE varchar (255) NULL,
CHARACTER_MAXIMUM_LENGTH int NULL,
pole_5 nvarchar (100) NULL /* "таблица + поле + имя" - идентификатор запроса */
)
if object_id('tempdb..##table_8',N'u') is null
BEGIN
create table ##table_8
(
id_identity int identity,
TABLE_SCHEMA varchar (255) NULL,
table_name varchar (255) NULL,
COLUMN_NAME varchar (255) NULL,
name_1 varchar (255) NULL,
name_2 varchar (255) NULL,
DATA_TYPE varchar (255) NULL,
DATA_SIZE varchar (255) NULL,
pole_5 nvarchar (100) NULL /* "таблица + поле + имя" - идентификатор запроса */
)
END
if object_id('tempdb..##table_10',N'u') is null
BEGIN
create table ##table_10
(
id_identity int identity,
TABLE_SCHEMA varchar (255) NULL,
table_name varchar (255) NULL,
COLUMN_NAME varchar (255) NULL,
name_1 varchar (255) NULL,
name_2 varchar (255) NULL,
DATA_TYPE varchar (255) NULL,
DATA_SIZE varchar (255) NULL,
pole_5 nvarchar (100) NULL /* "таблица + поле + имя" - идентификатор запроса */
)
END
if object_id('w_depersonalization_pole_1', 'u') is null
BEGIN
/* это стационарная таблица в которой накапливаются 'таблицы + поля + значения' которые были обработаны на 2-м этапе */
CREATE TABLE w_depersonalization_pole_1
(
id_identity int identity,
pole_1 nvarchar (4000) NULL,
DATA_TYPE varchar (255) NULL,
CHARACTER_MAXIMUM_LENGTH int NULL
)
END
if object_id('w_depersonalization_pole_3', 'u') is null
BEGIN
/* это стационарная таблица в которой накапливаются 'таблицы + поля + значения' которые были обработаны на 1-м этапе */
CREATE TABLE w_depersonalization_pole_3
(
id_identity int identity,
pole_1 nvarchar (100) NULL,
pole_6 varchar (10) NULL, /* поисковое слово по слогам длиной - @int_num */
DATA_TYPE varchar (255) NULL,
CHARACTER_MAXIMUM_LENGTH int NULL
)
CREATE INDEX isx_w_depersonalization_pole_3_pole_1 ON w_depersonalization_pole_3 (pole_1)
END
if object_id('w_depersonalization_table_8', 'u') is null
BEGIN
/* это стационарная таблица в которой накапливаются 'таблицы + поля + значения' КОТОРЫЕ НУЖНО ОБЕЗЛИЧИТЬ */
CREATE TABLE w_depersonalization_table_8
(
id_identity int NULL,
TABLE_SCHEMA varchar (255) NULL,
table_name varchar (255) NULL,
COLUMN_NAME varchar (255) NULL,
name_1 varchar (255) NULL,
name_2 varchar (255) NULL,
DATA_TYPE varchar (255) NULL,
DATA_SIZE varchar (255) NULL,
pole_5 nvarchar (100) NULL /* "таблица + поле + имя" - идентификатор запроса */
)
END
if object_id('w_depersonalization_table_9', 'u') is null
BEGIN
/* это стационарная таблица в которой накапливаются 'таблицы + поля + значения' КОТОРЫЕ НУЖНО ОБЕЗЛИЧИТЬ */
CREATE TABLE w_depersonalization_table_9
(
id_identity int NULL,
TABLE_SCHEMA varchar (255) NULL,
table_name varchar (255) NULL,
COLUMN_NAME varchar (255) NULL,
name_1 varchar (255) NULL,
name_2 varchar (255) NULL,
DATA_TYPE varchar (255) NULL,
DATA_SIZE varchar (255) NULL
)
END
if object_id('w_depersonalization_table_10', 'u') is null
BEGIN
/* это стационарная таблица в которой накапливаются 'таблицы + поля + значения' КОТОРЫЕ НУЖНО ОБЕЗЛИЧИТЬ */
CREATE TABLE w_depersonalization_table_10
(
id_identity int identity,
pole_1 nvarchar (4000) null,
pole_5 nvarchar (100) NULL, /* "таблица + поле + имя" - идентификатор запроса */
occupied int null /* 1 - если занята другой процедурой или 2- запись уже отработана */
)
END
if object_id('w_depersonalization_table_12', 'u') is null
BEGIN
/* таблица сбора всех данных по всем таблицам полям и подменяемым данным */
create table w_depersonalization_table_12
(
id_identity int identity,
pole_1 nvarchar (4000) null, /* Поиск полей для обезличивания */
pole_2 nvarchar (1000) null, /* Создание индекса */
pole_3 nvarchar (1000) null, /* Удаление индекса */
pole_4 nvarchar (100) null, /* "таблица + поле" - идентификатор индекса */
pole_5 nvarchar (100) null, /* "таблица + поле + имя" - идентификатор запроса */
pole_6 nvarchar (100) null, /* поисковое слово по слогам длиной - @int_num */
DATA_TYPE varchar (255) null, /* тип данных */
CHARACTER_MAXIMUM_LENGTH int null, /* размер поля */
occupied int null /* 1 - если занята другой процедурой или 2- запись уже отработана */
)
CREATE INDEX isx_w_depersonalization_table_12_occupied ON w_depersonalization_table_12 (pole_5, occupied)
END
if object_id('w_depersonalization_table_13', 'u') is null
BEGIN
/* таблица сбора всех данных по всем таблицам полям и подменяемым данным INSERT INTO ##table_8 ( TABLE_SCHEMA, table_name, COLUMN_NAME, name_1, name_2, DATA_TYPE, DATA_SIZE, pole_5) т */
create table w_depersonalization_table_13
(
id_identity int identity,
pole_1 nvarchar (4000) null, /* Поиск полей для обезличивания */
pole_2 nvarchar (1000) null, /* Создание индекса */
pole_3 nvarchar (1000) null, /* Удаление индекса */
pole_4 nvarchar (100) null, /* "таблица + поле" - идентификатор индекса */
pole_5 nvarchar (100) null, /* "таблица + поле + имя" - идентификатор запроса */
pole_6 nvarchar (100) null, /* поисковое слово по слогам длиной - @int_num */
DATA_TYPE varchar (255) null, /* тип данных */
CHARACTER_MAXIMUM_LENGTH int null, /* размер поля */
occupied int null /* 1 - если занята другой процедурой или 2- запись уже отработана */
)
CREATE INDEX isx_w_depersonalization_table_13_occupied ON w_depersonalization_table_13 (pole_5, occupied)
END
/*****************************************************************************************************************************************************************************************************************************/
/* в этой таблице лежат конечные UPDATE базы данных для обезличивания, если они есть, то создавать их ненужно, но обрабатываться будут только записи w_depersonalization_table_10.occupied = 0 остальные считаются в работе */
/*****************************************************************************************************************************************************************************************************************************/
SELECT @RowCount_table_10 = Count (*) FROM w_depersonalization_table_10 /* (TABLOCK)*/ (NOLOCK)
/* если конечных UPDATE(ов) нет, то создаем их */
IF @RowCount_table_10 = 0
BEGIN
/**********************************/
/* НАЧАЛО транзакции по TABLOCKX */
BEGIN TRAN a1
/*************************************/
/* Получаем количество записей которые можно обработать */
-- SELECT Count (*) FROM w_depersonalization_table_12 (NOLOCK)
-- SELECT top 100 * FROM w_depersonalization_table_12 (NOLOCK)
/* Блокируем таблицу до конца транзакции */
SELECT @occupied_12 = Count (*) FROM w_depersonalization_table_12 (TABLOCKX) /*WHERE occupied < 2*/ /* (NOLOCK)*/
-- SELECT Count (*) FROM w_depersonalization_table_12 WHERE occupied < 2 /* в работе */
-- SELECT * FROM w_depersonalization_table_12 WHERE occupied < 2 /* в работе */
/* проверка на начало второго этапа в этой таблице лежат INSERT INTO ##table_8 ( TABLE_SCHEMA, table_name, COLUMN_NAME, name_1, name_2, DATA_TYPE, DATA_SIZE, pole_5) */
SELECT @occupied_15 = Count (*) FROM w_depersonalization_table_13 /*(TABLOCKX)*/ (NOLOCK)
/* проверка на начало второго этапа */
IF @occupied_15 > 0
BEGIN
/* начался второй этап обработки, поэтому первый этап пропускаем */
SET @occupied_12 = -1
END
/* Проверка на наличие рабочих записей */
IF @occupied_12 = 0 /* блок BEGIN END работает если все записи обработаны */
BEGIN
-- if user_name() = @user_name DELETE FROM w_getdate with (nolock, index(isx_w_getdate_date_time_spid)) WHERE spid = @@spid
if user_name() = @user_name INSERT INTO w_getdate ( num, spid, date_time,sec, descr) SELECT 2, @@spid, GetDate (), IsNull (DATEDIFF(ms, Max (date_time), GetDate ()), 0), 'время начала работы первой процедуры' FROM w_getdate with (nolock, index(isx_w_getdate_date_time_spid)) WHERE spid = @@spid
/* удаляем не обработанные записи */
DELETE FROM w_depersonalization_table_12 /* первый этап */
DELETE FROM w_depersonalization_table_13 /* второй этап */
/* обработано раньше */
select @row_count = Count (*) from w_depersonalization_pole_3
if user_name() = @user_name INSERT INTO w_getdate ( num, spid, date_time,sec, descr) SELECT 3, @@spid, GetDate (), DATEDIFF(ms, Max (date_time), GetDate ()), Convert (varchar, @row_count) + ' - обработано записей раньше' FROM w_getdate with (nolock, index(isx_w_getdate_date_time_spid)) WHERE spid = @@spid
/* список всех Ф.И.О. для получения слогов длинной @int_num для предварительного сбора статистики - (в каких таблицах есть персональные данные) */
/* insert into #table_pre_14 (pole_name)
select distinct /* Фамилии */ s_U_FamilyName from t_user tu (nolock) where IIF (Rtrim (s_U_FamilyName) = '''', NULL, s_U_FamilyName) IS NOT NULL and Len (s_U_FamilyName)> 1 and ASCII (tu.s_U_FamilyName) > 191 and charindex (' ', s_U_FamilyName ) = 0 and Len (s_U_FamilyName) > 1
union select distinct /* Имена */ s_U_FirstName from t_user tu (nolock) where IIF (Rtrim (s_U_FirstName) = '''', NULL, s_U_FirstName) IS NOT NULL and Len (s_U_FirstName) > 1 and ASCII (tu.s_U_FirstName) > 191 and charindex (' ', s_U_FirstName ) = 0 and Len (s_U_FirstName) > 1
union select distinct /* Отчества */ s_U_LastName from t_user tu (nolock) where IIF (Rtrim (s_U_LastName) = '''', NULL, s_U_LastName) IS NOT NULL and Len (s_U_LastName) > 1 and ASCII (tu.s_U_LastName) > 191 and charindex (' ', s_U_LastName ) = 0 and Len (s_U_LastName) > 1
*/
--select from #table_pre_14 where charindex (' ', pole_name ) > 0
SELECT @row_count = count (*) FROM #table_pre_14
if user_name() = @user_name INSERT INTO w_getdate ( num, spid, date_time,sec, descr) SELECT 4, @@spid, GetDate (), DATEDIFF(ms, Max (date_time), GetDate ()), Convert (varchar, @row_count) + ' - список всех Ф.И.О.' FROM w_getdate with (nolock, index(isx_w_getdate_date_time_spid)) WHERE spid = @@spid
/* получаем список всех таблиц базы данных и количество записей в каждой */
insert into #table_name_1 (table_name, rows_1, rows_2) select object_name(id) table_name, rows, 0 from sysindexes where indid in (0,1) /*and rows > 100000000*/ order by table_name desc /* таблицы где записей более 100 миллионов */
/* получаем список всех таблиц и их полей в которых гипотетически могут встречаться Фамилия, Имя, Отчество */
insert into #table_03_VAR
(
TABLE_SCHEMA,
table_name,
COLUMN_NAME,
DATA_TYPE,
CHARACTER_MAXIMUM_LENGTH
)
select
it.TABLE_SCHEMA,
it.table_name,
ic.COLUMN_NAME,
ic.DATA_TYPE,
ic.CHARACTER_MAXIMUM_LENGTH
from
INFORMATION_SCHEMA.COLUMNS ic,
INFORMATION_SCHEMA.TABLES it,
#table_name_1 tn /* убираем таблицы где нет записей */
where
tn.rows_1 > 0 and /* убираем таблицы где нет записей */
tn.TABLE_NAME = it.TABLE_NAME and
ic.TABLE_NAME = it.TABLE_NAME and
ic.CHARACTER_MAXIMUM_LENGTH IS NOT NULL and
it.TABLE_TYPE = 'BASE TABLE' and /* только таблицы иначе попадут VIEW */
tn.table_name not like 'w_depersonalization%' and /* убираем из поиска служебные таблицы этой процедуры */
tn.table_name not like 'w_getdate%' /* убираем из поиска служебные таблицы этой процедуры */
order by
it.table_name,
ic.DATA_TYPE
SELECT @row_count = count (*) FROM #table_03_VAR
if user_name() = @user_name INSERT INTO w_getdate ( num, spid, date_time,sec, descr) SELECT 5, @@spid, GetDate (), DATEDIFF(ms, Max (date_time), GetDate ()), Convert (varchar, @row_count) + ' - список всех таблиц и их полей' FROM w_getdate with (nolock, index(isx_w_getdate_date_time_spid)) WHERE spid = @@spid
/* разбиваем Ф.И.О. по слогам */
UPDATE #table_pre_14
SET n_01 = SUBSTRING (pole_name, 1 , @int_num ),
n_02 = SUBSTRING (pole_name, 2 , @int_num ),
n_03 = SUBSTRING (pole_name, 3 , @int_num ),
n_04 = SUBSTRING (pole_name, 4 , @int_num ),
n_05 = SUBSTRING (pole_name, 5 , @int_num ),
n_06 = SUBSTRING (pole_name, 6 , @int_num ),
n_07 = SUBSTRING (pole_name, 7 , @int_num ),
n_08 = SUBSTRING (pole_name, 8 , @int_num ),
n_09 = SUBSTRING (pole_name, 9 , @int_num ),
n_10 = SUBSTRING (pole_name, 10 , @int_num ),
n_11 = SUBSTRING (pole_name, 11 , @int_num ),
n_12 = SUBSTRING (pole_name, 12 , @int_num ),
n_13 = SUBSTRING (pole_name, 13 , @int_num ),
n_14 = SUBSTRING (pole_name, 14 , @int_num ),
n_15 = SUBSTRING (pole_name, 15 , @int_num ),
n_16 = SUBSTRING (pole_name, 16 , @int_num ),
n_17 = SUBSTRING (pole_name, 17 , @int_num ),
n_18 = SUBSTRING (pole_name, 18 , @int_num ),
n_19 = SUBSTRING (pole_name, 19 , @int_num ),
n_20 = SUBSTRING (pole_name, 20 , @int_num )
/* складываем все слога в одну колонку */
insert #table_pre_13 (name_1) select n_01 from #table_pre_14 where len (n_01) = @int_num
insert #table_pre_13 (name_1) select n_02 from #table_pre_14 where len (n_02) = @int_num
insert #table_pre_13 (name_1) select n_03 from #table_pre_14 where len (n_03) = @int_num
insert #table_pre_13 (name_1) select n_04 from #table_pre_14 where len (n_04) = @int_num
insert #table_pre_13 (name_1) select n_05 from #table_pre_14 where len (n_05) = @int_num
insert #table_pre_13 (name_1) select n_06 from #table_pre_14 where len (n_06) = @int_num
insert #table_pre_13 (name_1) select n_07 from #table_pre_14 where len (n_07) = @int_num
insert #table_pre_13 (name_1) select n_08 from #table_pre_14 where len (n_08) = @int_num
insert #table_pre_13 (name_1) select n_09 from #table_pre_14 where len (n_09) = @int_num
insert #table_pre_13 (name_1) select n_10 from #table_pre_14 where len (n_10) = @int_num
insert #table_pre_13 (name_1) select n_11 from #table_pre_14 where len (n_11) = @int_num
insert #table_pre_13 (name_1) select n_12 from #table_pre_14 where len (n_12) = @int_num
insert #table_pre_13 (name_1) select n_13 from #table_pre_14 where len (n_13) = @int_num
insert #table_pre_13 (name_1) select n_14 from #table_pre_14 where len (n_14) = @int_num
insert #table_pre_13 (name_1) select n_15 from #table_pre_14 where len (n_15) = @int_num
insert #table_pre_13 (name_1) select n_16 from #table_pre_14 where len (n_16) = @int_num
insert #table_pre_13 (name_1) select n_17 from #table_pre_14 where len (n_17) = @int_num
insert #table_pre_13 (name_1) select n_18 from #table_pre_14 where len (n_18) = @int_num
insert #table_pre_13 (name_1) select n_19 from #table_pre_14 where len (n_19) = @int_num
insert #table_pre_13 (name_1) select n_20 from #table_pre_14 where len (n_20) = @int_num
/* Группируем слога, чтобы получить вес каждого слога */
insert into #table_pre_12 (name_1, row_1)
select name_1, count (*) from #table_pre_13 group by name_1 order by 2 desc
/* Прописываем лучший вес каждому Ф.И.О */
UPDATE
#table_pre_14
SET
name_1 = t2.name_1
FROM
#table_pre_12 t2
WHERE
charindex (t2.name_1, #table_pre_14.pole_name ) > 0 and
#table_pre_14.name_1 IS NULL
/* Проставляем значение веса */
UPDATE
#table_pre_14
SET
row_1 = t2.row_1
FROM
#table_pre_12 t2
WHERE
#table_pre_14.name_1 = t2.name_1
/* получаем список уникальные слов по три чиетыре или пять символов в зависимости от переменной @int_num */
insert into #table_pre_15 (name_1)
select distinct name_1 from #table_pre_14 where name_1 is not null
/* это наглядно видно здесь */
--select top 10 * from #table_pre_14
--select top 10 * from #table_pre_15
/* Для просты работы со слогами проставляем полные их имя, но это только ПЕРВОЕ имя которое включает этот слог, их должно быть много! */
UPDATE
#table_pre_15
SET
name_2 = p_14.pole_name
FROM
#table_pre_14 p_14
WHERE
p_14.name_1 = #table_pre_15.name_1
/* количество слогов из Ф.И.О. */
select @row_count = Count (*) from #table_pre_15
if user_name() = @user_name INSERT INTO w_getdate ( num, spid, date_time,sec, descr) SELECT 6, @@spid, GetDate (), DATEDIFF(ms, Max (date_time), GetDate ()), Convert (varchar, @row_count) + ' количество слогов из Ф.И.О.' FROM w_getdate with (nolock, index(isx_w_getdate_date_time_spid)) WHERE spid = @@spid
/* создаем скрипт поиска персональных данных ПО СЛОГАМ - (так как основное время уходи на поиск в тех таблицах, где совсем нет персональных данных, а ПО СЛОГАМ время сокращается в несколько раз) */
/* в транзакции отрабатывает за 20.4343 секунд */
INSERT INTO w_depersonalization_table_12
(
pole_1, /* 1 Поиск полей с кириллицей */
pole_2, /* 2 Создание индекса */
pole_3, /* 3 резерв */
pole_4, /* 4 "таблица + поле" - идентификатор индекса */
pole_5, /* 5 "таблица + поле + имя" - идентификатор запроса */
pole_6, /* 6 поисковое слово по слогам длиной - @int_num */
DATA_TYPE, /* 7 тип данных */
CHARACTER_MAXIMUM_LENGTH, /* 8 размер поля */
occupied /* 9 1 - если занята другой процедурой или 2 - запись уже отработана */
)
SELECT
/* 1 Поиск полей с кириллицей [а-я] VARCHAR */
'INSERT INTO ##table_10 ( TABLE_SCHEMA, table_name, COLUMN_NAME, DATA_TYPE, DATA_SIZE, pole_5)
SELECT DISTINCT ''' +
t3.TABLE_SCHEMA + ''', ''' +
t3.table_name + ''', ''' +
t3.COLUMN_NAME + ''', ''' +
t3.DATA_TYPE + ''', ''' +
Convert (varchar (100), t3.CHARACTER_MAXIMUM_LENGTH) + ''', ''' +
t3.TABLE_SCHEMA + '.'+ t3.table_name + '.' + t3.COLUMN_NAME + '.' + p5.name_2 + /* прописываем Ф.И.О. */ '''
FROM ' + t3.TABLE_SCHEMA + '.' + t3.table_name + ' ( nolock )
WHERE ' + 'PATINDEX(''%[а-я]%'', ' + t3.COLUMN_NAME + ' ) > 0 and ' + t3.COLUMN_NAME + ' IS NOT NULL' as pole_1 /* ищем кириллицу */
,
/* 2 Поиск полей ПО СЛОГАМ длиной - @int_num */
'INSERT INTO ##table_10 ( TABLE_SCHEMA, table_name, COLUMN_NAME, DATA_TYPE, DATA_SIZE, pole_5)
SELECT DISTINCT ''' +
t3.TABLE_SCHEMA + ''', ''' +
t3.table_name + ''', ''' +
t3.COLUMN_NAME + ''', ''' +
t3.DATA_TYPE + ''', ''' +
Convert (varchar (100), t3.CHARACTER_MAXIMUM_LENGTH) + ''', ''' +
t3.TABLE_SCHEMA + '.'+ t3.table_name + '.' + t3.COLUMN_NAME + '.' + p5.name_2 + /* прописываем Ф.И.О. */ '''
FROM ' + t3.TABLE_SCHEMA + '.' + t3.table_name + ' ( nolock )
WHERE ' + 'PATINDEX(''%' + p5.name_1 + '%'', ' + t3.COLUMN_NAME + ' ) > 0 and ' + t3.COLUMN_NAME + ' IS NOT NULL' as pole_1 /* ищем слог */
,
/* 3 резерв */
'if INDEXPROPERTY (object_id (''' + t3.TABLE_SCHEMA + '.'+ t3.table_name + '''), ''ids_'+ t3.table_name + '_' + t3.COLUMN_NAME + ''', ''IndexID'') > 0 DROP INDEX ids_' + t3.table_name + '_' + t3.COLUMN_NAME + ' ON ' + t3.TABLE_SCHEMA + '.' + t3.table_name
,
/* 4 "таблица + поле" - идентификатор индекса */
t3.TABLE_SCHEMA + '.'+ t3.table_name + '.' + t3.COLUMN_NAME, /* 4 "таблица + поле" - идентификатор индекса */
t3.TABLE_SCHEMA + '.'+ t3.table_name + '.' + t3.COLUMN_NAME + '.' + p5.name_2, /* 5 "таблица + поле + имя" как идентификатор поля */
p5.name_1, /* 6 поисковое слово по слогам длиной - @int_num */
t3.DATA_TYPE, /* 7 ип данных */
t3.CHARACTER_MAXIMUM_LENGTH, /* 8 размер поля */
0 as occupied /* 9 1 - если занята другой процедурой или 2- запись уже отработана или 3 обрабатывается повторно */
from
#table_03_VAR t3,
#table_pre_15 p5
where
t3.CHARACTER_MAXIMUM_LENGTH > 29 /* считаем что в поля менее 29 символов имен быть недолжно */
and t3.DATA_TYPE in ( 'text', 'ntext', 'nvarchar', 'varchar', 'char', 'nchar')
UNION
select
/* 1 Поиск полей с кириллицей [а-я] XML */
'INSERT INTO ##table_10 ( TABLE_SCHEMA, table_name, COLUMN_NAME, DATA_TYPE, DATA_SIZE, pole_5)
SELECT ''' +
t3.TABLE_SCHEMA + ''', ''' +
t3.table_name + ''', ''' +
t3.COLUMN_NAME + ''', ''' +
t3.DATA_TYPE + ''', ''' +
Convert (varchar (100), t3.CHARACTER_MAXIMUM_LENGTH) + ''', ''' +
t3.TABLE_SCHEMA + '.'+ t3.table_name + '.' + t3.COLUMN_NAME + '.' + p5.name_2 + '''
FROM ' + t3.TABLE_SCHEMA + '.' + t3.table_name + ' (nolock) WHERE '
+ 'cast (' + t3.COLUMN_NAME + Space (1) + 'as nvarchar (max)) like ''%[А-я]%'' having Count (*) > 0'
,
/* 2 Поиск полей ПО СЛОГАМ длиной - @int_num */
'INSERT INTO ##table_10 ( TABLE_SCHEMA, table_name, COLUMN_NAME, DATA_TYPE, DATA_SIZE, pole_5)
SELECT ''' +
t3.TABLE_SCHEMA + ''', ''' +
t3.table_name + ''', ''' +
t3.COLUMN_NAME + ''', ''' +
t3.DATA_TYPE + ''', ''' +
Convert (varchar (100), t3.CHARACTER_MAXIMUM_LENGTH) + ''', ''' +
t3.TABLE_SCHEMA + '.'+ t3.table_name + '.' + t3.COLUMN_NAME + '.' + p5.name_2 + '''
FROM ' + t3.TABLE_SCHEMA + '.' + t3.table_name + ' (nolock) WHERE '
+ t3.COLUMN_NAME + '.exist(N''//*[contains(., ' + '"' + p5.name_2 + '"'+ ')]'') = 1 having Count (*) > 0'
,
/* 3 резерв */
'if INDEXPROPERTY (object_id (''' + t3.TABLE_SCHEMA + '.'+ t3.table_name + '''), ''ids_'+ t3.table_name + '_' + t3.COLUMN_NAME + ''', ''IndexID'') > 0 DROP INDEX ids_' + t3.table_name + '_' + t3.COLUMN_NAME + ' ON ' + t3.TABLE_SCHEMA + '.' + t3.table_name
,
t3.TABLE_SCHEMA + '.'+ t3.table_name + '.' + t3.COLUMN_NAME, /* 4 "таблица + поле" - идентификатор индекса */
t3.TABLE_SCHEMA + '.'+ t3.table_name + '.' + t3.COLUMN_NAME + '.' + p5.name_2, /* 5 "таблица + поле + имя" как идентификатор поля */
p5.name_1, /* 6 поисковое слово по слогам длиной - @int_num */
t3.DATA_TYPE, /* 7 тип данных */
t3.CHARACTER_MAXIMUM_LENGTH, /* 8 размер поля */
0 as occupied /* 9 1 - если занята другой процедурой или 2- запись уже отработана или 3 обрабатывается повторно */
from
#table_03_VAR t3,
#table_pre_15 p5
where
t3.CHARACTER_MAXIMUM_LENGTH < 0
and t3.DATA_TYPE = 'xml'
-- ORDER BY
-- t3.TABLE_SCHEMA, t3.table_name, t3.COLUMN_NAME, p5.name_1
select @row_count = Count (*) from w_depersonalization_table_12
if user_name() = @user_name INSERT INTO w_getdate ( num, spid, date_time,sec, descr) SELECT 7, @@spid, GetDate (), DATEDIFF(ms, Max (date_time), GetDate ()), Convert (varchar, @row_count) + ' всего нужно обработать' FROM w_getdate with (nolock, index(isx_w_getdate_date_time_spid)) WHERE spid = @@spid
--goto err
/* убираем поля которые уже обработаны в транзакции. DELETE отрабатывает за 35.9593 секунд, при удалении 2 190 750 записей (всех) */
DELETE
p12 /* здесь лежат все гипотетические запросы */
FROM
w_depersonalization_table_12 p12 with (index (isx_w_depersonalization_table_12_occupied)), /* здесь лежат все гипотетические запросы */
w_depersonalization_pole_3 p3 with (index (isx_w_depersonalization_pole_3_pole_1)) /* здесь лежат все обработанные запросы */
WHERE
p12.pole_5 = p3.pole_1
/* осталось обработать */
select @row_count = Count (*) from w_depersonalization_table_12
if @row_count = 0
begin
/* вставляем одну запись, чтобы другие процедуры после окончания транзакции не пошли по этому пути */
INSERT INTO w_depersonalization_table_12 (occupied) VALUES (@occupied_02)
end
/* всего нужно обработать */
if user_name() = @user_name INSERT INTO w_getdate ( num, spid, date_time,sec, descr) SELECT 8, @@spid, GetDate (), DATEDIFF(ms, Max (date_time), GetDate ()), Convert (varchar, @row_count) + ' после удаления обработанных, осталось обработать' FROM w_getdate with (nolock, index(isx_w_getdate_date_time_spid)) WHERE spid = @@spid
END
/*************************************/
/* Завершение транзакции по TABLOCKX */
COMMIT TRAN a1
/*************************************/
/* будем обрабатывать */
select @row_count = Count (*) from w_depersonalization_table_12 (nolock) WHERE occupied = 0
if user_name() = @user_name INSERT INTO w_getdate ( num, spid, date_time,sec, descr) SELECT 9, @@spid, GetDate (), DATEDIFF(ms, Max (date_time), GetDate ()), Convert (varchar, @row_count) + ' - будем обрабатывать. Если 0 - то все записи уже обработаны.' FROM w_getdate with (nolock, index(isx_w_getdate_date_time_spid)) WHERE spid = @@spid
/* Получаем количество записей которые можно обработать */
SELECT @occupied_12 = Count (*) FROM w_depersonalization_table_12 (nolock) WHERE occupied = 0
SELECT @occupied_16 = Count (*) FROM w_depersonalization_table_12 (nolock) WHERE occupied = 1
-- SELECT Count (*) FROM w_depersonalization_table_12 WHERE occupied = 0 /* occupied = 0 записи которые нужно обрабатывать */
/******************************************************************/
/* цикл по 10000 записей из таблицы w_depersonalization_table_12 */
/* для того чтобы можно запустить параллельно несколько процедур */
/******************************************************************/
WHILE @occupied_12 > 0 or @occupied_16 > 0
BEGIN
if object_id('tempdb..#table_11',N'u') is not null drop table #table_11
/* таблица сбора всех данных по всем таблицам полям и подменяемым данным */
create table #table_11
(
id_identity int identity,
pole_1 nvarchar (4000) null, /* Поиск полей для обезличивания */
pole_2 nvarchar (1000) null, /* Создание индекса */
pole_3 nvarchar (1000) null, /* Удаление индекса */
pole_4 nvarchar (100) null, /* "таблица + поле" - идентификатор индекса */
pole_5 nvarchar (100) null, /* "таблица + поле + имя" - идентификатор запроса */
pole_6 nvarchar (100) null, /* поисковое слово по слогам длиной - @int_num */
DATA_TYPE varchar (255) null, /* тип данных */
CHARACTER_MAXIMUM_LENGTH int null, /* размер поля */
occupied int null /* 1 - если занята другой процедурой или 2- запись уже отработана */
)
/***********************************************************************************************************************************************/
/* Транзакция для блокировки таблицы по w_depersonalization_table_12 в момент выборки, чтобы параллельно не обрабатывались одни и теже записи */
/***********************************************************************************************************************************************/
IF @occupied_12 > 0
BEGIN
BEGIN TRAN a2
/* перебрасываем в новую таблицу чтобы обновить поле id_identity */
INSERT INTO #table_11
(
pole_1, /* Поиск полей для обезличивания */
pole_2, /* Создание индекса */
pole_3, /* Удаление индекса */
pole_4, /* "таблица + поле" - идентификатор индекса */
pole_5, /* "таблица + поле + имя" - идентификатор запроса */
pole_6, /* поисковое слово по слогам длиной - @int_num */
DATA_TYPE, /* тип данных */
CHARACTER_MAXIMUM_LENGTH, /* размер поля */
occupied /* 1 - если занята другой процедурой или 2 - запись уже отработана - 3 обрабатывается повторно */
)
SELECT TOP 10000 /* первые 10 000 записей для этой процедуры */
pole_1, /* Поиск полей для обезличивания */
pole_2, /* Создание индекса */
pole_3, /* Удаление индекса */
pole_4, /* "таблица + поле" - идентификатор индекса */
pole_5, /* "таблица + поле + имя" - идентификатор запроса */
pole_6, /* поисковое слово по слогам длиной - @int_num */
DATA_TYPE, /* тип данных */
CHARACTER_MAXIMUM_LENGTH, /* размер поля */
occupied /* 1 - если занята другой процедурой или запись уже отработана */
FROM
w_depersonalization_table_12 (TABLOCKX)
WHERE
occupied = 0 /* 1 - если занята другой процедурой или 2 - запись уже отработана */
ORDER BY
pole_5
/* Проставляем флаг occupied = 1 для забранных записей */
UPDATE
w_depersonalization_table_12
SET
occupied = 1 /* 1 для забранных записей */
FROM
#table_11 t11
WHERE
t11.pole_5 = w_depersonalization_table_12.pole_5
/****************************************************************************/
/* Завершение транзакции по блокировке таблицы w_depersonalization_table_12 */
/****************************************************************************/
COMMIT TRAN a2
END
ELSE IF @occupied_16 > 0
BEGIN
/* перебрасываем в новую таблицу чтобы обновить поле id_identity */
INSERT INTO #table_11
(
pole_1, /* Поиск полей для обезличивания */
pole_2, /* Создание индекса */
pole_3, /* Удаление индекса */
pole_4, /* "таблица + поле" - идентификатор индекса */
pole_5, /* "таблица + поле + имя" - идентификатор запроса */
pole_6, /* поисковое слово по слогам длиной - @int_num */
DATA_TYPE, /* тип данных */
CHARACTER_MAXIMUM_LENGTH, /* размер поля */
occupied /* 1 - если занята другой процедурой или 2 - запись уже отработана - 3 обрабатывается повторно */
)
SELECT TOP 10000 /* первые 10 000 записей для этой процедуры */
pole_1, /* Поиск полей для обезличивания */
pole_2, /* Создание индекса */
pole_3, /* Удаление индекса */
pole_4, /* "таблица + поле" - идентификатор индекса */
pole_5, /* "таблица + поле + имя" - идентификатор запроса */
pole_6, /* поисковое слово по слогам длинной - @int_num */
DATA_TYPE, /* тип данных */
CHARACTER_MAXIMUM_LENGTH, /* размер поля */
occupied /* 1 - если занята другой процедурой или запись уже отработана */
FROM
w_depersonalization_table_12 (nolock)
WHERE
occupied = 0 /* 1 - если занята другой процедурой или 2 - запись уже отработана */
ORDER BY
substring (Reverse (pole_5), CAST ((Rand () * 10) + 1 as int ), 3) /* сортировка случайным образом 10 вариантов сортировки */
END
/* получаем количество записей по всем таблицам */
select @row_count = Count (*) from #table_11
set @id_identity = 1
set @pole_1 = ''
if user_name() = @user_name INSERT INTO w_getdate ( num, spid, date_time,sec, descr) SELECT 10, @@spid, GetDate (), DATEDIFF(ms, Max (date_time), GetDate ()), Convert (varchar, @row_count) + ' - нужно обработать SELECT(ов)' FROM w_getdate with (nolock, index(isx_w_getdate_date_time_spid)) WHERE spid = @@spid
/********************************************************/
/* цикл символам кирилицы */
/********************************************************/
while @id_identity <= @row_count
begin
select
@pole_1 = pole_1, /* поиск для обезличивания */
@pole_2 = pole_2, /* создание индекса */
@pole_3 = pole_3, /* удаление индекса */
@pole_4 = pole_4, /* "таблица + поле" как идентификатор индекса */
@pole_5 = pole_5, /* "таблица + поле + имя" как идентификатор поля */
@pole_6 = pole_6, /* поисковое слово по слогам длиной - @int_num */
@DATA_TYPE = DATA_TYPE, /* тип данных */
@CHARACTER_MAXIMUM_LENGTH = CHARACTER_MAXIMUM_LENGTH /* размер поля */
from
#table_11
where
id_identity = @id_identity
if user_name() = @user_name INSERT INTO w_getdate ( num, spid, date_time,sec, descr) SELECT 11, @@spid, GetDate (), DATEDIFF(ms, Max (date_time), GetDate ()), @pole_1 FROM w_getdate with (nolock, index(isx_w_getdate_date_time_spid)) WHERE spid = @@spid
/* объединяем запросы в максимальную строку через UNION чтобы реже вызывать процедуру SP_EXECUTESQL */
if datalength (@pole_1) > 0 and datalength (@pole_2) > 0
begin
/* Проверяем а не исполнил ли кто-то этот запрос */
SELECT
@occupied_01 = Max (t12.occupied)
FROM
w_depersonalization_table_12 t12 (nolock)
WHERE
t12.pole_5 = @pole_5
/* если статус не равен двум, выполняем поиск */
IF NOT @occupied_01 = @occupied_02
BEGIN
/********************************************************************/
/* Основная проверка на то, что в данном поле таблицы есть кирилица */
/********************************************************************/
EXEC SP_EXECUTESQL @pole_1
set @pole_1 = ''
if user_name() = @user_name INSERT INTO w_getdate ( num, spid, date_time,sec, descr) SELECT 12, @@spid, GetDate (), DATEDIFF(ms, Max (date_time), GetDate ()), @pole_5 FROM w_getdate with (nolock, index(isx_w_getdate_date_time_spid)) WHERE spid = @@spid
END
IF EXISTS (select 1 from ##table_10 WHERE pole_5 = @pole_5)
BEGIN
/* Удаляем данные так как это была проверка наналичие кирилицы в поле */
DELETE FROM
##table_10
WHERE
pole_5 = @pole_5
/* сохраняем идентификатор */
SELECT @pole_44 = @pole_4 /* "таблица + поле" как идентификатор индекса */
/********************************************************/
/* цикл по полю для всех слогов из слов пользователей */
/********************************************************/
while @id_identity <= @row_count and @pole_44 = @pole_4
begin
/* сохраняем переменную */
SET @pole_22 = @pole_2
if datalength (@pole_2) > 0
begin
/* Проверяем а не исполнил ли кто-то этот запрос */
SELECT
@occupied_01 = Max (t12.occupied)
FROM
w_depersonalization_table_12 t12 (nolock)
WHERE
t12.pole_5 = @pole_5
/* если статус не равен двум, выполняем поиск */
IF NOT @occupied_01 = @occupied_02
BEGIN
/********************************************************************/
/* Проверка поля по слогам, что в данном поле таблицы есть кирилица */
/********************************************************************/
EXEC SP_EXECUTESQL @pole_2
END
/* очищаем переменную */
SET @pole_2 = ''
if user_name() = @user_name INSERT INTO w_getdate ( num, spid, date_time,sec, descr) SELECT 13, @@spid, GetDate (), DATEDIFF(ms, Max (date_time), GetDate ()), @pole_5 FROM w_getdate with (nolock, index(isx_w_getdate_date_time_spid)) WHERE spid = @@spid
/* все отработанные запросы сохраняются в таблицу */
INSERT INTO w_depersonalization_pole_3
(
pole_1, /* "таблица + поле + имя " как идентификатор запроса */
pole_6, /* поисковое слово по слогам длиной - @int_num */
DATA_TYPE, /* тип данных поля */
CHARACTER_MAXIMUM_LENGTH /* длина поля */
)
VALUES
(
@pole_5, /* "таблица + поле + имя " как идентификатор запроса */
@pole_6, /* поисковое слово по слогам длиной - @int_num */
@DATA_TYPE, /* тип данных поля */
@CHARACTER_MAXIMUM_LENGTH /* длина поля */
)
IF EXISTS (select 1 from ##table_10 WHERE pole_5 = @pole_5)
BEGIN
/* Вставка в стационарную таблицу найденные данные, */
/* это сделано для того что операции не успевают пройти за стуки, */
/* виртуалка перезапускается и теряется результат работы */
INSERT INTO w_depersonalization_table_9
( id_identity, TABLE_SCHEMA, table_name, COLUMN_NAME, name_1, name_2, DATA_TYPE, DATA_SIZE )
SELECT
id_identity, TABLE_SCHEMA, table_name, COLUMN_NAME, name_1, name_2, DATA_TYPE, DATA_SIZE /* '-1' для XML */
FROM
##table_10 (nolock)
WHERE
pole_5 = @pole_5
/* очищаем таблицу в которую загружаются найденные данные для обезлички (если такие были найдены) */
DELETE FROM
##table_10
WHERE
pole_5 = @pole_5
if user_name() = @user_name INSERT INTO w_getdate ( num, spid, date_time,sec, descr) SELECT 14, @@spid, GetDate (), DATEDIFF(ms, Max (date_time), GetDate ()), @pole_22 FROM w_getdate with (nolock, index(isx_w_getdate_date_time_spid)) WHERE spid = @@spid
/* Так как в данной 'таблица + поле' персональные данные найдены, нет смысла продолжать поиск дальше */
SET @pole_44 = 'Найдено!' /* это обозначает выход из второго цикла так как будет проверено @pole_44 = @pole_4 */
END
END
/* если продолжаем крутится во втором цикле */
IF @pole_44 = @pole_4
BEGIN
/* Проставляем флаг occupied = 2 для обработанных записей */
UPDATE
w_depersonalization_table_12
SET
occupied = 2
WHERE
w_depersonalization_table_12.pole_5 = @pole_5
if user_name() = @user_name INSERT INTO w_getdate ( num, spid, date_time,sec, descr) SELECT 15, @@spid, GetDate (), DATEDIFF(ms, Max (date_time), GetDate ()), Convert (varchar, @id_identity) FROM w_getdate with (nolock, index(isx_w_getdate_date_time_spid)) WHERE spid = @@spid
/* счетчик для цикла */
set @id_identity = @id_identity + 1
select
@pole_1 = pole_1, /* поиск для обезличивания */
@pole_2 = pole_2, /* создание индекса */
@pole_3 = pole_3, /* удаление индекса */
@pole_4 = pole_4, /* "таблица + поле" как идентификатор индекса */
@pole_5 = pole_5, /* "таблица + поле + имя" как идентификатор поля */
@pole_6 = pole_6, /* поисковое слово по слогам длиной - @int_num */
@DATA_TYPE = DATA_TYPE, /* тип данных */
@CHARACTER_MAXIMUM_LENGTH = CHARACTER_MAXIMUM_LENGTH /* размер поля */
from
#table_11
where
id_identity = @id_identity
END
ELSE
BEGIN
/* Выходи из второго цикал */
SET @id_identity_old = @id_identity
/* счетчик цикла */
SELECT
@id_identity = IsNull (Min (id_identity), @row_count + 1)
FROM
#table_11
WHERE
pole_4 <> @pole_4 and
id_identity > @id_identity_old
if user_name() = @user_name INSERT INTO w_getdate ( num, spid, date_time,sec, descr) SELECT 16, @@spid, GetDate (), DATEDIFF(ms, Max (date_time), GetDate ()), Convert (varchar, @id_identity_old) + '/' + Convert (varchar, @id_identity) FROM w_getdate with (nolock, index(isx_w_getdate_date_time_spid)) WHERE spid = @@spid
/* все НЕотработанные запросы сохраняются в таблицу, так как персональные данные всеравно найдены */
INSERT INTO w_depersonalization_pole_3
(
pole_1, /* "таблица + поле + имя " как идентификатор запроса */
pole_6, /* поисковое слово по слогам длиной - @int_num */
DATA_TYPE, /* тип данных поля */
CHARACTER_MAXIMUM_LENGTH /* длина поля */
)
SELECT
pole_5, /* "таблица + поле + имя " как идентификатор запроса */
pole_6, /* поисковое слово по слогам длиной - @int_num */
DATA_TYPE, /* тип данных поля */
CHARACTER_MAXIMUM_LENGTH /* длина поля */
FROM
#table_11
WHERE /* здесь именно '<' так как текущая запись уже сохранена */
@id_identity_old < id_identity and id_identity < @id_identity
/* Проставляем флаг occupied = 2 для обработанных */
UPDATE
w_depersonalization_table_12
SET
occupied = 2
FROM
#table_11 t11
WHERE /* здесь именно '<' так как текущая запись уже сохранена */
w_depersonalization_table_12.pole_4 = t11.pole_4 and
@id_identity_old <= t11.id_identity and t11.id_identity < @id_identity
END
END
/* счетчик для цикла */
--set @id_identity = @id_identity + 1 /* счетчик уже прибавился */
END
ELSE
BEGIN
SET @id_identity_old = @id_identity
/* счетчик цикла */
SELECT
@id_identity = IsNull (Min (id_identity), @row_count + 1)
FROM
#table_11
WHERE
pole_4 <> @pole_4 and
id_identity > @id_identity_old
/* все отработанные запросы сохраняются в таблицу */
INSERT INTO w_depersonalization_pole_3
(
pole_1, /* "таблица + поле + имя " как идентификатор запроса */
pole_6, /* поисковое слово по слогам длиной - @int_num */
DATA_TYPE, /* тип данных поля */
CHARACTER_MAXIMUM_LENGTH /* длина поля */
)
SELECT
pole_5, /* "таблица + поле + имя " как идентификатор запроса */
pole_6, /* поисковое слово по слогам длиной - @int_num */
DATA_TYPE, /* тип данных поля */
CHARACTER_MAXIMUM_LENGTH /* длина поля */
FROM
#table_11
WHERE /* сдесь именно '<=' так как текущая запись НЕ сохранена */
@id_identity_old <= id_identity and id_identity < @id_identity
if user_name() = @user_name INSERT INTO w_getdate ( num, spid, date_time,sec, descr) SELECT 17, @@spid, GetDate (), DATEDIFF(ms, Max (date_time), GetDate ()), Convert (varchar, @id_identity_old ) + '/' + Convert (varchar, @id_identity ) FROM w_getdate with (nolock, index(isx_w_getdate_date_time_spid)) WHERE spid = @@spid
/* Проставляем флаг occupied = 2 для обработанных */
UPDATE
w_depersonalization_table_12
SET
occupied = 2
FROM
#table_11 t11
WHERE
/* сдесь именно '<=' так как текущая запись НЕ сохранена */
w_depersonalization_table_12.pole_4 = t11.pole_4 and
@id_identity_old <= t11.id_identity and t11.id_identity < @id_identity
END
end
else
begin
/* по идее сюща цикл попадать никогда не должен, но на всякий случай кусочек проработан */
SET @id_identity_old = @id_identity
/* счетчик цикла */
SELECT
@id_identity = IsNull (Min (id_identity), @row_count + 1)
FROM
#table_11
WHERE
datalength ( @pole_1) > 0 and
datalength ( @pole_2) > 0 and
pole_4 <> @pole_4 and
id_identity > @id_identity_old
if user_name() = @user_name INSERT INTO w_getdate ( num, spid, date_time,sec, descr) SELECT 18, @@spid, GetDate (), DATEDIFF(ms, Max (date_time), GetDate ()), Convert (varchar, @id_identity_old ) FROM w_getdate with (nolock, index(isx_w_getdate_date_time_spid)) WHERE spid = @@spid
end
end
/* удаляем таблицу чтобы обновить поле id_identity */
drop table #table_11
/* Получаем количество записей которые можно обработать */
SELECT @occupied_12 = Count (*) FROM w_depersonalization_table_12 with (nolock, index (isx_w_depersonalization_table_12_occupied) ) WHERE occupied = 0
SELECT @occupied_16 = Count (*) FROM w_depersonalization_table_12 with (nolock, index (isx_w_depersonalization_table_12_occupied) ) WHERE occupied = 1
END
if user_name() = @user_name INSERT INTO w_getdate ( num, spid, date_time,sec, descr) SELECT 19, @@spid, GetDate (), DATEDIFF(ms, Max (date_time), GetDate ()), Convert (varchar, @id_identity_old ) FROM w_getdate with (nolock, index(isx_w_getdate_date_time_spid)) WHERE spid = @@spid
-- SELECT Count (*) FROM w_depersonalization_table_12 WHERE occupied = 3 /* если осталис записи occupied = 3 то их нужно перевести occupied = 1 (так как их обработку прерывали ) */
-- DELETE FROM w_depersonalization_table_12 WHERE occupied = 2 /* обработаны */
-- select Count (*) as 'обработано' from w_depersonalization_pole_3
/*------ второй этап --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
SELECT @occupied_12 = Count (*) FROM w_depersonalization_table_12 /*(TABLOCKX)*/ (NOLOCK) WHERE occupied <> 2 /* проверка на все ли записи обработаны? */
/* Ожидание когда закончат работу паралельные процедуры так как свободных записей уже не осталось, все в работе */
IF @occupied_12 > 0
BEGIN
/* цикл ожидания пока все записи не обработаются */
while @occupied_12 > 0
BEGIN
if user_name() = @user_name INSERT INTO w_getdate ( num, spid, date_time,sec, descr) SELECT 20, @@spid, GetDate (), DATEDIFF(ms, Max (date_time), GetDate ()), 'WAITFOR DELAY 00:01:00' FROM w_getdate with (nolock, index(isx_w_getdate_date_time_spid)) WHERE spid = @@spid
/* Задержка на указанное время WAITFOR DELAY '00:01:00' одна минута */
WAITFOR DELAY '00:01:00'
SELECT @occupied_12 = Count (*) FROM w_depersonalization_table_12 /*(TABLOCKX)*/ (NOLOCK) WHERE occupied <> 2 /* проверка на все ли записи обработаны? */
END
END
--SELECT Count (*) FROM w_depersonalization_table_12 (TABLOCKX) /* (NOLOCK)*/ WHERE occupied <> 2 /* все ли записи обработаны */
/* транзакция для блокировки w_depersonalization_table_13 */
BEGIN TRAN a3
SELECT @RowCount_table_13 = Count (*) FROM w_depersonalization_table_13 (TABLOCK) /*(TABLOCKX)*/
/* если записей нет, то создаем их */
IF @RowCount_table_13 = 0
BEGIN
/* Группируем результат всей предыдущей работы */
insert into #table_12 (TABLE_SCHEMA, table_name, COLUMN_NAME, DATA_TYPE, CHARACTER_MAXIMUM_LENGTH, pole_5 ) select TABLE_SCHEMA, table_name, COLUMN_NAME, DATA_TYPE, Convert (int, DATA_SIZE), Count (*) from w_depersonalization_table_9 GROUP BY TABLE_SCHEMA, table_name, COLUMN_NAME, DATA_TYPE, DATA_SIZE order by TABLE_SCHEMA, table_name, COLUMN_NAME, DATA_TYPE, DATA_SIZE
truncate table #table_01
/* список всех Ф.И.О. для получения списка обезличивания */
insert into #table_01 (name_1)
select distinct /* Фамилии */ s_U_FamilyName from t_user tu (nolock) where IIF (Rtrim (s_U_FamilyName) = '''', NULL, s_U_FamilyName) IS NOT NULL and Len (s_U_FamilyName)> 1 and ASCII (tu.s_U_FamilyName) > 191 and charindex (' ', s_U_FamilyName ) = 0 and Len (s_U_FamilyName) > 1
union select distinct /* Имена */ s_U_FirstName from t_user tu (nolock) where IIF (Rtrim (s_U_FirstName) = '''', NULL, s_U_FirstName) IS NOT NULL and Len (s_U_FirstName) > 1 and ASCII (tu.s_U_FirstName) > 191 and charindex (' ', s_U_FirstName ) = 0 and Len (s_U_FirstName) > 1
union select distinct /* Отчества */ s_U_LastName from t_user tu (nolock) where IIF (Rtrim (s_U_LastName) = '''', NULL, s_U_LastName) IS NOT NULL and Len (s_U_LastName) > 1 and ASCII (tu.s_U_LastName) > 191 and charindex (' ', s_U_LastName ) = 0 and Len (s_U_LastName) > 1
if user_name() = @user_name INSERT INTO w_getdate ( num, spid, date_time,sec, descr) SELECT 21, @@spid, GetDate (), DATEDIFF(ms, Max (date_time), GetDate ()), null FROM w_getdate with (nolock, index(isx_w_getdate_date_time_spid)) WHERE spid = @@spid
/* самый простой способо сделать второй список пользователей в другой последовательности */
insert into #table_02 (name_2)
select name_1 from #table_01 order by substring (name_1, 2, 3) desc, id_identity desc
/* просталяем второй столбец пользователей */
UPDATE t1 SET name_2 = t2.name_2 FROM #table_01 t1, #table_02 t2 WHERE t2.id_identity = t1.id_identity and NOT t1.name_1 = t2.name_2
/* проходимся еще раз, так как может остаться одно пустое поле */
UPDATE t1 SET name_2 = t2.name_2 FROM #table_01 t1, #table_02 t2 WHERE t1.name_2 IS NULL and NOT t1.name_1 = t2.name_2
if user_name() = @user_name INSERT INTO w_getdate ( num, spid, date_time, sec, descr) SELECT 22, @@spid, GetDate (), DATEDIFF(ms, Max (date_time), GetDate ()), null FROM w_getdate with (nolock, index(isx_w_getdate_date_time_spid)) WHERE spid = @@spid
/* в транзации отрабатывает за 346.486 секунд это около 6 минут */
INSERT INTO w_depersonalization_table_13
(
pole_1, /* 1 Поиск полей с кирилицей */
pole_2, /* 2 Создание индекса */
pole_3, /* 3 резерв */
pole_4, /* 4 "таблица + поле" - идентификатор индекса */
pole_5, /* 5 "таблица + поле + имя" - идентификатор запроса */
pole_6, /* 6 поисковое слово по слогам длиной - @int_num */
DATA_TYPE, /* 7 тип данных */
CHARACTER_MAXIMUM_LENGTH, /* 8 размер поля */
occupied /* 9 1 - если занята другой процедурой или 2 - запись уже отработана */
)
SELECT
'INSERT INTO ##table_8 ( TABLE_SCHEMA, table_name, COLUMN_NAME, name_1, name_2, DATA_TYPE, DATA_SIZE, pole_5)
SELECT DISTINCT ''' +
t2.TABLE_SCHEMA + ''', ''' +
t2.table_name + ''', ''' +
t2.COLUMN_NAME + ''', ''' +
p1.name_1 + ''', ''' +
p1.name_2 + ''', ''' +
t2.DATA_TYPE + ''', ''' +
Convert (varchar (100), t2.CHARACTER_MAXIMUM_LENGTH) + ''', ''' +
t2.TABLE_SCHEMA + '.'+ t2.table_name + '.' + t2.COLUMN_NAME + '.' + p1.name_1 + '''
FROM ' + t2.TABLE_SCHEMA + '.' + t2.table_name + ' (nolock' +
--CASE
-- WHEN t2.CHARACTER_MAXIMUM_LENGTH < 900 THEN ' index ( ids_'+ t2.table_name + '_' + t2.COLUMN_NAME + ')'
-- ELSE ''
--END +
') ' + '
WHERE ' + 'PATINDEX(''%' + p1.name_1 + '%'', ' + t2.COLUMN_NAME + ' ) > 0 and ' + t2.COLUMN_NAME + ' IS NOT NULL'
,
/* 2 резерв, так как индекс не нужен */
CASE
WHEN t2.CHARACTER_MAXIMUM_LENGTH < 900 THEN 'if INDEXPROPERTY (object_id (''' + t2.TABLE_SCHEMA + '.'+ t2.table_name + '''), ''ids_'+ t2.table_name + '_' + t2.COLUMN_NAME + ''', ''IndexID'') is null CREATE INDEX ids_' + t2.table_name + '_' + t2.COLUMN_NAME + ' ON ' + t2.TABLE_SCHEMA + '.' + t2.table_name + ' (' + t2.COLUMN_NAME + ')'
ELSE ''
END
,
/* 3 резерв, так как индекс не нужен */
'if INDEXPROPERTY (object_id (''' + t2.TABLE_SCHEMA + '.'+ t2.table_name + '''), ''ids_'+ t2.table_name + '_' + t2.COLUMN_NAME + ''', ''IndexID'') > 0 DROP INDEX ids_' + t2.table_name + '_' + t2.COLUMN_NAME + ' ON ' + t2.TABLE_SCHEMA + '.' + t2.table_name
,
/* 4 "таблица + поле" - идентификатор индекса */
t2.TABLE_SCHEMA + '.'+ t2.table_name + '.' + t2.COLUMN_NAME, /* 4 "таблица + поле" - идентификатор индекса */
t2.TABLE_SCHEMA + '.'+ t2.table_name + '.' + t2.COLUMN_NAME + '.' + p1.name_1, /* 5 "таблица + поле + имя" как идентификатор поля */
p1.name_2, /* 6 поисковое слово по слогам длиной - @int_num */
t2.DATA_TYPE, /* 7 ип данных */
t2.CHARACTER_MAXIMUM_LENGTH, /* 8 размер поля */
0 as occupied /* 9 1 - если занята другой процедурой или 2- запись уже отработана или 3 обрабатывается повторно */
from
#table_01 p1, /* списиок персональных данных */
#table_12 t2 /* список таблиц, где скорее всего есть персональные данные, так как эти таблицы были проерены по слогам */
where
t2.CHARACTER_MAXIMUM_LENGTH > 29 /* считаем что в поля менее 29 символов имен быть недолжно */
and t2.DATA_TYPE in ( 'text', 'ntext', 'nvarchar', 'varchar', 'char', 'nchar')
UNION
select
/* 2 Поиск полей ПО СЛОГАМ длиной - @int_num */
'INSERT INTO ##table_8 ( TABLE_SCHEMA, table_name, COLUMN_NAME, name_1, name_2, DATA_TYPE, DATA_SIZE, pole_5)
SELECT ''' +
t2.TABLE_SCHEMA + ''', ''' +
t2.table_name + ''', ''' +
t2.COLUMN_NAME + ''', ''' +
p1.name_1 + ''', ''' +
p1.name_2 + ''', ''' +
t2.DATA_TYPE + ''', ''' +
Convert (varchar (100), t2.CHARACTER_MAXIMUM_LENGTH) + ''', ''' +
t2.TABLE_SCHEMA + '.'+ t2.table_name + '.' + t2.COLUMN_NAME + '.' + p1.name_1 + '''
FROM ' + t2.TABLE_SCHEMA + '.' + t2.table_name + ' (nolock) WHERE '
+ t2.COLUMN_NAME + '.exist(N''//*[contains(., ' + '"' + p1.name_1 + '"'+ ')]'') = 1 having Count (*) > 0'
,
/* 2 резерв */
NULL
,
/* 3 резерв */
'if INDEXPROPERTY (object_id (''' + t2.TABLE_SCHEMA + '.'+ t2.table_name + '''), ''ids_'+ t2.table_name + '_' + t2.COLUMN_NAME + ''', ''IndexID'') > 0 DROP INDEX ids_' + t2.table_name + '_' + t2.COLUMN_NAME + ' ON ' + t2.TABLE_SCHEMA + '.' + t2.table_name
,
t2.TABLE_SCHEMA + '.'+ t2.table_name + '.' + t2.COLUMN_NAME, /* 4 "таблица + поле" - идентификатор индекса */
t2.TABLE_SCHEMA + '.'+ t2.table_name + '.' + t2.COLUMN_NAME + '.' + p1.name_2, /* 5 "таблица + поле + имя" как идентификатор поля */
p1.name_1, /* 6 поисковое слово по слогам длиной - @int_num */
t2.DATA_TYPE, /* 7 тип данных */
t2.CHARACTER_MAXIMUM_LENGTH, /* 8 размер поля */
0 as occupied /* 9 1 - если занята другой процедурой или 2- запись уже отработана или 3 обрабатывается повторно */
from
#table_01 p1, /* списиок персональных данных */
#table_12 t2 /* список таблиц, где скорее всего есть персональные данные, так как эти таблицы были проерены по слогам */
where
t2.CHARACTER_MAXIMUM_LENGTH < 0
and t2.DATA_TYPE = 'xml'
select @row_count = Count (*) from w_depersonalization_table_13
if user_name() = @user_name INSERT INTO w_getdate ( num, spid, date_time,sec, descr) SELECT 23, @@spid, GetDate (), DATEDIFF(ms, Max (date_time), GetDate ()), Convert (varchar, @row_count) + ' всего нужно обрабоать' FROM w_getdate with (nolock, index(isx_w_getdate_date_time_spid)) WHERE spid = @@spid
/* убираем поля которые уже обработаны в транзакции. DELETE отрабатывает за 35.9593 секунд, при удалени 2 190 750 записей (всех) */
DELETE
p13 /* здесь лежат все гипотетические запросы */
FROM
w_depersonalization_table_13 p13 with (nolock, index (isx_w_depersonalization_table_13_occupied)), /* здесь лежат все гипотетические запросы */
w_depersonalization_pole_1 p1 (nolock) /* здесь лежат все обработанные запросы */
WHERE
p13.pole_5 = p1.pole_1
select @row_count = Count (*) from w_depersonalization_table_13
if user_name() = @user_name INSERT INTO w_getdate ( num, spid, date_time,sec, descr) SELECT 24, @@spid, GetDate (), DATEDIFF(ms, Max (date_time), GetDate ()), Convert (varchar, @row_count) + ' но осталось обрабоать' FROM w_getdate with (nolock, index(isx_w_getdate_date_time_spid)) WHERE spid = @@spid
/* осталось обрабоать */
select @row_count = Count (*) from w_depersonalization_table_13
if @row_count = 0
begin
/* вставыляем одну запись, чтобы другие процедуры после окончания транзакии не пошли по этому пути */
INSERT INTO w_depersonalization_table_13 (occupied) VALUES (@occupied_02)
end
END
COMMIT TRAN a3
/* Получаем количество записей которые можно обработать */
SELECT @occupied_13 = Count (*) FROM w_depersonalization_table_13 (nolock) WHERE occupied = 0
SELECT @occupied_14 = Count (*) FROM w_depersonalization_table_13 (nolock) WHERE occupied = 1
-- SELECT Count (*) FROM w_depersonalization_table_12 WHERE occupied = 0 /* occupied = 0 записи которые нужно обрабатывать, occupied = 1 в работе, occupied = 2 для обработанных записей (обработка завершена ) */
/******************************************************************/
/* цикл по 10000 записей из таблицы w_depersonalization_table_12 */
/* для того чтобы можно запустить паралельно несколько процедур */
/******************************************************************/
WHILE @occupied_13 > 0 or @occupied_14 > 0
BEGIN
if user_name() = @user_name INSERT INTO w_getdate ( num, spid, date_time,sec, descr)
SELECT 25, @@spid, GetDate (), DATEDIFF(ms, Max (date_time), GetDate ()), Convert (varchar, @occupied_13) + '/' + Convert (varchar, @occupied_14) + ' цикл по 10 000 записей '
FROM w_getdate with (nolock, index(isx_w_getdate_date_time_spid))
WHERE spid = @@spid
if object_id('tempdb..#table_13',N'u') is not null drop table #table_13
/* таблица сбора всех данных по всем таблицам, полям и подменяемым данным */
create table #table_13
(
id_identity int identity,
pole_1 nvarchar (4000) null, /* Поиск полей для обезличивания */
pole_2 nvarchar (1000) null, /* Создание индекса */
pole_3 nvarchar (1000) null, /* Удаление индекса */
pole_4 nvarchar (100) null, /* "таблица + поле" - идентификатор индекса */
pole_5 nvarchar (100) null, /* "таблица + поле + имя" - идентификатор запроса */
pole_6 nvarchar (100) null, /* поисковое слово по слогам длиной - @int_num */
DATA_TYPE varchar (255) null, /* тип данных */
CHARACTER_MAXIMUM_LENGTH int null, /* размер поля */
occupied int null /* 1 - если занята другой процедурой или 2- запись уже отработана */
)
/***********************************************************************************************************************************************/
/* Транзакция для блокировки таблицы по w_depersonalization_table_12 в момент выборки, чтобы параллельно не обрабатывались одни и теже записи */
/***********************************************************************************************************************************************/
IF @occupied_13 > 0
BEGIN
BEGIN TRAN a4
/* перебрасываем в новую таблицу чтобы обновить поле id_identity */
INSERT INTO #table_13
(
pole_1, /* Поиск полей для обезличивания */
pole_2, /* Создание индекса */
pole_3, /* Удаление индекса */
pole_4, /* "таблица + поле" - идентификатор индекса */
pole_5, /* "таблица + поле + имя" - идентификатор запроса */
pole_6, /* поисковое слово по слогам длиной - @int_num */
DATA_TYPE, /* тип данных */
CHARACTER_MAXIMUM_LENGTH, /* размер поля */
occupied /* 1 - если занята другой процедурой или 2 - запись уже отработана - 3 обрабатывается повторно */
)
SELECT TOP 10000 /* первые 10 000 записей для этой процедуры */
pole_1, /* Поиск полей для обезличивания */
pole_2, /* Создание индекса */
pole_3, /* Удаление индекса */
pole_4, /* "таблица + поле" - идентификатор индекса */
pole_5, /* "таблица + поле + имя" - идентификатор запроса */
pole_6, /* поисковое слово по слогам длиной - @int_num */
DATA_TYPE, /* тип данных */
CHARACTER_MAXIMUM_LENGTH, /* размер поля */
occupied /* 1 - если занята другой процедурой или запись уже отработана */
FROM
w_depersonalization_table_13 (TABLOCKX)
WHERE
occupied = 0 /* 1 - если занята другой процедурой или 2 - запись уже отработана */
ORDER BY
pole_5 asc
/* Проставляем флаг occupied = 1 для забранных записей */
UPDATE
w_depersonalization_table_13
SET
occupied = 1 /* 1 для забранных записей */
FROM
#table_13 t11
WHERE
t11.pole_5 = w_depersonalization_table_13.pole_5
/****************************************************************************/
/* Завершение транзакции по блокировке таблицы w_depersonalization_table_13 */
/****************************************************************************/
COMMIT TRAN a4
END
ELSE IF @occupied_14 > 0
BEGIN
/* перебрасываем в новую таблицу чтобы обновить поле id_identity */
INSERT INTO #table_13
(
pole_1, /* Поиск полей для обезличивания */
pole_2, /* Создание индекса */
pole_3, /* Удаление индекса */
pole_4, /* "таблица + поле" - идентификатор индекса */
pole_5, /* "таблица + поле + имя" - идентификатор запроса */
pole_6, /* поисковое слово по слогам длиной - @int_num */
DATA_TYPE, /* тип данных */
CHARACTER_MAXIMUM_LENGTH, /* размер поля */
occupied /* 1 - если занята другой процедурой или 2 - запись уже отработана - 3 обрабатывается повторно */
)
SELECT TOP 10000 /* первые 10 000 записей для этой процедуры */
pole_1, /* Поиск полей для обезличивания */
pole_2, /* Создание индекса */
pole_3, /* Удаление индекса */
pole_4, /* "таблица + поле" - идентификатор индекса */
pole_5, /* "таблица + поле + имя" - идентификатор запроса */
pole_6, /* поисковое слово по слогам длиной - @int_num */
DATA_TYPE, /* тип данных */
CHARACTER_MAXIMUM_LENGTH, /* размер поля */
occupied /* 1 - если занята другой процедурой или запись уже отработана */
FROM
w_depersonalization_table_13 (NOLOCK)
WHERE
occupied = 1 /* 1 - если занята другой процедурой или 2 - запись уже отработана */
ORDER BY
SubString (Reverse (pole_5), CAST ((Rand () * 10) + 1 as int ), 3) /* сортировка случайным образом - 10 случайных вариантов */
END
/* получаем количество записей по всем таблицам */
select @row_table_13 = Count (*) from #table_13 (NOLOCK)
-- set @row_table_13 = 1000 /* если нужно поставить огранчения для отладки */
set @id_identity = 1
set @pole_1 = ''
if user_name() = @user_name INSERT INTO w_getdate ( num, spid, date_time,sec, descr) SELECT 26, @@spid, GetDate (), DATEDIFF(ms, Max (date_time), GetDate ()), Convert (varchar, @row_table_13) + ' - нужно обработать SELECT(ов) цикл по символам кирилицы' FROM w_getdate with (nolock, index(isx_w_getdate_date_time_spid)) WHERE spid = @@spid
/********************************************************/
/* цикл по символам кирилицы */
/********************************************************/
/* Цикл для формирования строк формата:
схема_таблицы пример: dbo
таблица пример: t_User
колонка пример: s_U_LastName
подменяемое_имя пример: Харитон
на_что_меняем пример: Иванович
тип_данных пример: varchar
размер пример: 40 */
while @id_identity <= @row_table_13
begin
set @pole_1 = ''
select
@pole_1 = pole_1, /* поиск для обезличивания */
@pole_2 = pole_2, /* создание индекса */
@pole_3 = pole_3, /* удаление индекса */
@pole_4 = pole_4, /* "таблица + поле" как идентификатор индекса */
@pole_5 = pole_5, /* "таблица + поле + имя" как идентификатор поля */
@DATA_TYPE = DATA_TYPE, /* тип данных */
@CHARACTER_MAXIMUM_LENGTH = CHARACTER_MAXIMUM_LENGTH /* размер поля */
from
#table_13
where
id_identity = @id_identity
if user_name() = @user_name INSERT INTO w_getdate ( num, spid, date_time,sec, descr) SELECT 27, @@spid, GetDate (), DATEDIFF(ms, Max (date_time), GetDate ()), Convert (varchar (10), @id_identity) + ' - № записи ' FROM w_getdate with (nolock, index(isx_w_getdate_date_time_spid)) WHERE spid = @@spid
IF Len (@pole_1) > 0 and Len (@pole_5) > 0
BEGIN
/* Проверяем а не исполнил ли кто-то этот запрос */
SELECT
@occupied_01 = Max (t13.occupied)
FROM
w_depersonalization_table_13 t13 (NOLOCK)
WHERE
t13.pole_5 = @pole_5
/* если статус не равен двум, выполняем поиск */
IF NOT @occupied_01 = @occupied_02
BEGIN
/*********************************/
/* поиск полей для обезличивания */
/*********************************/
EXEC SP_EXECUTESQL @pole_1
/* все отработанные запросы сохраняются в таблицу */
INSERT INTO w_depersonalization_pole_1
(
pole_1,
DATA_TYPE,
CHARACTER_MAXIMUM_LENGTH
)
VALUES
(
@pole_5, /* "таблица + поле + имя " как идентификатор запроса */
@DATA_TYPE,
@CHARACTER_MAXIMUM_LENGTH
)
if user_name() = @user_name INSERT INTO w_getdate ( num, spid, date_time,sec, descr) SELECT 28, @@spid, GetDate (), DATEDIFF(ms, Max (date_time), GetDate ()), @pole_5 FROM w_getdate with (nolock, index(isx_w_getdate_date_time_spid)) WHERE spid = @@spid
/* Вставка в стационарную таблицу найденные данные, это сделано для того что операции не успевают пройти за стуки, */
/* виртуалка перезапускается и теряется результат работы */
INSERT INTO w_depersonalization_table_8
(
id_identity,
TABLE_SCHEMA,
table_name,
COLUMN_NAME,
name_1,
name_2,
DATA_TYPE,
DATA_SIZE,
pole_5
)
SELECT
id_identity,
TABLE_SCHEMA,
table_name,
COLUMN_NAME,
name_1,
name_2,
DATA_TYPE,
DATA_SIZE,
pole_5
FROM
##table_8 (NOLOCK)
WHERE
pole_5 = @pole_5
/* Сколько найдено полей с персональными данными */
SELECT @row_count = Count (*) FROM ##table_8 WHERE pole_5 = @pole_5
if user_name() = @user_name INSERT INTO w_getdate ( num, spid, date_time,sec, descr) SELECT 29, @@spid, GetDate (), DATEDIFF(ms, Max (date_time), GetDate ()), 'найдено: ' + Convert (varchar, @row_count) FROM w_getdate with (nolock, index(isx_w_getdate_date_time_spid)) WHERE spid = @@spid
if @row_count > 0
BEGIN
/* очищаем таблицу в которую загружаются найденные данные для обезлички (если такие были найдены) */
DELETE FROM
##table_8
WHERE
pole_5 = @pole_5
END
/* Проставляем флаг occupied = 1 для забранных записей */
UPDATE
w_depersonalization_table_13
SET
occupied = 2 /* occupied = 2 для обработанных записей (обработка завершена ) */
WHERE
w_depersonalization_table_13.pole_5 = @pole_5
END
END
set @id_identity = @id_identity + 1
END
if user_name() = @user_name INSERT INTO w_getdate ( num, spid, date_time,sec, descr) SELECT 30, @@spid, GetDate (), DATEDIFF(ms, Max (date_time), GetDate ()), NULL FROM w_getdate with (nolock, index(isx_w_getdate_date_time_spid)) WHERE spid = @@spid
SELECT @occupied_13 = Count (*) FROM w_depersonalization_table_13 (nolock) WHERE occupied = 0
SELECT @occupied_14 = Count (*) FROM w_depersonalization_table_13 (nolock) WHERE occupied = 1
END
/*-- третий этап --*/
SELECT @occupied_13 = Count (*) FROM w_depersonalization_table_13 /*(TABLOCKX)*/ (NOLOCK) WHERE occupied <> 2 /* проверка на все ли записи обработаны? */
/* Ожидание когда закончат работу паралельные процедуры так как свободных записей уже не осталось, все в работе */
IF @occupied_13 > 0
BEGIN
/* цикл ожидания пока все записи не обработаются */
while @occupied_13 > 0
BEGIN
if user_name() = @user_name INSERT INTO w_getdate ( num, spid, date_time,sec, descr) SELECT 31, @@spid, GetDate (), DATEDIFF(ms, Max (date_time), GetDate ()), 'WAITFOR DELAY 00:01:00' FROM w_getdate with (nolock, index(isx_w_getdate_date_time_spid)) WHERE spid = @@spid
/* Задержка на указанное время WAITFOR DELAY '00:01:00' одна минута */
WAITFOR DELAY '00:01:00'
SELECT @occupied_13 = Count (*) FROM w_depersonalization_table_13 /*(TABLOCKX)*/ (NOLOCK) WHERE occupied <> 2 /* проверка на все ли записи обработаны? */
END
END
/* транзакция для блокировки w_depersonalization_table_10 */
BEGIN TRAN a5
SELECT @RowCount_table_10 = Count (*) FROM w_depersonalization_table_10 (TABLOCK) /*(TABLOCKX)*/
/* если записей нет, то создаем их */
IF @RowCount_table_10 = 0
BEGIN
/* в этой таблице лежат конечные UPDATE базы данных для обезличивания */
INSERT INTO w_depersonalization_table_10
(
pole_1, /* текст скрипта для обезличивания базы данных */
pole_5, /* "таблица + поле + имя" - идентификатор запроса */
occupied /* 1 - если занята другой процедурой или 2- запись уже отработана */
)
select distinct
'UPDATE ' + TABLE_SCHEMA + '.' + table_name +
' SET ' + column_name + ' = Convert ( xml, replace ( Convert (varchar (max), ' + COLUMN_NAME + '), ''' + name_1 + ''', ''' + name_2 + ''' ))
WHERE ' + column_name + '.exist(N''//*[contains(., ' + '"' + name_1 + '"'+ ')]'') = 1',
pole_5, /* "таблица + поле + имя" - идентификатор запроса */
0 as occupied
from
w_depersonalization_table_8
where
DATA_TYPE = 'xml' and
table_name not like '%dbo.w_%'
UNION
select distinct
'UPDATE ' + TABLE_SCHEMA + '.' + table_name +
' SET ' + column_name + ' = Convert ( ' + DATA_TYPE + ', replace ( Convert (varchar (max), ' + COLUMN_NAME + '), ''' + name_1 + ''', ''' + name_2 + ''' ))
WHERE ' + 'PATINDEX(''%' + name_1 + '%'', ' + COLUMN_NAME + ' ) > 0 and ' + COLUMN_NAME + ' IS NOT NULL',
pole_5, /* "таблица + поле + имя" - идентификатор запроса */
0 as occupied
from
w_depersonalization_table_8
where
DATA_TYPE in ('ntext', 'text') and
table_name not like '%dbo.w_%'
UNION
select distinct
'UPDATE ' + TABLE_SCHEMA + '.' + table_name +
' SET ' + column_name + ' = replace ( ' + COLUMN_NAME + ', ''' + name_1 + ''', ''' + name_2 + ''' )
WHERE ' + 'PATINDEX(''%' + name_1 + '%'', ' + COLUMN_NAME + ' ) > 0 and ' + COLUMN_NAME + ' IS NOT NULL',
pole_5, /* "таблица + поле + имя" - идентификатор запроса */
0 as occupied
from
w_depersonalization_table_8
where
/* здесь должны обрабатываться DATA_TYPE только 'nvarchar' и 'varchar' но если будут какие то еще типы, то они или могут создать скрипт с ошибой , но только так их можно отловить */
DATA_TYPE not in ('ntext', 'text', 'xml') and
table_name not like '%dbo.w_%'
END
/* конец транзакции для блокировки w_depersonalization_table_10 */
COMMIT TRAN a5
END
/******************************************************************************************************************************************************************/
/* Получаем количество записей которые можно обработать, но они должны быть в статусе occupied = 0 иначе считается что они обрабатываются паралельной процедурой */
SELECT @occupied_10 = Count (*) FROM w_depersonalization_table_10 (nolock) WHERE occupied = 0
SELECT @occupied_11 = Count (*) FROM w_depersonalization_table_10 (nolock) WHERE occupied = 1
/******************************************************************************************************************************************************************/
if user_name() = @user_name INSERT INTO w_getdate ( num, spid, date_time,sec, descr) SELECT 32, @@spid, GetDate (), DATEDIFF(ms, Max (date_time), GetDate ()), Convert (varchar, @occupied_10) + '/' + Convert (varchar, @occupied_11) + ' Цикл по реальным Ф.И.О ' FROM w_getdate with (nolock, index(isx_w_getdate_date_time_spid)) WHERE spid = @@spid
-- SELECT Count (*) FROM w_depersonalization_table_12 WHERE occupied = 0 /* occupied = 0 записи которые нужно обрабатывать, occupied = 1 в работе, occupied = 2 для обработанных записей (обработка завершена ) */
/******************************************************************/
/* цикл по 10000 записей из таблицы w_depersonalization_table_12 */
/* для того чтобы можно запустить паралельно несколько процедур */
/******************************************************************/
WHILE @occupied_10 > 0 or @occupied_11 > 0
BEGIN
if user_name() = @user_name INSERT INTO w_getdate ( num, spid, date_time,sec, descr)
SELECT 32, @@spid, GetDate (), DATEDIFF(ms, Max (date_time), GetDate ()), Convert (varchar, @occupied_10) + '/' + Convert (varchar, @occupied_10) + ' цикл по 10 000 записей Ф.И.О'
FROM w_getdate with (nolock, index(isx_w_getdate_date_time_spid)) WHERE spid = @@spid
/* таблица пересоздается чтоб обновилось поле id_identity */
if object_id('tempdb..#table_13',N'u') is not null drop table #table_10
create table #table_10
(
id_identity int identity,
pole_1 nvarchar (4000) null, /* текст скрипта для обезличивания базы данных */
pole_5 nvarchar (100) NULL, /* "таблица + поле + имя" - идентификатор запроса */
occupied int NULL /* 1 - если занята другой процедурой или 2- запись уже отработана */
)
if @occupied_10 > 0
BEGIN
BEGIN TRAN a6
/* получаем 1000 записей для обезличивания */
INSERT INTO #table_10
(
pole_1, /* текст скрипта для обезличивания базы данных */
pole_5, /* "таблица + поле + имя" - идентификатор запроса */
occupied /* 1 - если занята другой процедурой или 2- запись уже отработана */
)
SELECT top 1000
pole_1, /* текст скрипта для обезличивания базы данных */
pole_5, /* "таблица + поле + имя" - идентификатор запроса */
occupied /* 1 - если занята другой процедурой или 2- запись уже отработана */
FROM
w_depersonalization_table_10 (TABLOCKX)
WHERE
occupied = 0
/* Проставляем флаг occupied = 1 для забранных записей */
UPDATE
w_depersonalization_table_10
SET
occupied = 1 /* 1 для забранных записей */
FROM
#table_10 t10
WHERE
t10.pole_5 = w_depersonalization_table_10.pole_5
COMMIT TRAN a6
END
ELSE IF @occupied_11 > 0
BEGIN
/* получаем 1000 записей для обезличивания */
INSERT INTO #table_10
(
pole_1, /* текст скрипта для обезличивания базы данных */
pole_5, /* "таблица + поле + имя" - идентификатор запроса */
occupied /* 1 - если занята другой процедурой или 2- запись уже отработана */
)
SELECT top 1000
pole_1, /* текст скрипта для обезличивания базы данных */
pole_5, /* "таблица + поле + имя" - идентификатор запроса */
occupied /* 1 - если занята другой процедурой или 2- запись уже отработана */
FROM
w_depersonalization_table_10 (NOLOCK)
WHERE
occupied = 1
ORDER BY
SubString (Reverse (pole_5), CAST ((Rand () * 10) + 1 as int ), 3) /* сортировка случайным образом - 10 случайных вариантов */
END
/* начальные установки */
select @row_count = Count (*) from #table_10
-- set @row_count = 100 /* если нужно поставить огранчения для отладки */
set @id_identity = 1
set @pole_1 = ''
/* Цикл обезличивания таблиц всей базы */
while @id_identity <= @row_count
begin
select
@pole_1 = pole_1,
@pole_5 = pole_5
from
#table_10
where
id_identity = @id_identity
SELECT
@occupied_01 = Max (t10.occupied)
FROM
w_depersonalization_table_10 t10
WHERE
t10.pole_5 = @pole_5
IF NOT @occupied_01 = @occupied_02
BEGIN
if user_name() = @user_name INSERT INTO w_getdate ( num, spid, date_time,sec, descr) SELECT 33, @@spid, GetDate (), DATEDIFF(ms, Max (date_time), GetDate ()), Convert (varchar, @id_identity) + '/' + Convert (varchar, @row_count) + ' цикл обедличка по 10 000 записей' FROM w_getdate with (nolock, index(isx_w_getdate_date_time_spid)) WHERE spid = @@spid
/* обезличивание */
-- EXEC SP_EXECUTESQL @pole_1
/* проставляем флаг - запись обезличина */
UPDATE
w_depersonalization_table_10
SET
occupied = 2 /* 2- запись обезличина */
WHERE
pole_5 = @pole_5
END
if user_name() = @user_name INSERT INTO w_getdate ( num, spid, date_time,sec, descr) SELECT 34, @@spid, GetDate (), DATEDIFF(ms, Max (date_time), GetDate ()), @pole_5 FROM w_getdate with (nolock, index(isx_w_getdate_date_time_spid)) WHERE spid = @@spid
/* переходим к следующей записи */
set @id_identity = @id_identity + 1
end
SELECT @occupied_10 = Count (*) FROM w_depersonalization_table_10 (nolock) WHERE occupied = 0
SELECT @occupied_11 = Count (*) FROM w_depersonalization_table_10 (nolock) WHERE occupied = 1
END
SELECT @occupied_10 = Count (*) FROM w_depersonalization_table_10 /*(TABLOCKX)*/ (NOLOCK) WHERE occupied <> 2 /* проверка на все ли записи обработаны? */
/* Ожидание когда закончат работу паралельные процедуры так как свободных записей уже не осталось, все в работе */
IF @occupied_10 > 0
BEGIN
/* цикл ожидания пока все записи не обработаются */
while @occupied_10 > 0
BEGIN
if user_name() = @user_name INSERT INTO w_getdate ( num, spid, date_time,sec, descr) SELECT 35, @@spid, GetDate (), DATEDIFF(ms, Max (date_time), GetDate ()), 'WAITFOR DELAY 00:01:00' FROM w_getdate with (nolock, index(isx_w_getdate_date_time_spid)) WHERE spid = @@spid
/* Задержка на указанное время WAITFOR DELAY '00:01:00' одна минута */
WAITFOR DELAY '00:01:00'
SELECT @occupied_10 = Count (*) FROM w_depersonalization_table_13 /*(TABLOCKX)*/ (NOLOCK) WHERE occupied <> 2 /* проверка на все ли записи обработаны? */
END
END
BEGIN TRAN a7
SELECT @occupied_10 = Count (*) FROM w_depersonalization_table_10 (NOLOCK) /* (NOLOCK)*/ WHERE occupied = 2 /* проверка на все ли записи обработаны? */
SELECT @occupied_12 = Count (*) FROM w_depersonalization_table_10 (TABLOCKX) /* (NOLOCK)*/ WHERE occupied <> 2 /* проверка на все ли записи обработаны? */
IF @occupied_10 > 0 and @occupied_12 = 0
BEGIN
/* эти DELETE(ы) удаляют всю статичтику и ключи обезличивания, после этого удаления нельзя проанализировать как и скольк по времение работала процедура */
TRUNCATE TABLE w_depersonalization_pole_1 /* 2 137 862 записей, стационарная таблица в которой накапливаются 'таблици + поля + значения' которые были обработаны на 2-м этапе */
TRUNCATE TABLE w_depersonalization_pole_3 /* 2 212 970 записей, стационарная таблица в которой накапливаются 'таблици + поля + значения' которые были обработаны на 1-м этапе */
TRUNCATE TABLE w_depersonalization_table_8 /* 121 393 записей, стационарная таблица в которой накапливаются 'таблици + поля + значения' КОТОРЫЕ НУЖНО ОБЕЗЛИЧИТЬ */
TRUNCATE TABLE w_depersonalization_table_9 /* 7 377 записей, стационарная таблица в которой накапливаются 'таблици + поля + значения' КОТОРЫЕ НУЖНО ОБЕЗЛИЧИТЬ */
TRUNCATE TABLE w_depersonalization_table_10 /* 116 873 записей, стационарная таблица в которой накапливаются 'таблици + поля + значения' КОТОРЫЕ НУЖНО ОБЕЗЛИЧИТЬ */
TRUNCATE TABLE w_depersonalization_table_12 /* 1 150 записей, таблица сбора всех данных по всем таблицам полям и подменяемым данным */
TRUNCATE TABLE w_depersonalization_table_13 /* 2 118 060 записей, таблица сбора всех данных по всем таблицам полям и подменяемым данным */
if object_id('tempdb..##table_8',N'u') is not null drop table ##table_8
if object_id('tempdb..##table_10',N'u') is not null drop table ##table_10
TRUNCATE TABLE w_getdate /* 6 615 544 запией всех операций */
END
COMMIT TRAN a7
err:
drop table #table_01
drop table #table_02
drop table #table_12
drop table #table_name_1
drop table #table_pre_12
drop table #table_pre_13
drop table #table_pre_14
drop table #table_pre_15
drop table #table_03_VAR
-- drop table ##table_10 /* эту таблицу нужно удалить если добавляем в нее поля */
SELECT @occupied_13 = Count (*) FROM w_depersonalization_table_13 (nolock) WHERE occupied = 0
if user_name() = @user_name INSERT INTO w_getdate ( num, spid, date_time,sec, descr) SELECT 36, @@spid, GetDate (), DATEDIFF(ms, Max (date_time), GetDate ()), Convert (varchar, @occupied_13) + ' конечных запросов' FROM w_getdate with (nolock, index(isx_w_getdate_date_time_spid)) WHERE spid = @@spid
end