Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Conexión con bases de datos (https://www.clubdelphi.com/foros/forumdisplay.php?f=2)
-   -   Detectar llaves foraneas con TFields (https://www.clubdelphi.com/foros/showthread.php?t=79576)

jasmad 18-07-2012 01:15:30

Detectar llaves foraneas con TFields
 
hola

alguien sabe si es posible detectar si un campo es llave foranea accesando a los procedimientos, funciones o propiedades del tfield,
y si no es posible por esos medios es posible hacer esto de alguna otra forma ?

creo esto seria muy util para poder generar formularios dinamicamente

saludos

Al González 18-07-2012 02:27:07

A través de TFields no, pero dependiendo del motor de base de datos que estés utilizando puedes hacer consultas a los metadatos.

Por ejemplo, si tu base de datos fuese Firebird, en ella podrías acceder a diversas tablas especiales como RDB$Index_Segments, RDB$Relation_Constraints y RDB$Ref_Constraints para averiguar si un campo en particular forma parte de un índice de llave externa y cuál es ese índice y el nombre de la respectiva restricción.

NOTA: Siempre es bueno indicar con qué tecnologías trabajas.

Saludos.

jasmad 19-07-2012 16:48:32

Detectar llaves foraneas
 
hola,

estoy con motor Firebird
codetyphon 2.50
lazarus 0.9.31
componentes de acceso a bd ibdac

ya conocia esa forma de accesar a las tablas de sistema de firebird pero estoy buscando una manera de saber si el campo es llave foranea y a que tabla referencia desde la aplicacion; de hecho casi siempre los paquetes de acceso a datos tienen un componente de metadatos pero eso depende del paquete que uses.

Casimiro Notevi 19-07-2012 17:37:42

Si es firebird, entonces lo que te ha indicado Al González:

Cita:

Empezado por Al González
Por ejemplo, si tu base de datos fuese Firebird, en ella podrías acceder a diversas tablas especiales como RDB$Index_Segments, RDB$Relation_Constraints y RDB$Ref_Constraints para averiguar si un campo en particular forma parte de un índice de llave externa y cuál es ese índice y el nombre de la respectiva restricción.


Al González 19-07-2012 19:22:02

Cita:

Empezado por jasmad (Mensaje 437681)
[...] y si no es posible por esos medios es posible hacer esto de alguna otra forma ?

Cita:

Empezado por jasmad (Mensaje 437766)
[...] desde la aplicacion; de hecho casi siempre los paquetes de acceso a datos tienen un componente de metadatos pero eso depende del paquete que uses.

Bueno, como has de imaginar, puedes hacer la consulta respectiva desde la propia aplicación.

Seguramente los hay, pero no conozco un paquete de componentes que te dé esa información de manera fácil, salvo un "FirebirdSQLConnection" que hace tiempo derivé de TSQLConnection. Es para Delphi y no creo que compile en Lazarus, así que al menos podría poner aquí una copia de los métodos que hacen el trabajo sucio:

Código Delphi [-]
  // Saber la tabla que refiere un campo de llave externa ("foránea")
  Function TMagiaSQLConnection.FieldRefTable (Const Table, Field :String)
    :String;
  Begin
    Result := ConstraintRefTable (FieldConstraint (Table, Field));
  End;

  // Saber el nombre de la restricción ("constraint") —necesarias para llaves externas— aplicada a un campo
  Function TMagiaFirebirdSQLConnection.FieldConstraint (
    Const Table, Field :String) :String;
  Begin
    Result := SelectTrim (
      'First 1 RC.RDB$Constraint_Name From RDB$Relation_Constraints RC ' +
      'Inner Join RDB$Index_Segments ISe On ISe.RDB$Index_Name = ' +
      'RC.RDB$Index_Name Where (RC.RDB$Relation_Name = ' +
      QuotedCasedName (Table) + ') And (ISe.RDB$Field_Name = ' +
      QuotedCasedName (Field) + ') And (ISe.RDB$Field_Position = 0)');
  End;

  // Saber la tabla de referencia de una restricción
  Function TMagiaFirebirdSQLConnection.ConstraintRefTable (
    Const Constraint :String) :String;
  Begin
    { Get reference table of constraint }
    Result := SelectTrim (
      'Select RelC.RDB$Relation_Name From RDB$Relation_Constraints RelC ' +
      'Inner Join RDB$Ref_Constraints RefC On RefC.RDB$Const_Name_UQ = ' +
      'RelC.RDB$Constraint_Name Where RefC.RDB$Constraint_Name = ' +
      QuotedCasedName (Constraint));
  End;

SelectTrim es un método que ejecuta un simple Select sobre un campo de la base de datos (mediante el método nativo Execute), devolviendo el resultado como cadena de caracteres y quitándole espacios que tuviera en ambos extremos. QuotedCasedName es una función que lo único que hace (en este caso y para simplificar) es convertir a mayúsculas una cadena de caracteres y encerrarla entre comillas simples. El código completo de esa y otras clases está aquí (pasen por alto la licencia, estoy por cambiarla a open source).

A partir de aquí y con lo que ya conoces sobre cómo acceder a las tablas del sistema (metadatos), jasmad, creo que podrás conseguir lo que pides. Espero sea de ayuda. :)

Algunas otras monerías de estas clases:

Código Delphi [-]
  // Ejecutar procedimiento almacenado dando nombre y argumentos
  Function TMagiaSQLConnection.ExecProc (Const Proc :String;
    Const AParams :Variant) :Variant;

  // Obtener la fecha y hora del servidor
  Function TMagiaSQLConnection.CurrentTimeStamp :TDateTime;

  // Obtener el mayor valor de un campo
  Function TMagiaSQLConnection.Max (Const Table, Field :String;
    Const Conditions :String = '') :Variant;

  // Obtener el siguiente valor de una secuencia (generador en Firebird)
  Function TMagiaSQLConnection.NextValue (Const Sequence :String) :Integer;

  // Obtener la tabla, el campo y un ID de error a partir de los mensajes de excepción más comunes
  Function TMagiaFirebirdSQLConnection.TableError (Const Msg :String)
    :TghTableError;

Saludos.

Al González.

jasmad 19-07-2012 19:36:28

gracias por tu ayuda Al


La franja horaria es GMT +2. Ahora son las 07:43:56.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi