我想要达到的目标如下。当我删除一条记录时,我想检查是否有任何 FK 关系并且它需要是递归的。这样,我可以显示与您要删除的记录相关的所有记录的列表。
所以嵌套链接的一个小例子项目 1 -> 阶段 1 -> 块 1 -> ..
因此,当我尝试删除项目 1 时,我需要先获取需要删除的项目列表:阶段 1 块 1 ....
我想用一个带有 ID 和表名(格式 [chema].[tablename])并找到所有这些链接记录的存储过程来做到这一点。
我遇到的问题是递归部分。到目前为止,这是我的代码:
ALTER PROCEDURE core.usp_CanBeDeleted
@entityId int,
@entityName nvarchar(250)
AS
BEGIN
DECLARE @NumberRecords int, @RowCount int
DECLARE @childId int
DECLARE @query nvarchar(max)
DECLARE @eName nvarchar(250) , @keyName nvarchar(250)
DECLARE @columnName nvarchar(250)
DECLARE @keys TABLE(
RowID int IDENTITY(1, 1),
name nvarchar(250),
entityName nvarchar(250),
columnName nvarchar(250)
)
if not exists (select * from sysobjects where name='partialResults' and xtype='U')
BEGIN
CREATE TABLE partialResults(
RowID int IDENTITY(1, 1),
id int,
parentId int,
name nvarchar(250),
FK_name nvarchar(250)
)
END
DECLARE @recusiveResults TABLE(
RowID int,
id int,
parentId int,
name nvarchar(250),
FK_name nvarchar(250)
)
DECLARE @results TABLE(
RowID int,
id int,
parentId int,
name nvarchar(250),
FK_name nvarchar(250)
)
SET @RowCount = 1
-- get all FK's of the entity
INSERT INTO @keys
SELECT name, '[' + OBJECT_SCHEMA_NAME(parent_object_id) + '].[' + OBJECT_NAME(parent_object_id)+ ']',cu.column_name
from sys.foreign_keys k
INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE CU
ON k.name = CU.CONSTRAINT_NAME
where k.referenced_object_id = OBJECT_ID(@entityName)
-- set variable to number of records in temp table
SET @NumberRecords = @@ROWCOUNT
-- loop through the FK's an get all linked entities
WHILE(@RowCount <= @NumberRecords)
BEGIN
SELECT @keyName = name, @eName = entityName, @columnName = columnName
FROM @keys
WHERE RowId = @RowCount
-- get all FK information
SET @query = 'INSERT INTO partialResults(FK_name, name, id, parentId)'
+ ' SELECT ''' + @keyName + ''','''+ @eName + ''',' + 'id,' + cast(@entityId as varchar(25)) + ' as parentid'
+ ' FROM ' +@eName
+ ' WHERE id in '
+ ' (SELECT ' + @columnName
+ ' FROM ' + @entityName
+ ' WHERE id = ' + cast(@entityId as varchar(25))
+ ' )'
--print @query
EXEC (@query)
SET @RowCount = @RowCount + 1
END
-- rest number of records
SET @RowCount = 1
SELECT @NumberRecords = count(id)
FROM partialResults
-- save partialResults
INSERT INTO @results--(FK_name, name, id, parentId)
SELECT *--FK_name, name, id, parentId
FROM partialResults
DELETE FROM partialResults
WHILE(@RowCount <= @NumberRecords)
BEGIN
-- select next row
SELECT @childId = id, @eName = name
FROM @results
WHERE RowId = @RowCount
INSERT INTO @recusiveResults
EXEC core.usp_CanBeDeleted @childId, @eName
SET @RowCount = @RowCount + 1
END
INSERT INTO @results
SELECT *
FROM @recusiveResults
if exists (select * from sysobjects where name='partialResults' and xtype='U')
BEGIN
-- remove temp tables
DROP TABLE partialResults
END
-- return results
SELECT *
FROM @results
END
GO
问题出在这里:
INSERT INTO @recusiveResults
EXEC core.usp_CanBeDeleted @childId, @eName
显然你不能嵌套一个插入执行程序。但是我真的没有看到任何其他方式来做到这一点。我尝试将其转换为函数,但还有其他问题,例如动态查询。
任何帮助将不胜感激。