2010-12-20 11 views
0

データベースからcsvファイルにデータをエクスポートする抽出アプリケーションを使用しています。いくつかの条件変数に基づいて、異なるテーブルからデータを抽出し、複数のテーブルからデータを抽出する必要があるため、条件によってはUNION ALLを使用する必要があります。したがって、UNION ALL条件を満たすために、列の数と一致させるためにNULLを使用しています。オラクル表から列名を動的に取得する最良の方法

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

テーブル構造の変更がコードの変更を必要としないように列名を動的に抽出する方法を教えてください。


私の懸念は、照会するテーブルを決定する条件です。可変条件は、条件がある場合の条件は、Bは、次にテーブルAとTableyのから負荷である場合、TABLEX

  • からロード

    • あります。

    データを取得する必要があるテーブルを知っている必要があります。テーブルがわかると、データディクショナリからカラム名を問い合わせるのは簡単です。しかし、いくつかの列を除外する必要があり、これらの列は各表ごとに異なるという条件が1つあります。

    私はリスト列を動的に生成するためにのみ問題を解決しようとしています。しかし、私のマネージャーは私に、単に固定するのではなく、概念レベルで解決策をとるように言いました。これは、プロバイダとコンシューマが絶えずデータをロードし消費する非常に大きなシステムです。だから、彼は一般的な解決法を望んでいた。

    したがって、条件、tablename、除外列を保存するための最良の方法は何ですか? 1つの方法は、データベースに格納することです。他の方法はありますか?はいの場合は何が最高ですか?ファイナライズする前に少なくとも2つのアイデアを与えなければならないので。

    おかげで、

  • 答えて

    1

    [OK]を、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

    こんにちはジム、これはまさに私が欲しかったものです。どうもありがとう。実際に私は動的に列を生成するためにのみ問題を解決しようとしています。しかし、私のマネージャーは私に、修正するのではなく、概念レベルで解決策をとるように言いました。これは、プロバイダとコンシューマが絶えずデータをロードし消費する非常に大きなシステムです。だから、彼は一般的な解決法を望んでいました。あなたの助けに感謝します。これはまさに私が思ったものです。しかし、私はシステムに関するより多くの情報を入手し、どのシステムにも適用できる一般的なソリューションに取り組まなければならないと思います。 – MNC

    +0

    あなたはそれがすべてのシナリオのために拡張可能であるようにそれを成型することを望んで、それに答えてチックと答えのマークを与えるために怖がらないでください:)。季節の挨拶... –

    +0

    こんにちはジム、どのように答えとして2つの記事を選択します。あなたと@APCの回答に印をつけようとしています。それは私に答えとして両方をマークすることができません。 – MNC

    4

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

    Select COLUMN_NAME from user_tab_columns where table_name='EMP' 
    

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

    +0

    私の懸念は、照会するテーブルを決定する条件です。条件がある場合の条件 は、Bは、その後、我々は、テーブルの簡単なを知っていたら、 のデータを取得する必要がありますどのテーブルから知っている必要がありますTableAの&tableY.weからロードされた場合、その後、TABLEXから負荷のようにvarible条件 あなたが提案した通りです。 &それらの条件が1つあります。いくつかの列が必要ですが、除外するには が必要です。 条件を保存する最善の方法はtablename、列を一方向に除外します はデータベースに格納しています他の方法 &はい最高 – MNC

    +0

    @MNCがあれば:私はTHRコードでどうなるのか、あなたは、あなただけの列挙型をロードすることを好む場合は、条件から依存かどうか、列挙型に含まれる各テーブルのカラム名を取得することで必要な、またはコードの先頭にすべてのコードをロードします。除外カラムと条件については、データベース内で行うことが大きな関心事です。パラメータを変更するときにアプリケーションを再構築する必要はありません。私はこのようにします。 – LaGrandMere

    +0

    @LeGrandMere申し訳ありませんが、私は十分な情報を与えていないと思います。さらに分割されるいくつかの変数があります。例を挙げましょう。 2つの変数ID、nameがあります。 Idに基づくほとんどのクエリでは、テーブル名を決定し、データを抽出します。しかし、いくつかのIDについては、名前も考慮する必要があります。 IDが5の場合と同様に、IDが5で名前がAならばIDをチェックし、IDが5の場合はlaodテーブルAを、次にBの場合はtableB、tableAなどから読み込みます。名前の条件が見つからない可能性があります。 – MNC

    0

    MNC、どのように

    かかわらず、組み合わせの(アップフロントアプリケーションのプロセスに関与するすべての既知のテーブルの辞書の作成について - ちょうど辞書テーブルの中にキーイングされています)。この辞書のメンバーは列名のIList<string>になります。これにより、現在の列数dicTable[myVarTableName].Countと、dicTable[myVarTableName].valueの反復処理の両方で、2つのテーブルを比較して列名を引き出すことができます。

    最後に少しのlinq関数を使って、最大の列数を持つ表を判別し、それに応じてNULLを持つ構造体を作成することができます。

    これは思考のための食糧を与えることを望む。

    +0

    @Jim申し訳ありませんが、私は十分な情報を与えていないと思います。さらに分割されるいくつかの変数があります。例を挙げましょう。 2つの変数ID、nameがあります。 Idに基づくほとんどのクエリでは、テーブル名を決定し、データを抽出します。しかし、いくつかのIDについては、名前も考慮する必要があります。 IDが5の場合と同様に、IDが5で名前がAならばIDをチェックし、IDが5の場合はlaodテーブルAを、その後BはテーブルB、テーブルAからロードします。私たちは名前の条件を見逃すかもしれません。 – MNC

    +0

    申し訳ありませんが、私は辞書にテーブルデータを読み込むことを意味していませんでした。メタデータだけです(つまり、IList <>の列名を持つtablenameをキーとする)。あなたはより豊かな価値オブジェクトに必要なロジックをさらに外挿することによってlinqで意思決定ツリーを作成すると思います。 –

    +0

    でも、私は辞書のテーブルデータをメタデータだけを読み飛ばすものとして取っていませんでした。しかし、条件は2つの値に依存します。それが私の懸念でした。あなたが例を挙げることができれば、大きな助けになるでしょう。ありがとう。 – MNC

    1

    実際には、動的クエリを作成するためのルールエンジンを設計しています。これは小さな仕事ではありません。あなたが提供した要件は次のとおりです。各ルールは、1つまたは複数のテーブル

  • から選択したルール(あなたは「条件変数」と呼んでいるもの)
    1. Storeはさらにいくつかのルールがテーブルから除外される列を指定します
    2. 複数のテーブルから選択するルールは、UNION ALL演算子で満たされます。投影が一致しない表は、NULL列と一直線になるようにしなければなりません。

    あなたが言及していないいくつかの可能な要件:例えばマスキング

    1. フォーマット
    2. クエリの投影における列の順序の変更
    3. 前の要件は、複数のテーブルのルールに関して特に重要です。なぜなら、テーブルの予測は次の条件を満たす必要があります。列の数だけでなくデータ型も指定できます。それに続いて、パディングNULL列は必ずしも投影の端部に貼り付けられるとは限らない。 3つの列テーブルをcol1, col2, null, col3として4つの列テーブルにマッピングすることができる。
    4. 一部のマルチテーブルクエリは、操作の代わりにに接続することによって満足される必要があります。
    5. WHERE句を追加するためのルール。
    6. 除外された列のデフォルトセットを定義するためのメカニズムです(つまり、テーブルが照会されるたびに適用されます)。

    私はこれらのルールをデータベーステーブルに保存します。それらはデータであり、データを格納するのはデータベースであるためです。 (すでに手にルールエンジンを持っていない限り。)

    あなたは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_Orderは、UNION ALLクエリでテーブルが表示される順序を指定します。これは、先頭のテーブルのcolumn_namesをCSVファイルの見出しとして使用する場合にのみ重要です。
    • All_Columns_YNは、問合せをSELECT *として記述できるかどうか、またはデータ・ディクショナリとRULE_EXCLUDED_COLUMNS表から列名を問い合せる必要があるかどうかを示します。
    • No_of_padding_colsは、カラムリストの末尾に追加する方法を多くのNULL値を指定することにより、それらのUNION ALL列に突起を一致させるための単純な実装です。

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

  • +0

    答えてくれてありがとう私はこれを実装しようとしていますこれをメモリに保存したいのであれば、これを実装すれば使えるデータ構造は何ですか?または独自のデータ型を実装するのが最善でしょうか?アプリが最初に読み込まれたときに、ルールと対応する表を取得できます。 SQLのクエリを構築してメモリに格納することができます。つまり、データ構造はより正確です。 – MNC

    関連する問題