私が達成しようとしているのは次のとおりです。レコードを削除するときに、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
明らかに、insert exec をネストすることはできません。しかし、私はそれを行う他の方法を本当に見ていません。関数に変換しようとしましたが、動的クエリのような他の問題があります。
どんな助けでも大歓迎です。