2013-08-06 7 views
5

Ho la tabella A con una chiave primaria sulla colonna ID e le tabelle B,C,D... con 1 o più colonne con relazioni di chiave esterna a A.ID.SQL come si esegue una query per le tabelle che fanno riferimento a un valore di chiave esterna specifico?

Come si scrive una query che mi mostra tutte le tabelle che contengono un valore specifico (ad es. 17) della chiave primaria?

Mi piacerebbe avere il codice sql generico che può assumere un nome di tabella e il valore della chiave primaria e visualizzare tutte le tabelle che fanno riferimento a quel valore specifico tramite una chiave esterna.

Il risultato dovrebbe essere un elenco di nomi tabella .

sto utilizzando MS SQL 2012.

+0

Quindi siete alla ricerca di un diagramma ERD? – Elias

+0

Che tipo di RDBMS? Le relazioni FK sono effettivamente definite nelle specifiche 'CREATE TABLE', o solo per valore? –

+0

Esistono relazioni FK esistenti. Non sto cercando un diagramma, sto cercando le tabelle che impedirebbero l'eliminazione delle righe nella tabella PK a causa di una relazione FK esistente. – CoderBrien

risposta

1

non un ideale, ma dovrebbe restituire ciò che è necessario (elenco delle tabelle):

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 
3

Si desidera guardare sys.foreignkeys. Vorrei iniziare da 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/

che invia qualcosa come

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 
+0

Per le chiavi primarie delle stringhe, come funzionerebbe la fuga? Diciamo che il tuo è una stored procedure che riceve @value come parametro e "sa" che è un varchar. – xanatos

+0

Se si dispone di chiavi primarie di stringa, o guids, si potrebbe fare in modo che lo sql tratti tutte le chiavi come stringhe e consenta di convertirlo implicitamente in inte, ecc. Ove appropriato. – podiluska

0

Si potrebbe achive che scrivendo qualche SQL. Inserisco un esempio ma è solo un mockup che mostra come potresti farlo.

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