我有A
一个在列上具有主键的ID
表B,C,D...
,以及具有 1 个或多个与外键关系的列的表A.ID
。
如何编写一个查询来显示所有包含17
主键特定值(例如 )的表?
我想要一个通用的 sql 代码,它可以采用表名和主键值并显示通过外键引用该特定值的所有表。
结果应该是一个表名列表。
我正在使用 MS SQL 2012。
我有A
一个在列上具有主键的ID
表B,C,D...
,以及具有 1 个或多个与外键关系的列的表A.ID
。
如何编写一个查询来显示所有包含17
主键特定值(例如 )的表?
我想要一个通用的 sql 代码,它可以采用表名和主键值并显示通过外键引用该特定值的所有表。
结果应该是一个表名列表。
我正在使用 MS SQL 2012。
你想看看sys.foreignkeys
。我将从http://blog.sqlauthority.com/2009/02/26/sql-server-2008-find-relationship-of-foreign-key-and-primary-key-using-t-sql-find-开始数据库中带有外键约束的表/
给予类似的东西
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
不是一个理想的,但应该返回所需的(表格列表):
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
您可以通过编写一些 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
该查询将返回一个表名列表并将这些名称附加到数据中(如果用于查找),如果子数据作为每日实例保存,则返回“(无日期)”。
此外,为使用光标提前道歉。我倾向于仅将它们用于特殊情况,例如这种情况(即查找可能存在于 100 个表中的少数奇数记录)。
在我的例子中,一个表引用了不到 400 个表(所有这些表都是作为“学习”系统的一部分自动生成的),并且根据保存的条目类型,数据可能会或可能不会写入这些表中。进一步的转折是其中一些数据也是按日期的,因此查询还必须使用外键检查每个表中是否存在日期列(幸运的是,在这些情况下,该列将始终命名为“dt”) .
从列为引用“资产”表的近 400 个表中。只有十几个表实际上保存了我正在调查的特定条目的数据。所有表格都将数据保存为每日实例/详细信息。
引用表的名称是“资产”,动态 SQL 包含一个子查询(将人类可读的名称转换为主键,用作 FK 值)。
游标查询来自 Gishu 在如何列出引用 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;