Лучший способ динамически получать имена столбцов из таблиц оракула - PullRequest
0 голосов
/ 20 декабря 2010

Мы используем приложение экстрактора, которое будет экспортировать данные из базы данных в CSV-файлы. На основе некоторой переменной условия он извлекает данные из разных таблиц, и для некоторых условий мы должны использовать UNION ALL, поскольку данные должны быть извлечены из более чем одной таблицы. Таким образом, чтобы удовлетворить условию UNION ALL, мы используем нули, чтобы соответствовать количеству столбцов.

Прямо сейчас все запросы в системе предварительно построены на основе переменной условия. Проблема заключается в том, что всякий раз, когда происходит изменение в проекции таблицы (т.е. добавляется новый столбец, модифицируется существующий столбец, удаляется столбец), мы должны вручную изменять код в приложении.

Не могли бы вы дать несколько советов, как динамически извлекать имена столбцов, чтобы любые изменения в структуре таблицы не требовали изменений в коде?


Меня беспокоит условие, которое решает, какую таблицу запрашивать. Переменная условие как

  • если условие A, загрузить из TableX
  • если условие B, тогда загрузка из Таблицы A и Таблицы Y.

Мы должны знать, из какой таблицы нам нужно получить данные. Как только мы узнаем таблицу, будет просто запросить имена столбцов из словаря данных. Но есть еще одно условие: некоторые столбцы необходимо исключить, и эти столбцы различны для каждой таблицы.

Я пытаюсь решить проблему только для динамического генерирования столбцов списка. Но мой менеджер сказал мне, чтобы принимать решение на концептуальном уровне, а не просто исправить. Это очень большая система с поставщиками и потребителями, постоянно загружающими и потребляющими данные. Поэтому он хотел решения, которое может быть общим.

Так, каков наилучший способ хранения условия, имени таблицы, исключенных столбцов? Один из способов хранения в базе данных. Есть ли другие способы? Если да, что лучше? Как я должен дать хотя бы пару идей перед окончательной доработкой.

Спасибо,

Ответы [ 4 ]

4 голосов
/ 20 декабря 2010

Простой запрос, подобный этому, поможет вам узнать имя каждого столбца таблицы в Oracle.

Select COLUMN_NAME from user_tab_columns where table_name='EMP'

Используйте его в своем коде:)

1 голос
/ 21 декабря 2010

Итак, что вы действительно ищете, так это создание механизма правил для построения динамических запросов.Это немалое начинание.Вы указали следующие требования:

  1. Правила хранения (то, что вы называете «условной переменной»)
  2. Каждое правило выбирает из одной или нескольких таблиц
  3. Дополнительно некоторыеправила определяют столбцы, которые должны быть исключены из таблицы
  4. Правила, которые выбираются из нескольких таблиц, удовлетворяются оператором UNION ALL;таблицы, проекции которых не совпадают, должны быть приведены в соответствие с нулевыми столбцами.

Некоторые возможные требования, которые вы не упоминаете:

  1. Маскировка формата, например, включая или исключая времяэлемент столбцов DATE
  2. Изменение порядка столбцов в проекции запроса
  3. Предыдущее требование особенно важно, когда речь идет о правилах для нескольких таблиц, поскольку проекции таблиц должны совпадатьпо типу данных, а также по количеству столбцов.
  4. Исходя из этого, столбцы заполнения NULL могут не обязательно прикрепляться к концу проекции, например, таблица из трех столбцов может быть сопоставлена ​​с таблицей из четырех столбцов какcol1, col2, null, col3.
  5. Некоторые многостоловые запросы, возможно, должны удовлетворяться объединениями , а не операциями set.
  6. Правила добавления предложений WHERE.
  7. Механизм определения наборов исключаемых столбцов по умолчанию (т. Е. Которые применяются при каждом запросе к таблице).

Я бы сохранил эти правила в таблицах базы данных.Потому что это данные, а для хранения данных нужны базы данных.(Если у вас уже нет движка правил).

Принимая первый набор требований, вам нужны три таблицы:

RULES
-----
RuleID 
Description
    primary key (RuleID)

RULE_TABLES
-----------
RuleID
Table_Name
Table_Query_Order
All_Columns_YN
No_of_padding_cols
    primary key (RuleID, Table_Name)


RULE_EXCLUDED_COLUMNS
---------------------
RuleID
Table_Name
Column_Name
    primary key (RuleID, Table_Name, Column_Name)

Я использовал составные первичные ключи только потому, что легчеработать с ними в этом контексте, например, проводить анализ воздействия;Я бы не рекомендовал это для обычных приложений.

Я думаю, что все это не требует пояснений, за исключением дополнительных столбцов в RULE_TABLES.

  • Table_Query_Order указывает порядок, в котором таблицы появляются в запросах UNION ALL;это имеет значение, только если вы хотите использовать column_names ведущей таблицы в качестве заголовков в CSV-файле.
  • All_Columns_YN указывает, может ли запрос быть записан как SELECT * или нужно ли запрашивать имена столбцов из словаря данных и таблицы RULE_EXCLUDED_COLUMNS.
  • No_of_padding_cols - это упрощенная реализация для сопоставления проекций в этих столбцах UNION ALL путем указания количества пустых значений, добавляемых в конец списка столбцов.

Я не являюсьсобираюсь заняться теми требованиями, которые вы не указали, потому что я не знаю, заботитесь ли вы о них.Основное, что просит ваш начальник - это приложение само по себе.Помните, что помимо приложения для генерации запросов вам понадобится интерфейс для поддержки правил.

1 голос
/ 20 декабря 2010

Хорошо, MNC, попробуйте это по размеру (вставьте его в новое консольное приложение):

using System;
using System.Collections.Generic;
using System.Linq;
using Test.Api;
using Test.Api.Classes;
using Test.Api.Interfaces;
using Test.Api.Models;

namespace Test.Api.Interfaces
{
    public interface ITable
    {
        int Id { get; set; }
        string Name { get; set; }
    }
}

namespace Test.Api.Models
{
    public class MemberTable : ITable
    {
        public int Id { get; set; }
        public string Name { get; set; }
    }
    public class TableWithRelations
    {
        public MemberTable Member { get; set; }
        // list to contain partnered tables
        public IList<ITable> Partner { get; set; }

        public TableWithRelations()
        {
            Member = new MemberTable();
            Partner = new List<ITable>();
        }
    }
}

namespace Test.Api.Classes
{
    public class MyClass
    {
        private readonly IList<TableWithRelations> _tables;

        public MyClass()
        {
            // tableA stuff
            var tableA = new TableWithRelations { Member = { Id = 1, Name = "A" } };
            var relatedclasses = new List<ITable>
             {
                new MemberTable
                {
                   Id = 2,
                   Name = "B"
                }
             };
            tableA.Partner = relatedclasses;


            // tableB stuff
            var tableB = new TableWithRelations { Member = { Id = 2, Name = "B" } };
            relatedclasses = new List<ITable>
             {
                new MemberTable
                {
                   Id = 3,
                   Name = "C"
                }
             };
            tableB.Partner = relatedclasses;


            // tableC stuff
            var tableC = new TableWithRelations { Member = { Id = 3, Name = "C" } };
            relatedclasses = new List<ITable>
             {
                new MemberTable
                {
                   Id = 2,
                   Name = "D"
                }
             };
            tableC.Partner = relatedclasses;


            // tableD stuff
            var tableD = new TableWithRelations { Member = { Id = 3, Name = "D" } };
            relatedclasses = new List<ITable>
             {
                new MemberTable
                {
                   Id = 1,
                   Name = "A"
                },
                new MemberTable
                {
                   Id = 2,
                   Name = "B"
                },
             };
            tableD.Partner = relatedclasses;

            // add tables to the base tables collection
            _tables = new List<TableWithRelations> { tableA, tableB, tableC, tableD };
        }

        public IList<ITable> Compare(int tableId, string tableName)
        {
            return _tables.Where(table => table.Member.Id == tableId
                            && table.Member.Name == tableName)
                        .SelectMany(table => table.Partner).ToList();
        }
    }
}

namespace Test.Api
{
    public class TestClass
    {
        private readonly MyClass _myclass;
        private readonly IList<ITable> _relatedMembers;

        public IList<ITable> RelatedMembers
        {
            get { return _relatedMembers; }
        }

        public TestClass(int id, string name)
        {
            this._myclass = new MyClass();
            // the Compare method would take your two paramters and return
            // a mathcing set of related tables that formed the related tables
            _relatedMembers = _myclass.Compare(id, name);
            // now do something wityh the resulting list
        }
    }
}

class Program
{
    static void Main(string[] args)
    {
        // change these values to suit, along with rules in MyClass
        var id = 3;
        var name = "D";
        var testClass = new TestClass(id, name);

        Console.Write(string.Format("For Table{0} on Id{1}\r\n", name, id));
        Console.Write("----------------------\r\n");
        foreach (var relatedTable in testClass.RelatedMembers)
        {
            Console.Write(string.Format("Related Table{0} on Id{1}\r\n",
                      relatedTable.Name, relatedTable.Id));
        }
        Console.Read();
    }
}

Я вернусь немного назад, чтобы посмотреть, подходит он или нет.

0 голосов
/ 20 декабря 2010

MNC,

Как насчет создания словаря всех известных таблиц, вовлеченных в процесс приложения, заранее (независимо от комбинаций - просто словарь таблиц), который основан на имени таблицы.члены этого словаря будут IList<string> из имен столбцов.Это позволит вам сравнить две таблицы по количеству имеющихся столбцов dicTable[myVarTableName].Count, а также выполнить итерацию по dicTable[myVarTableName].value для извлечения имен столбцов.

В конце фрагмента вы можете выполнитьмаленькая функция linq для определения таблицы с наибольшим количеством столбцов и создания структуры с нулевыми значениями соответственно.

Надеюсь, это даст пищу для размышлений ..

...