2011-09-30 23 views
8

Si tengo una tabla, Tabla A:¿Cómo encontrar dependencias de clave externa de una fila específica?

Id 
1 
2 
3 
... 

y otros dos tablas:

TableB:

Id, TableAId 
1 1 
2 1 

TableC:

Id, TableAId 
1, 1 
2, 2 

Dónde TableAId es una relación FK con TableA.Id.

¿Cómo puedo determinar que TableA, Id 1, tiene tres filas apuntando hacia él? Y esa TableA, Id 2 tiene una fila que lo señala? Y más específicamente, ¿cómo identifico cuáles son esas filas? (Su nombre de la tabla y Id)

+0

Su objetivo no es del todo clara. ¿Desea encontrar los metadatos para identificar naves de realimentación de claves foráneas entre las tablas, o quiere las consultas TSql para encontrar los datos dado que ya conoce las relaciones de claves foráneas? – user957902

+0

No me interesan los metadatos. En mi ejemplo, muestro cómo me interesa determinar las tablas y filas específicas que tienen dependencias en otra fila específica. Me gustaría obtener esa información sin escribir una declaración de selección (potencialmente) enorme que une todas las tablas posibles junto con la tabla de objetivos. –

Respuesta

15

Puede usar las vistas INFORMATION_SCHEMA para generar declaraciones seleccionadas para mostrar las filas en cuestión. Solo he probado esto en las tablas proporcionadas en la pregunta, pero podría ampliarse para que funcione en los casos en que las claves sean columnas múltiples.

declare @table_schema nvarchar(50) = 'dbo', 
     @table_name nvarchar(50) = 'TableA', 
     @id int = 1 

select fk_col.TABLE_SCHEMA, fk_col.TABLE_NAME, fk_col.COLUMN_NAME, 
    'select * from ' + fk_col.TABLE_SCHEMA + '.' + fk_col.TABLE_NAME + ' t1 ' 
     + ' inner join ' + @table_schema + '.' + @table_name + ' t2 ' 
     + ' on t1.' + fk_col.COLUMN_NAME + ' = t2.' + pk_col.COLUMN_NAME 
     + ' where t2.' + pk_col.COLUMN_NAME + ' = ' + cast(@id as nvarchar) 

from INFORMATION_SCHEMA.TABLE_CONSTRAINTS pk 

    join INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE pk_col 
     on pk.CONSTRAINT_SCHEMA = pk_col.CONSTRAINT_SCHEMA 
     and pk.CONSTRAINT_NAME = pk_col.CONSTRAINT_NAME 

    join INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS fk 
     on pk.CONSTRAINT_SCHEMA = fk.UNIQUE_CONSTRAINT_SCHEMA 
     and pk.CONSTRAINT_NAME = fk.UNIQUE_CONSTRAINT_NAME 

    join INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE fk_col 
     on fk_col.CONSTRAINT_SCHEMA = fk.CONSTRAINT_SCHEMA 
     and fk_col.CONSTRAINT_NAME = fk.CONSTRAINT_NAME 

where pk.TABLE_SCHEMA = @table_schema 
    and pk.TABLE_NAME = @table_name 
    and pk.CONSTRAINT_TYPE = 'PRIMARY KEY' 

Las instrucciones select generadas:

select * from dbo.TableB t1 inner join dbo.TableA t2 on t1.TableAId = t2.Id where t2.Id = 1 
select * from dbo.TableC t1 inner join dbo.TableA t2 on t1.TableAId = t2.Id where t2.Id = 1 

y los resultados de la consulta:

Id   TableAId Id 
----------- ----------- ----------- 
1   1   1 
2   1   1 

Id   TableAId Id 
----------- ----------- ----------- 
1   1   1 
+0

gran respuesta, thx :) – mrzepa

+0

Hola, por favor podrías darme el código Mysql equivalente. –

2

Con el fin de averiguar qué existen relaciones FK, hay que fijarse en los sys vistas de catálogo de SQL Server - algo así como:

SELECT * 
FROM sys.foreign_keys 
WHERE referenced_object_id = OBJECT_ID('TableA') 

Esto mostrará toda clave externa relaciones que existen a TableA.

Una vez que tenga esa información, es un JOIN bastante simple entre TableA y cualquiera de esas otras tablas involucradas.

Actualización: una vez que sepa que p. Ej. TableB y TableC referencia a su TableA, se pueden encontrar las filas depdendent con una combinación sencilla:

SELECT c.* 
FROM dbo.TableC c 
INNER JOIN dbo.TableA a ON a.ID = c.TableAID -- or whatever column joins the tables..... 
WHERE....... -- possibly with a WHERE clause... 
+0

@KirkWoll: Sí, lo sé, pero esas dependencias en el nivel de datos solo existen en función del esquema. Si no sabe ** qué ** otra tabla de referencia 'TableA', no tiene ** forma ** de averiguar qué ** filas ** de esas otras filas de referencia de tablas en su' TableA' –

+0

I * do * conocer las dependencias en el nivel de esquema. Pero eso no me dice cómo encontrar las dependencias de datos. ¿Cómo encuentro las * filas * dependientes? Y en la práctica tengo alrededor de 20-30 tablas que apuntan a esta tabla. ¿Crear esa unión masiva es la única manera? –

+1

@KirkWoll: ¿cómo desea encontrar dependencias de datos, si no sabe en qué otras tablas podrían estar esas filas que hacen referencia a su fila en 'TableA' ??? Necesita ** dependencias de esquema ** primero - ** LUEGO ** (y solo ENTONCES) puede buscar dependencias de datos ... –

4

No tengo SQL en este equipo por lo que no puede darle código exacto, pero aquí está la forma en que debe ir. Tenga en cuenta que usaré la terminología de SQL Server.

No veo forma de hacer esto sin sql dinámico, al menos en SQL Server.

  1. Crear #t tabla temporal con columnas FK_TBL_NM, FK_CLMN_VAL.
  2. No debería ser difícil de conseguir todas las relaciones fk para PK de la Tabla A:

    SELECT * FROM sys.foreign_keys 
    WHERE referenced_object_id = OBJECT_ID('TableA') 
    
  3. utilizar un cursor para iterar a través del resultado de esta consulta y para cada generación y ejecución de SQL dinámico que se unirá TableA y la tabla recuperada del cursor y devuelve FK_TBL_NM (TableB, TableC, ...) y el valor de la columna fk.

  4. Inserte el resultado en #t (que es difícil de obtener el resultado SQL dinámico en la mesa, pero hacer una investigación sobre stackoverflow)

Ahora usted tiene la tabla que contiene una fila para cada fila de TableB , TableC, ...

Sé que esto es factible porque escribí el código con lógica similar para mi proyecto actual en el trabajo hace unos días.

Tenga en cuenta que probablemente deba hacer que su código funcione con pk/fk con más de una columna. También hay diferentes tipos de datos para las columnas. Esto complica las cosas un poco, pero es posible.

Cada paso que mencioné anteriormente no es difícil de implementar. Sin embargo, si tiene alguna dificultad, busque en stackoverflow :)

Cuestiones relacionadas