0

データベースからcsvファイルにデータをエクスポートする抽出アプリケーションを使用しています。いくつかの条件変数に基づいて、さまざまなテーブルからデータを抽出します。いくつかの条件では、データを複数のテーブルから抽出する必要があるため、UNIONALLを使用する必要があります。したがって、UNION ALL条件を満たすために、列の数と一致するようにnullを使用しています。

現在、システム内のすべてのクエリは、条件変数に基づいて事前に構築されています。問題は、テーブルプロジェクションに変更がある場合(つまり、新しい列が追加された、既存の列が変更された、列が削除された場合)、アプリケーションのコードを手動で変更する必要があることです。

テーブル構造を変更してもコードを変更する必要がないように、列名を動的に抽出する方法をいくつか提案していただけますか?


私の懸念は、クエリするテーブルを決定する条件です。可変条件は次のようなものです

  • 条件がAの場合、TableXからロードします
  • 条件がBの場合、TableAおよびTableYからロードします。

どのテーブルからデータを取得する必要があるかを知る必要があります。テーブルがわかれば、データディクショナリから列名をクエリするのは簡単です。ただし、もう1つの条件があります。それは、一部の列を除外する必要があり、これらの列はテーブルごとに異なるということです。

リスト列を動的に生成する場合にのみ問題を解決しようとしています。しかし、私のマネージャーは、単に修正するのではなく、概念レベルで解決策を作るように私に言いました。これは非常に大きなシステムであり、プロバイダーとコンシューマーは常にデータをロードして消費します。そこで彼は、一般的な解決策を求めていました。

では、条件、テーブル名、除外された列を保存するための最良の方法は何ですか?1つの方法は、データベースに保存することです。他に方法はありますか?はいの場合、何が最善ですか?ファイナライズする前に、少なくともいくつかのアイデアを提示する必要があるためです。

ありがとう、

4

4 に答える 4

4

このような単純なクエリは、Oracle のテーブルの各列名を知るのに役立ちます。

Select COLUMN_NAME from user_tab_columns where table_name='EMP'

あなたのコードでそれを使用してください:)

于 2010-12-20T15:38:43.453 に答える
1

つまり、動的クエリを構築するためのルール エンジンを設計することです。これは小さな取り組みではありません。あなたが提供した要件は次のとおりです。

  1. ストア ルール (「条件変数」と呼ばれるもの)
  2. 各ルールは 1 つ以上のテーブルから選択します
  3. さらに、テーブルから除外する列を指定するルールもあります
  4. 複数のテーブルから選択するルールは、UNION ALL 演算子で満たされます。プロジェクションが一致しないテーブルは、NULL 列と整列させる必要があります。

あなたが言及していないいくつかの可能な要件:

  1. DATE 列の時間要素を含めたり除外したりするなどのフォーマット マスキング
  2. クエリの射影で列の順序を変更する
  3. 前の要件は、マルチテーブル ルールに関しては特に重要です。これは、テーブルのプロジェクションがデータ型と列数で一致する必要があるためです。
  4. それに続いて、パディング NULL 列は、必ずしもプロジェクションの最後に追加されるとは限りません。たとえば、3 列のテーブルが のように 4 列のテーブルにマッピングされる場合がありますcol1, col2, null, col3
  5. 一部のマルチテーブル クエリは、セット操作ではなく結合によって満たす必要がある場合があります。
  6. WHERE 句を追加するための規則。
  7. 除外される列のデフォルト セットを定義するメカニズム (つまり、テーブルがクエリされるたびに適用される) 。

これらのルールをデータベース テーブルに格納します。それらはデータであり、データを保存することがデータベースの目的だからです。(既にルール エンジンを持っている場合を除きます。)

最初の一連の要件を考慮すると、次の 3 つのテーブルが必要になります。

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_OrderUNION ALL クエリでテーブルが表示される順序を指定します。これは、主要なテーブルの column_names を CSV ファイルの見出しとして使用する場合にのみ重要です。
  • All_Columns_YNクエリを SELECT * として記述できるかどうか、またはデータ ディクショナリと RULE_EXCLUDED_COLUMNS テーブルから列名をクエリする必要があるかどうかを示します。
  • No_of_padding_cols列リストの最後に追加する NULL の数を指定することにより、これらの UNION ALL 列のプロジェクションを一致させるための単純な実装です。

あなたがそれらを気にするかどうかわからないので、私はあなたが指定しなかった要件に取り組むつもりはありません. 基本的なことは、上司が求めているのは、それ自体がアプリケーションであるということです。クエリを生成するためのアプリケーションと同様に、ルールを維持するためのインターフェースが必要になることに注意してください。

于 2010-12-21T06:51:10.393 に答える
1

わかりました、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();
    }
}

適合するかどうかは、しばらくしてから確認します。

于 2010-12-20T17:43:12.227 に答える
0

多国籍企業、

tablename をキーとする、アプリケーション プロセスに関連するすべての既知のテーブルのディクショナリ (組み合わせに関係なく、テーブルのディクショナリのみ) を事前に作成するのはどうですか。このディクショナリのメンバーはIList<string>列名になります。これにより、存在する列の数の両方で2つのテーブルを比較するdicTable[myVarTableName].Countだけでなく、列名を抽出するために繰り返し処理することができdicTable[myVarTableName].valueます。

ピースの最後で、小さな linq 関数を実行して、最大数の列を持つテーブルを特定し、それに応じて null を持つ構造を作成できます。

これが思考の糧になることを願っています..

于 2010-12-20T15:53:47.813 に答える