Я пытаюсь найти ссылочные объекты, но из-за плохих ссылок на сервер есть некоторые ошибки с sys.dm_sql_referenced_entities ().
Я использую try catch для обработки ошибок, но это приводит к тому, что, если повреждена только одна ссылка, другие не отображаются, и я получаю 0 строк
(затронуто 0 строк)!
На SQL2016 проблем нет, и я вижу другие строки.
Как я могу получить другие строки?
BEGIN TRY
INSERT INTO @refTable
SELECT
@nestLevel,
@referencingEntityFullName AS referencing_object_name,
OBJECT_ID(@referencingEntityFullName) AS referencing_object_id,
r.referencing_minor_id, --if > 0 then computed column
r.referenced_server_name,
r.referenced_database_name,
r.referenced_schema_name,
r.referenced_entity_name,
r.referenced_minor_name,
r.is_caller_dependent, --warning on these!
r.is_ambiguous--,
--r.is_selected,
--r.is_updated,
--r.is_select_all,
--r.is_insert_all,
--r.is_all_columns_found
FROM
sys.dm_sql_referenced_entities(@referencingEntityFullName, 'OBJECT') r
WHERE
r.referenced_entity_name = @currentReferencedEntityName
AND
(
@filterColumns = 0
OR
r.referenced_minor_name IN (SELECT ColumnName FROM @piiTablesAndColumns ptac WHERE ptac.TableName = @currentReferencedEntityFullName)
OR
r.referenced_minor_name IS NULL --for SELECT *; check if it really works this way
)
END TRY
BEGIN CATCH
print('catched!')
END CATCH
Весь код:
DECLARE @piiTablesAndColumnsTmp TABLE(TableName NVARCHAR(517), ColumnNames NVARCHAR(MAX))
INSERT INTO @piiTablesAndColumnsTmp VALUES
('dbo.stgCustomers', 'Email, PasswordHash, DateOfBirth, Title, Forename, MiddleInitial, Surname, AddressLine1, AddressLine2, AddressLine3, AddressLine4, AddressLine5, Postcode'),
('dbo.tblCustomersA', 'Email, PasswordHash, DateOfBirth, Title, Forename, MiddleInitial, Surname, AddressLine1, AddressLine2, AddressLine3, AddressLine4, AddressLine5, Postcode'),
('dbo.tblCustomersB', 'Email, PasswordHash, DateOfBirth, Title, Forename, MiddleInitial, Surname, AddressLine1, AddressLine2, AddressLine3, AddressLine4, AddressLine5, Postcode'),
('dbo.tblVIPSaleCustomers', 'MobileNumber, DateFirstLoggedIn'),
('dbo.tblVIPSaleCustomersArchive', 'MobileNumber, DateFirstLoggedIn'),
('dbo.tblOrders', 'AccountNo, PlacedDate, OrderDeliveryInstructionsID, OrderGiftMessage, OrderDeliveryRequestedTo')
--Filter root object columns if 1.
DECLARE @filterColumnsOption BIT = 1
/***
DO NOT MODIFY BELOW HERE
**/
DECLARE @piiTablesAndColumns TABLE(TableName NVARCHAR(517), ColumnName NVARCHAR(128))
INSERT INTO @piiTablesAndColumns
SELECT
piiTmp2.TableName,
RTRIM(LTRIM( ss.data))
FROM
@piiTablesAndColumnsTmp piiTmp2
CROSS APPLY (
SELECT
Split.a.value('.', 'VARCHAR(100)') AS Data
FROM
(
SELECT TableName,
CAST ('<M>' + REPLACE(ColumnNames, ',', '</M><M>') + '</M>' AS XML) AS Data
FROM @piiTablesAndColumnsTmp piiTmp
) AS A CROSS APPLY Data.nodes ('/M') AS Split(a) where a.TableName=piiTmp2.TableName) ss
--SELECT * FROM @piiTablesAndColumns order by 1,2
DECLARE @refTable TABLE
(
nest_level INT,
referencing_object_name NVARCHAR(1000),
referencing_object_id INT,
referencing_minor_id INT,
referenced_server_name NVARCHAR(1000),
referenced_database_name NVARCHAR(1000),
referenced_schema_name NVARCHAR(1000),
referenced_entity_name NVARCHAR(1000),
referenced_minor_name NVARCHAR(1000),
is_caller_dependent BIT,
is_ambiguous BIT--,
--is_selected BIT,
--is_updated BIT,
--is_select_all BIT,
--is_insert_all BIT,
--is_all_columns_found BIT
);
DECLARE tableCur CURSOR FOR
SELECT DISTINCT ptac.TableName
FROM @piiTablesAndColumns ptac
DECLARE @currentReferencedEntityFullName NVARCHAR(517)
OPEN tableCur
FETCH NEXT FROM tableCur INTO @currentReferencedEntityFullName
/******* Repeats for every table */
WHILE @@FETCH_STATUS = 0
BEGIN
print 'Processing TABLE: ' + @currentReferencedEntityFullName
DECLARE @referencingEntities TABLE(SchemaName NVARCHAR(128), EntityName NVARCHAR(517))
DECLARE @processedReferencedEntities TABLE (EntityName NVARCHAR(1000))
DECLARE @currentReferencedEntityName NVARCHAR(517)
DECLARE @currentReferencedEntityId INT
DECLARE @nestLevel INT = 0
DECLARE @filterColumns BIT = @filterColumnsOption
Start:
SET @currentReferencedEntityId = OBJECT_ID(@currentReferencedEntityFullName)
SET @currentReferencedEntityName = OBJECT_NAME(@currentReferencedEntityId)
print 'Processing root: ' + @currentReferencedEntityName
DELETE FROM @referencingEntities
INSERT INTO @referencingEntities
SELECT
r.referencing_schema_name,
r.referencing_entity_name
FROM
sys.dm_sql_referencing_entities(@currentReferencedEntityFullName, 'OBJECT') r
--where
--referencing_entity_name not in ('usp_ImportCustomerData','usp_UpdateCustomerBulkNearestStore','usp_ArchiveVipData'/*,'usp_UpdateCustomerVipSaleDeliveryStore'*/)
DECLARE cRt CURSOR FOR SELECT SchemaName, EntityName FROM @referencingEntities
OPEN cRt
DECLARE @rtSchemaName NVARCHAR(128)
DECLARE @rtEntityName NVARCHAR(517)
FETCH NEXT FROM cRt INTO @rtSchemaName, @rtEntityName
WHILE @@FETCH_STATUS = 0
BEGIN
DECLARE @referencingEntityFullName NVARCHAR(1000) = @rtSchemaName + '.' + @rtEntityName
BEGIN TRY
INSERT INTO @refTable
SELECT
@nestLevel,
@referencingEntityFullName AS referencing_object_name,
OBJECT_ID(@referencingEntityFullName) AS referencing_object_id,
r.referencing_minor_id, --if > 0 then computed column
r.referenced_server_name,
r.referenced_database_name,
r.referenced_schema_name,
r.referenced_entity_name,
r.referenced_minor_name,
r.is_caller_dependent, --warning on these!
r.is_ambiguous--,
--r.is_selected,
--r.is_updated,
--r.is_select_all,
--r.is_insert_all,
--r.is_all_columns_found
FROM
sys.dm_sql_referenced_entities(@referencingEntityFullName, 'OBJECT') r
WHERE
r.referenced_entity_name = @currentReferencedEntityName
AND
(
@filterColumns = 0
OR
r.referenced_minor_name IN (SELECT ColumnName FROM @piiTablesAndColumns ptac WHERE ptac.TableName = @currentReferencedEntityFullName)
OR
r.referenced_minor_name IS NULL --for SELECT *; check if it really works this way
)
END TRY
BEGIN CATCH
print('catched!' + @referencingEntityFullName + CAST(OBJECT_ID(@referencingEntityFullName) AS VARCHAR(100)))
raiseerror
END CATCH
FETCH NEXT FROM cRt INTO @rtSchemaName, @rtEntityName
END
CLOSE cRt
DEALLOCATE cRt
--repeat for all the referencing objects to get all the data processing paths
INSERT INTO @processedReferencedEntities VALUES ( @currentReferencedEntityFullName )
SET @filterColumns = 0
SET @currentReferencedEntityFullName = NULL
SELECT TOP 1
@currentReferencedEntityFullName = rt.referencing_object_name,
@nestLevel = rt.nest_level + 1
FROM
@refTable rt
WHERE
rt.referencing_object_name NOT IN (SELECT EntityName FROM @processedReferencedEntities)
IF @currentReferencedEntityFullName IS NOT NULL
GOTO Start
FETCH NEXT FROM tableCur INTO @currentReferencedEntityFullName
END
CLOSE tableCur
DEALLOCATE tableCur
SELECT * FROM @refTable r1
where not exists (select 1 from @refTable r2 where r2.referenced_minor_name is not null and r2.referencing_object_id=r1.referencing_object_id)
ORDER BY referencing_object_name, referenced_entity_name