SQL如何查询引用特定外键值的表?

时间:2013-08-06 14:38:06

标签: sql sql-server foreign-keys sql-server-2012

我的表A包含列ID上的主键和表B,C,D...,其中包含一列或多列与A.ID具有外键关系的列。

如何编写一个查询,向我显示包含主键特定值(例如17)的所有表?

我希望通用sql代码可以获取表名和主键值,并显示通过外键引用该特定值的所有表。

结果应该是表名列表

我正在使用MS SQL 2012。

4 个答案:

答案 0 :(得分:3)

您想查看sys.foreignkeys。我会从http://blog.sqlauthority.com/2009/02/26/sql-server-2008-find-relationship-of-foreign-key-and-primary-key-using-t-sql-find-tables-with-foreign-key-constraint-in-database/

开始

给出像

这样的东西
declare @value nvarchar(20) = '1'

SELECT 
    'select * from '

    + QUOTENAME( SCHEMA_NAME(f.SCHEMA_ID))
    + '.'
    + quotename( OBJECT_NAME(f.parent_object_id) )
    + ' where '
    + COL_NAME(fc.parent_object_id,fc.parent_column_id) 
    + ' = '
    + @value

FROM sys.foreign_keys AS f
 INNER JOIN sys.foreign_key_columns AS fc ON f.OBJECT_ID = fc.constraint_object_id
 INNER JOIN sys.objects AS o ON o.OBJECT_ID = fc.referenced_object_id

答案 1 :(得分:1)

不是理想的,但应该返回所需的内容(表格列表):

declare @tableName sysname, @value sql_variant

set @tableName = 'A'
set @value = 17

declare @sql nvarchar(max)

create table #Value (Value sql_variant)
insert into #Value values (@value)

create table #Tables (Name sysname, [Column] sysname)
create index IX_Tables_Name on #Tables (Name)

set @sql = 'declare @value sql_variant
select @value = Value from #Value

'
set @sql = @sql + replace((
select
    'insert into #Tables (Name, [Column])
select ''' + quotename(S.name) + '.' + quotename(T.name) + ''', ''' + quotename(FC.name) + '''
where exists (select 1 from ' + quotename(S.name) + '.' + quotename(T.name) + ' where ' + quotename(FC.name) + ' = @value)
'
from
    sys.columns C
    join sys.foreign_key_columns FKC on FKC.referenced_column_id = C.column_id and FKC.referenced_object_id = C.object_id
    join sys.columns FC on FC.object_id = FKC.parent_object_id and FC.column_id = FKC.parent_column_id
    join sys.tables T on T.object_id = FKC.parent_object_id
    join sys.schemas S on S.schema_id = T.schema_id
where
    C.object_id = object_id(@tableName)
    and C.name = 'ID'
order by S.name, T.name
for xml path('')), '
', CHAR(13))

--print @sql
exec(@sql)

select distinct Name
from #Tables
order by Name

drop table #Value
drop table #Tables

答案 2 :(得分:0)

你可以通过编写一些SQL来实现这一点。我发布了一个例子,但它只是一个模型,展示了你可以做到的方式。

CREATE TABLE tempTable
(
     TABLE_NAME varchar(255)
);

CREATE UNIQUE CLUSTERED INDEX Idx_tempTable ON tempTable(TABLE_NAME);

DECLARE @var2 nvarchar(max)

INSERT INTO tempTable 
       SELECT DISTINCT 
              TABLE_NAME 
       FROM INFORMATION_SCHEMA.COLUMNS 
       WHERE COLUMN_NAME LIKE '%COLUMN_NAME%'

/*FOREACH result of the tempTable you could find if the COLUMN_NAME of the result(table) has the value you want*/

SET @var2 = 'SELECT TABLE_NAME FROM ' + tempTableResult + ' WHERE COLUMN_NAME=VALUE'

exec(@var2)

DROP TABLE tempTable

答案 3 :(得分:0)

查询将返回一个表名列表,并在表名后附加数据(如果用于查找);如果子数据作为日常实例保存,则返回“(无日期)”。

此外,对于使用游标,也要道歉。我倾向于仅将它们用于诸如此类的特殊情况(即查找可能存在于100多个表中的少数奇数记录)。

就我而言,一个表引用了将近400个表(所有这些表都是作为“学习”系统的一部分自动生成的),并且根据保存的条目类型,数据可能会写入也可能不会写入这些表中。另一个问题是,这些数据中的某些也是按日期分类的,因此查询还必须检查每个表中是否带有外键的date列(幸运的是,在这些情况下,该列将始终命名为“ dt”)

从列出的近400个表中引用“资产”表。实际上,只有十几个表保存着我正在调查的特定条目的数据。所有表都将数据作为每日实例/细节保存。

引用表的名称为“资产”,并且Dynamic SQL包含一个子查询(将人类可读的名称转换为用作FK值的主键)。

光标查询来自Gishu,How can I list all foreign keys referencing a given table in SQL Server?

DECLARE @TableName varchar(255) DECLARE @FKeyColumn varchar(255) DECLARE @rowcount int DECLARE @sqlCMD NVARCHAR(500) DECLARE @dt NVARCHAR(10) = '2008-08-25' DECLARE @SymbolName NVARCHAR(9) = 'thingImLookingFor' DECLARE @byDate varchar(255) DECLARE TableCursor CURSOR FOR select t.name as TableWithForeignKey, c.name as ForeignKeyColumn from sys.foreign_key_columns as fk inner join sys.tables as t on fk.parent_object_id = t.object_id inner join sys.columns as c on fk.parent_object_id = c.object_id and fk.parent_column_id = c.column_id where fk.referenced_object_id = (select object_id from sys.tables where name = 'asset') OPEN TableCursor FETCH NEXT FROM TableCursor INTO @TableName, @FKeyColumn WHILE @@FETCH_STATUS = 0 BEGIN SET @sqlCMD = 'SELECT @rowcount=count(*) FROM ' + @TableName + ' WHERE ' + @FKeyColumn + '=(SELECT asset_id FROM asset WHERE primary_symbol=''' + @SymbolName + ''')' SET @byDate = ' (no date)' IF EXISTS(SELECT 1 FROM sys.columns WHERE sys.columns.name = N'dt' AND sys.columns.object_id = Object_ID(@TableName)) BEGIN SET @sqlCMD = @sqlCMD + ' AND dt=''' + @dt + '''' SET @byDate = ' (' + @dt + ')' END EXEC sp_executesql @sqlCMD, N'@rowcount int output', @rowcount output IF(@rowcount=1) PRINT(@TableName + @byDate) FETCH NEXT FROM TableCursor INTO @TableName, @FKeyColumn END CLOSE TableCursor; DEALLOCATE TableCursor;