Sql 如何查找指向不同表的孤立记录(需要参数化)?
表A与许多表B、C、D等有1-1关系。。。并由两列定义: ObjectTypenvarchar100//另一个表的名称 _Guiduniqueidentifier//另一个表中的记录ID 此外,所有表都包含一个IsDeletedbit列 问题是: 如何列出从A点到B、C、D中不存在的所有记录。。。还是已删除=1组的记录 以下操作无效,因为ObjectType必须是参数:Sql 如何查找指向不同表的孤立记录(需要参数化)?,sql,tsql,recursion,with-statement,Sql,Tsql,Recursion,With Statement,表A与许多表B、C、D等有1-1关系。。。并由两列定义: ObjectTypenvarchar100//另一个表的名称 _Guiduniqueidentifier//另一个表中的记录ID 此外,所有表都包含一个IsDeletedbit列 问题是: 如何列出从A点到B、C、D中不存在的所有记录。。。还是已删除=1组的记录 以下操作无效,因为ObjectType必须是参数: SELECT ObjectType, _Guid FROM A where NOT EXISTS (
SELECT ObjectType, _Guid FROM A
where
NOT EXISTS (
select * from ObjectType where oid = _Guid
)
以下操作也不起作用:
SELECT ObjectType, _Guid FROM A
where
NOT EXISTS (
exec('select * from '+ObjectType+' where oid =''' + _Guid + '''')
)
我缺少什么?查询必须具有静态已知的结构才能优化和执行。不能使用动态表名 连接所有可能的表
SELECT *
FROM A
LEFT JOIN B ON ...
LEFT JOIN C ON ...
LEFT JOIN D ON ...
WHERE
(B.IsDeleted IS NULL AND C.IsDeleted IS NULL AND D.IsDeleted IS NULL)
OR (B.IsDeleted = 1 OR C.IsDeleted = 1 OR D.IsDeleted = 1)
我想我没有得到完全正确的条件,因为我们还需要匹配ObjectType。我把它留给你修理。重要的想法是连接所有可能的表。下面这个糟糕的SQL似乎可以工作:
DECLARE @A_tmpTable TABLE (
idx smallint Primary Key IDENTITY(1,1)
, ObjectType nvarchar(200)
, _Guid nvarchar(100)
, Oid nvarchar(100)
)
DECLARE @orphanedA_tmpTable TABLE (
Oid nvarchar(100)
)
DECLARE @_objectType nvarchar(200)
DECLARE @_Guid nvarchar(100)
DECLARE @_oid nvarchar(100)
DECLARE @i int, @numrows int
DECLARE @found bit
-- populate temp table
INSERT @A_tmpTable SELECT ObjectType, _Guid, Oid FROM A WHERE IsDeleted = 0
--SELECT * FROM @A_tmpTable
-- foreach the @A_tmpTable
SET @i = 1;
SET @numrows = (SELECT COUNT(*) FROM @A_tmpTable)
--SELECT @i, @numrows
IF @numrows > 0
WHILE (@i <= @numrows)
BEGIN
SET @ObjectType = (SELECT TOP 1 ObjectType FROM @A_tmpTable WHERE idx = @i);
SET @_Guid = (SELECT TOP 1 _Guid FROM @A_tmpTable WHERE idx = @i);
SET @_oid = (SELECT TOP 1 Oid FROM @A_tmpTable WHERE idx = @i);
DECLARE @SQL nvarchar(max) = 'IF EXISTS (SELECT * FROM '+@ObjectType+' WHERE OID =''' + @_Guid + ''' AND IsDeleted = 0)
SET @found = 1;
ELSE
SET @found = 0;
';
-- check if table record exists and save the result in the @found variable
exec sp_executesql @SQL, N'@found bit out', @found out
IF @found = 0
INSERT INTO @orphanedA_tmpTable (Oid) VALUES (@_oid);
SET @i = @i + 1
END
SELECT * FROM A WHERE Oid IN (SELECT Oid FROM @orphanedA_tmpTable)