我有一个表,其主键“ID”字段在许多其他表中用作外键。
如何在其他表中检查此表中的特定记录(例如第一条记录“ID = 1”)?
如果在某个其他表中使用了特定记录,我不想对该行执行任何操作。
答案 0 :(得分:2)
从表面上看,你的问题没有意义。我们来看看一些数据。
users
user_id user_email
--
1 abc@def.com
2 def@hij.com
user_downloads
user_id filename downloaded_starting
1 123.pdf 2013-05-29 08:00:13
1 234.pdf 2013-05-29 08:05:27
1 345.pdf 2013-05-29 08:10:33
user_downloads上有一个外键:foreign key (user_id) references users (user_id)
。
只要您不将该外键声明为ON DELETE CASCADE
,则无法删除用户中的相应行。您不必检查其他表中是否存在行而您不应该。在一个大系统中,这可能意味着要检查数百个表。
如果未将外键声明为ON UPDATE CASCADE
,则如果user_id被任何其他表引用,则无法更新该user_id。所以,再次,你不必检查。
如果您使用电子邮件地址作为外键引用的目标,则请再次使用ON DELETE CASCADE
并且不要使用ON UPDATE CASCADE
。不要使用这些声明,也不必检查。如果不使用电子邮件地址作为外键引用的目标,则阻止对其进行更新是没有意义的。
因此,如果您正确构建表格,则无需检查任何内容。
答案 1 :(得分:1)
非常直率的解决方案:
我说这是直率的:)
答案 2 :(得分:1)
您可以使用触发器回滚任何为
提供true的事务 "where exists( select * from otherTable Where fk = id union select * from anotherTable Where fk = id union etc)
如果你在每个以fk开头的表上都有任何索引,那么它不会太沉重(无论如何你应该具有一般速度),SQL只会检查索引的id。即检查每个表的单个读数。
答案 3 :(得分:1)
如果您不想使用试错法,请使用以下命令:
DECLARE @schema NVARCHAR(20)
DECLARE @table NVARCHAR(50)
DECLARE @column NVARCHAR(50)
DECLARE @SQL NVARCHAR(1000)
DECLARE @ID INT
DECLARE @exists INT
DECLARE @x NVARCHAR(100)
SELECT @x = '@exists int output', @ID = 1, @schema = 'dbo', @table = 'Gebruiker', @column = 'GebruikerHasGebruiker_id'
SELECT @SQL = 'SELECT @exists = 1 WHERE EXISTS( ' + STUFF((
SELECT ' UNION ALL SELECT ' + U2.COLUMN_NAME + ' AS ID FROM ' + U2.TABLE_SCHEMA + '.' + U2.TABLE_NAME + ' WHERE ' + U2.COLUMN_NAME + ' = ' + cast(@id as VARCHAR(10))
FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS R INNER JOIN INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE U ON R.UNIQUE_CONSTRAINT_NAME = U.CONSTRAINT_NAME
INNER JOIN INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE U2 ON R.CONSTRAINT_NAME = U2.CONSTRAINT_NAME
WHERE U.TABLE_SCHEMA = @schema
AND U.TABLE_NAME = @table
AND U.COLUMN_NAME = @column
FOR XML PATH('')
),1,11, '') + ')'
EXEC sp_executesql @SQL, @x, @exists = @exists OUTPUT
IF 1 <> @exists
BEGIN
-- do you stuff here
END
但是在99%的情况下你可以做到这一点,这太过分了。如果您已经知道FK并且只是创建查询,则会更快。
编辑: 一点解释。此动态SQL在信息模式中查看与其他表的所有关系。它使用该信息创建查询以检查您的ID是否存在于该表中。使用UNION,它会添加所有结果,如果找到任何结果,则返回1。只要不检查多列上的FK,这可以用于任何列的任何数据库。
答案 4 :(得分:0)
使用此解决方案,您无需对所有引用的表进行硬编码。
use tempdb
go
/* provide test data*/
if OBJECT_ID(N't2') is not null
drop table t2
if OBJECT_ID(N't1') is not null
drop table t1
create table t1(i int not null primary key)
create table t2(i int not null, constraint fk_t1_t2 foreign key (i) references t1(i))
go
insert into t1 values(1),(2)
insert into t2 values(1)
/* checking if the primary key value referenced in other tables */
declare @forCheck int=1 /* id to be checked if it referenced in other tables */
declare @isReferenced bit=0
begin tran
begin try
delete from t1 where i=@forCheck
end try
begin catch
set @isReferenced=1
end catch
rollback
select @isReferenced
答案 5 :(得分:0)
方法应该是收集所有依赖对象并查询它们以检查父表记录是否存在。
我使用一个返回依赖对象的过程。 我无法发布该程序的原因是超过限定数量30000个字符发布它是48237个字符。让我知道你的邮件ID我将把程序发给你。
迭代过程的结果,检查是否有任何依赖列保存主表数据。