Alex Aza'nın çözümünü geliştirdim.
Ben softdelete kullanıyorum, bu yüzden "where" durumunda bir "delete" sütunu eklemek gerekiyor. Ve daha fazlası TSQL'de, tablo, NHibernate'de miras alınan nesneyi temsil ettiğinde ve PK'nin ana tablodan FK olduğunu keşfettiğimde bir işlev yaptım.
Takip:
declare @RowId int = 4
declare @TableName sysname = 'TABLE'
declare @Command varchar(max)
select @Command = isnull(@Command + ' union all ', '') + 'select ''' + object_name(parent_object_id) +
''' where exists(select * from ' + object_name(parent_object_id) +
CASE
WHEN EXISTS(select object_name(object_id) from sys.columns col where name = 'deleted' and object_id = parent_object_id)
THEN ' where ' + col.name+ ' = ' + cast(@RowId as varchar) +' and deleted = 0 '
when dbo.ParentIdFromTable(object_name(parent_object_id)) <> ''
then ' inner join ' + dbo.ParentIdFromTable(object_name(parent_object_id)) + ' on id = ' + dbo.PrimaryKey(object_name(parent_object_id))
+' where ' + col.name+ ' = ' + cast(@RowId as varchar) +' and deleted = 0 '
else
' where ' + col.name+ ' = ' + cast(@RowId as varchar)
END
+ ')'
from sys.foreign_key_columns fkc
join sys.columns col on
fkc.parent_object_id = col.object_id and fkc.parent_column_id = col.column_id
where object_name(referenced_object_id) = @TableName
PRINT @Command
execute (@Command)
Depedencies Fonksiyonlar:
CREATE FUNCTION dbo.ParentIdFromTable(@Table varchar(255))
RETURNS varchar(255)
AS
BEGIN
declare @tableParent varchar(255) = ''
if exists(select pk.TABLE_NAME, pk.COLUMN_NAME, col.name, object_name(referenced_object_id) Referenced, object_name(parent_object_id) as Parent
from sys.columns col
inner join sys.foreign_key_columns fkc on
fkc.parent_object_id = col.object_id and fkc.parent_column_id = col.column_id
inner join INFORMATION_SCHEMA.KEY_COLUMN_USAGE pk on
pk.TABLE_NAME = object_name(object_id) and pk.COLUMN_NAME = col.name
WHERE OBJECTPROPERTY(OBJECT_ID(constraint_name), 'IsPrimaryKey') = 1
AND table_name = @table)
begin
while exists(select *
from sys.columns col
inner join sys.foreign_key_columns fkc on
fkc.parent_object_id = col.object_id and fkc.parent_column_id = col.column_id
inner join INFORMATION_SCHEMA.KEY_COLUMN_USAGE pk on
pk.TABLE_NAME = object_name(object_id) and pk.COLUMN_NAME = col.name
WHERE OBJECTPROPERTY(OBJECT_ID(constraint_name), 'IsPrimaryKey') = 1 AND table_name = @table)
begin
-- Descobrir o parent, column
select @tableParent = object_name(referenced_object_id)
from sys.columns col
inner join sys.foreign_key_columns fkc on
fkc.parent_object_id = col.object_id and fkc.parent_column_id = col.column_id
inner join INFORMATION_SCHEMA.KEY_COLUMN_USAGE pk on
pk.TABLE_NAME = object_name(object_id) and pk.COLUMN_NAME = col.name
WHERE OBJECTPROPERTY(OBJECT_ID(constraint_name), 'IsPrimaryKey') = 1
AND table_name = @table
--print @tableParent
set @table = @tableParent
end
end
return @tableParent;
END;
GO
CREATE FUNCTION dbo.PrimaryKey(@Table varchar(255))
RETURNS varchar(255)
AS
BEGIN
declare @columnName varchar(255) = ''
-- Descobrir o parent, column
select @columnName = COLUMN_NAME
from INFORMATION_SCHEMA.KEY_COLUMN_USAGE
WHERE OBJECTPROPERTY(OBJECT_ID(constraint_name), 'IsPrimaryKey') = 1
AND table_name = @Table
return @columnName
end;
[SQL Server tetiğe Yardım] (içinde
olası yinelenen http://stackoverflow.com/questions/6244077/help-on-sql -server-tetikleyici – gbn
Amacım bir basamaklı silme neden değil, kayıt silinebilir ise önceden bilmek. Eğer silinemez değilse, kullanıcı silinemez olmadığını bildirecektir. – Yeonho
Zaten bir cevabı işaretlediğinizi biliyorum, ancak bu çok kullanıcılı bir sistemse, en iyi cevap sadece silme girişiminde bulunmak ve meydana gelen bir hatayla başa çıkmak olabilir - aksi takdirde, burada her türlü yarış koşulları mümkündür. Her şeyi yüksek izolasyonlu bir işlemde sarın. –