PiensoPienso: Listar todos las tablas que usan un atributo o sus subtipos


Un DBA me planteo el siguiente problema:

Necesito un reporte que tenga todos las tablas que contengan el atributo ProductoID o cualquier subtipo del mismo y que se indique si forma parte de la clave.

El listado deberia ser de la forma
Atributo, Tabla, Clave(S/N)

La base de conocimiento esta en GeneXus 9.0, tiene un mas de 500 tablas y unos 7000 atributos.

Como lo harian? Yo no encontré ninguna forma elegante.

Comentarios

  1. Que tal lo siguiente:

    1> Sacar un listado de todas las tablas del sistema (probablemente se quede colgado un buen rato).
    2> Grabarlo como XML.
    3> Importarlo en Excel en 2 hojas distintas.
    4> En la primer hoja filtras todas las filas con ProductId.
    5> En la segunda hoja filtras todas las filas con el supertipo ProductId.

    Seguramente te convenga reemplazar las ocurrencias de:
    "TblAttIsKey" y agregar una 'S' entre los tags.
    así vas a tener como distinguir las claves.

    Si usas "Origenes XML" podés seleccionar que campos importar.

    No se si puede ser considerado "elegante" pero creo que logra lo que necesitás en poco tiempo.

    ResponderBorrar
  2. Pablo:
    Gracias por el comentario.
    La solucion es buena, aunque demora demasiado.

    Prosigue la busqueda de soluciones mas rapidas.

    La definicion de "elegante", es que no tenga "mal olor".

    Enrique

    ResponderBorrar
  3. Bueno, va ejemplo en .NET con GXPublic utilizando gxknowledgebase.dll (GXPatters)

    Seguramente se vea "feo" porque elimina espacios.
    Lástima que con GXPublic no puedo hacer Join's, de lo contrario se resuelve de forma mucho más simple.

    En el caso que se tenga los registros volcadas a un DBMS si sería posible hacerlo.. con una única sentencia.

    -------------------------
    using System;
    using System.Collections;
    using System.Collections.Specialized;
    using GXKnowledgeBase;
    using GXKnowledgeBase.Results;

    namespace PiensoPienso
    {
    class Program
    {

    public static void Main(string[] args)
    {
    string KBPath = @"C:\Modelos\";
    string FltAttNam = "ProductId";

    KnowledgeBase.KB.Open(KBPath);

    ArrayList attlist = new ArrayList();
    Hashtable attnames = new Hashtable();

    int FndAttId = 0;
    string Sentence = "SELECT ATTID FROM ATTRIBUTE WHERE MdlId=1 AND ATTNAM=\""+ FltAttNam +"\"";
    using (KnowledgeBaseQuery query = KnowledgeBase.KB.ExecuteQuery(Sentence)){
    while (query.Read()){
    FndAttId = (int) query["AttId"];
    attnames.Add(FndAttId,query["ATTNAM"]);
    }
    }
    attlist.Add(FndAttId); // Incorporo a la lista el atributo original

    // Busco los atributros que tienen al mismo como supertipo
    Sentence = "SELECT * FROM ATTRIBUTE WHERE MdlId=1 AND AttIdSup=" + FndAttId.ToString() ;
    using (KnowledgeBaseQuery query = KnowledgeBase.KB.ExecuteQuery(Sentence)){
    while (query.Read()){
    attlist.Add((int) query["AttId"]);
    attnames.Add((int) query["AttId"],query["ATTNAM"]);
    }
    }

    foreach (int attid in attlist)
    {
    Sentence = "SELECT * FROM TBLATT WHERE MdlId=1 AND ATTID=" + attid.ToString() ;
    using (KnowledgeBaseQuery query = KnowledgeBase.KB.ExecuteQuery(Sentence)){
    while (query.Read()){
    int attkey = (int) query["TblAttIsKey"];
    string Sentence2 = "SELECT * FROM TABLE WHERE MdlId=1 AND TBLID=" + ((int) query["TblId"]).ToString();
    using (KnowledgeBaseQuery query2 = KnowledgeBase.KB.ExecuteQuery(Sentence2)){
    while (query2.Read()){
    System.Console.WriteLine(attnames[attid]+ ", " + ((string) query2["TblNam"]) +", " + (attkey==1?"S":"N"));
    }
    }
    }
    }
    }

    }
    }
    }

    ResponderBorrar
  4. Cuando necesite algo similar hice un procedimeinto en mssql server
    faltaria agregar los subtipos, pero puede servir.

    CREATE PROCEDURE [dbo].[usp_BuscarCampo] @bus varchar(10) AS
    set @bus = '%'+rtrim(@bus)+'%'
    SELECT sysObjects.name +' - '+ sysColumns.name as 'tabla'
    FROM sysObjects, sysColumns
    WHERE sysObjects.id = sysColumns.id and sysObjects.xtype = 'u'
    and
    (sysColumns.name Like @bus)
    order by sysObjects.name

    ResponderBorrar
  5. Nando, no serviría para el cometido que requiere Enrique.

    1 - Va contra un Like
    2 - No indica si se encuentra en la PK o no.

    Acá paso una sentencia compatible con SQLServer que retorna el listado en el formato que Enrique lo requiere.

    Lo único que no tengo cuales son los atributos del subtipo, pero si se hace un listado con los mismos podría ejecutar la sentencia para cada uno de ellos (GXPublic le puede ayudar).

    Select Column_Name,Table_Name, (case when (SELECT 'S' FROM INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE as cu WHERE cu.TABLE_NAME=col.TABLE_NAME and cu.COLUMN_NAME = col.COLUMN_NAME )<>'S' then 'N' else 'S' end) as INPK from INFORMATION_SCHEMA.COLUMNS col where col.COLUMN_NAME = ('ProductoId')

    ResponderBorrar
  6. David
    Tenes razon, pero a mi me sirvio el like porque los subtipos en la kb estaban armados con una nomenclatura estandar por ej CiudadId, DestinoCiudadId y OrigenCiudadID
    respecto si son indices o no tu solucion me parece correcta

    ResponderBorrar
  7. Me resulta maravilloso esto del blog.

    Se plantearon 3 soluciones bien diferentes, una usando solo geneuxs, otra usando GXPulbic, y otra basandose en la base de datos.
    Gracias a Pablo,David y Nando por sus aportes!.

    Todas estan buenas y creo que demuestra que esta faltando algo para resolver este tipo de consultas dentro de GeneXus.

    Mi solucion fue esta:

    1) Listar todos los subtipos de ProductoId.
    Con el List Attribute en GeneXus, averiguo el AttId de ProductoId.

    Con KBQuery (http://www.gxopen.com/gxopenrocha/servlet/hproject?311) haciendo la consulta:

    SELECT * FROM ATTRIBUTE WHERE MdlId=1 AND AttIdSup= [attid de ProductoId]

    Con esto logro una lista de todos los atributos subtipos de ProductoId.

    2) Salvo el resultado en una planilla electronica y con eso armo un string de la forma

    ProductoId*,;ProyectoProductoId*,;ProdId*,;

    3) En el List Attribute, pongo el string de arriba y con el boton Select dejo marcado solo el boton de Tables.

    4) Proceso la salida del list attribute (con Notepad) y con eso llego al resultado esperado.

    Sirve, si se necesita una unica vez, porque cuando hago esto me siento como Fonseca (http://blog.genexus.com/guscarr/?p=255)

    Enrique

    ResponderBorrar

Publicar un comentario

1) Lee el post
2) Poné tu opinión sobre el mismo.
Todos los comentarios serán leidos y la mayoría son publicados.

Entradas más populares de este blog

Aplicación monolítica o distribuida?

La nefasta influencia del golero de Cacho Bochinche en el fútbol uruguayo

Funcionalidades de GeneXus que vale la pena conocer: DATE Constants.