回答
该脚本将显示所有具有引用该行的行你正在试图删除的表:
declare @RowId int = 1
declare @TableName sysname = 'ParentTable'
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) + ' where ' + col.name+ ' = ' + cast(@RowId as varchar) + ')'
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
execute (@Command)
假设外键不是复合。
选项1(检测出):
您执行Select Statement
,以确定是否有任何记录引用记录要被删除的 - 而且,如果你想,手动删除这些记录是请参考它。这也可以使用触发器完成,尽管我建议不要触发器,因为它们往往会让人们(以及你自己)感到惊讶。
选项2(自动化):
你可以看看Cascading Deletes,如果配置正确,会导致所有记录引用的记录要被删除的也被删除。
当使用级联删除(意译由Joel Coehoorn书面文本)
- 级联删除可能是有意义的,当关系的语义可以包括一个“是的一部分”的描述。示例:网络订单,网络订单行项目
- 如果您保留历史记录或使用软删除(只设置删除位列),则不应使用级联删除
- 如果您设置了自己的级联,级联可能会使您陷入麻烦外键错误。
- 在彻底理解之前使用级联并不明智。但是,这是一个有用的功能,因此值得花时间理解。
这是关于stackoverflow的Cascading Deletes的一个很好的讨论。
当您尝试使用FK删除记录时,SQL Server会引发异常。 IS SQL Server内部执行SELECT语句以知道是否有任何记录引用它? – Yeonho 2011-06-10 04:42:15
SQL以各种方式跟踪关系和约束,其中一些方法类似于select语句。不过,我认为它更像垃圾收集。 “没有什么东西可以再引用这块内存了,所以我可以删除它” – 2011-06-10 04:44:08
没有人提到这个问题,但仅仅是为了记录我用了很多的程序
sp_helpconstraint 'dbo.mytable'
,以便找到所有dbo.mytable相关的约束,并表参考dbo.mytable。 我觉得它非常有用和方便。
我改进了Alex Aza的解决方案。
我使用softdelete,所以有必要在条件“where”中添加一个“delete”列。 而且我在TSQL中做了一个函数,它发现当表代表在NHibernate中继承的对象时,PK是父表中的FK。
如下:
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功能:
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触发器(的
- 1. 如何知道是否使用mysqli dbdriver删除行
- 2. 如何知道我的存储过程是否在MS SQL Server中被删除?
- 3. 如何知道行值sql server asp.net?
- 4. 如何在SQL Server中删除多行
- 5. 知道AsyncTask是否正在运行
- 6. 如何知道Sql Server中的表中是否没有值
- 7. 如何知道表中的一行是否在删除之前在其他表中被引用?
- 8. 如何知道行是否已更新
- 9. 如何知道是否所有单元格使用MGSwipeTableCell删除
- 10. 我需要知道一个进程是否正在运行
- 11. 如何知道正在运行的后台进程是否为
- 12. 如何知道正在运行的脚本是否死亡?
- 13. Android:如何知道Commonsware的WakefulIntentService是否正在运行?
- 14. 执行cursor.execute()时,如何知道查询是否正确执行?
- 15. 如何知道行sql server中有任何更改?
- 16. 如何知道是否有任何应用程序正在运行?
- 17. SQL Server:检查表列是否存在并删除行
- 18. 如何知道要实施哪些SQL Server 2005索引建议?
- 19. 如何知道某个进程是否正在运行?
- 20. 如何知道批处理作业是否正在运行
- 21. 如何知道cgi脚本是否正在执行?
- 22. 如何知道hbase服务器是否正在运行
- 23. 如何知道WildFly是否正在运行Web Profile或Full Profile?
- 24. SyncAdapter运行动画 - 如何知道SyncAdapter是否正在同步
- 25. 如何知道关机是否正在进行?
- 26. java如何知道你是否正在运行javaw.exe与java.exe
- 27. 如何知道AnimationTimer是否正在运行?
- 28. 如何知道Spork是否正在运行
- 29. 如何知道TaskTracker是否正在运行Java代码?
- 30. 如何知道bash脚本是否正在运行nohup?
可能重复http://stackoverflow.com/questions/6244077/help-on-sql -server-trigger) – gbn 2011-06-10 04:46:34
我的目标不是导致级联删除,而是事先知道记录是否可删除。如果它不可删除,则会通知用户它不可删除。 – Yeonho 2011-06-10 06:07:20
我知道你已经标记了一个答案,但是如果这是一个多用户系统,最好的答案可能是试图删除并应对发生的错误 - 否则在这里可能有各种竞争条件,除非您将所有内容都包装在高度隔离的事务中。 – 2011-06-10 06:43:59