質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

87.79%

oracleから抽出したデータとDataTableを結合したい

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 1,035

score 7

実現したいこと

DataTable(table)にcsvtableとoracleTableのデータを結合したものを表示したい

不明点

DataTableを二つ用意してから任意のデータをもってきたいと思ったのですが、下記コードのoracleから取り込んだデータを持ってきたいという箇所にどうやってデータを投入したらよいかがわかりません。

 private void Button_Click_1(object sender, EventArgs e)
        {
            //Csv読み込んだファイル呼ぶ
            DataTable csvtable = Csv(textBox1.Text);
            //オラクルからデータを抽出する
            using (OracleConnection conn = new OracleConnection())
            {
                string DataSource = //"oracleへのパス";
                conn.ConnectionString = DataSource;
                //コネクションオープン
                conn.Open();
                using (OracleCommand cmd = new OracleCommand(select * from TABLE名)
                {
                    cmd.Connection = conn;
                    using (OracleDataReader reader = cmd.ExecuteReader())
                    {
                        DataTable oracleTable = new DataTable();
                        oracleTable.Load(reader);
                        dataGridView2.DataSource = oracleTable;
                    }
                }
            }
            //結合する

            //レイアウト変更用のDataTable作成
            DataTable table = new DataTable("ReasultDataTable");
            table.Columns.Add("名前", typeof(string));
            table.Columns.Add("年齢", typeof(string));
            table.Columns.Add("性別", typeof(string));
            table.Columns.Add("職業", typeof(string));
            table.Columns.Add("出身", typeof(string));
            //新規のレイアウトにcsv内のデータを投入する
            foreach (DataRow csvrow in csvtable.Rows)
            {
                DataRow dtRow = table.NewRow();

                dtRow["名前"] = csvrow["name"];//Csv(textBox1.Text)内の列データをdtRowに挿入  
                dtRow["年齢"] = csvrow["age"];//Csv(textBox1.Text)内の列データをdtRowに挿入 
                dtRow["性別"] = csvrow["gender"];//Csv(textBox1.Text)内の列データをdtRowに挿入 

                //oracleから取り込んだデータを持ってきたい
                dtRow["職業"] = csvrow["age"];//オラクルデータ挿入 
                dtRow["出身"] = csvrow["gender"];//オラクルデータ挿入

                table.Rows.Add(dtRow);
            }
             dataGridView1.DataSource = table;
        }

開発環境

VisualStudio2017

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • Orlofsky

    2020/11/09 18:30

    > ※実際に動作させる際は、select文も*ではなく細かく定めております。その上で30秒かかってしまいます。

    そのSELECT文とCREATE TABLE, CREATE INDEX, テーブル毎のレコード件数、実行計画を質問に追記しないと適切なコメントが付くのは難しいでしょう。テーブル名や列名を適当に置換すれば提示しても構わないはず。また、ちゃんと統計情報を収集していますか?

    Oracle 統計情報の収集 https://www.shift-the-oracle.com/performance-tuning/dbms_statistics.html
    Oracle EXPLAIN PLAN を使って実行計画を取得する https://www.shift-the-oracle.com/sql/explain-plan.html

    キャンセル

  • SurferOnWww

    2020/11/10 08:29

    質問は何なのですか? 表題を見ると 2 つの DataTable を join するクエリ (Linq to Object?) の書き方のように思えますが、中身を見ると Oracle からデータを取得する時間短縮の質問に見えます。

    キャンセル

  • AEGIL

    2020/11/10 11:44

    統計情報に関しては収集しておりませんでした。実現したいこと質問したいことは結合部分についてが主なので編集させていただきました。誤解を生んでしまい申し訳ありません。

    キャンセル

  • SurferOnWww

    2020/11/11 10:15

    質問者さん、無言になってしまいましたが、回答したのでそれに対するフィードバックを書いてください。役に立った/立たなかったくらいはすぐにでも書けると思いますけど。役に立たなかっらなら、どこが期待する回答と違うかなど書いてもらえると別の案が出せるかも。とにかく無言は NG です。

    キャンセル

回答 1

checkベストアンサー

0

DataTableを二つ用意してから任意のデータをもってきたいと思ったのですが、下記コードのoracleから取り込んだデータを持ってきたいという箇所にどうやってデータを投入したらよいかがわかりません。

DataTable ではなく List<T> 型のオブジェクトに SQL Server と CSV ファイルのレコードを取得し、Linq to Objects を使って内部結合または左外部結合する例ですが、以下の記事が参考になりませんか?

異なるデータソースの結合と表示
http://surferonwww.info/BlogEngine/post/2017/11/26/how-to-join-and-show-the-records-from-different-data-sources.aspx

SQL Server でなく Oracle の場合でも ADO.NET + ODP.NET を使って同じことができるはずです。

List<T> 型のオブジェクトではなくて、どうしても DataTable 同士を結合したいということでも、多少書き方は変わりますが、やはり Linq to Objects で結合できます。

以前作ったサンプルを紹介しておきます。Microsoft が提供するサンプルデーターベース Northwind の Orders テーブル、Customers テーブルを DataTable に取得してそれらを結合しています。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data;
using System.Data.SqlClient;

namespace ConsoleAppDataTableJoinByLinq
{
    // 結合後の結果を格納するためのクラス定義
    public class Result
    {
        public int OrderID { get; set; }
        public string CompanyName { get; set; }
        public int? EmployeeID { set; get; }
        public DateTime? OrderDate { get; set; }
        public decimal? Freight { get; set; }
    }

    class Program
    {
        static void Main(string[] args)
        {
            string connString = @"data source=lpc:(local)\sqlexpress;initial catalog=NORTHWIND;integrated security=True;";
            string queryOrders = "SELECT [OrderID],[CustomerID],[EmployeeID],[OrderDate],[RequiredDate],[ShippedDate],[ShipVia],[Freight],[ShipName],[ShipAddress],[ShipCity],[ShipRegion],[ShipPostalCode],[ShipCountry] FROM [Orders]";
            string queryCustomers = "SELECT [CustomerID],[CompanyName],[ContactName],[ContactTitle],[Address],[City],[Region],[PostalCode],[Country],[Phone],[Fax] FROM [Customers]";
            DataTable orders = new DataTable();
            DataTable customers = new DataTable();
            using (SqlConnection connection = new SqlConnection(connString))
            {
                using (SqlCommand command = new SqlCommand(queryOrders, connection))
                {
                    SqlDataAdapter adapter = new SqlDataAdapter(command);
                    adapter.Fill(orders);
                }

                using (SqlCommand command = new SqlCommand(queryCustomers, connection))
                {
                    SqlDataAdapter adapter = new SqlDataAdapter(command);
                    adapter.Fill(customers);
                }
            }

            // 内部結合
            var innerJoin = from o in orders.AsEnumerable()
                            join c in customers.AsEnumerable()
                            on o.Field<string>("CustomerID") equals c.Field<string>("CustomerID")
                            where o.Field<int?>("EmployeeID") == 9
                            select new Result
                            {
                                OrderID = o.Field<int>("OrderID"),
                                CompanyName = c.Field<string>("CompanyName"),
                                EmployeeID = o.Field<int?>("EmployeeID"),
                                OrderDate = o.Field<DateTime?>("OrderDate"),
                                Freight = o.Field<decimal?>("Freight")
                            };

            foreach (Result result in innerJoin)
            {
                Console.WriteLine($"Id: {result.OrderID}, Name: {result.CompanyName}, EmpID: {result.EmployeeID}, Date: {result.OrderDate}, Freight: {result.Freight}");
            }

            Console.WriteLine("--------------------------------");

            // 左外部結合
            var leftOuterJoin = from o in orders.AsEnumerable()
                                join c in customers.AsEnumerable()
                                on o.Field<string>("CustomerID") equals c.Field<string>("CustomerID") into cGroup
                                from item in cGroup.DefaultIfEmpty()    // Empty だと item が null になる
                                where o.Field<int?>("EmployeeID") == 9
                                select new Result
                                {
                                    OrderID = o.Field<int>("OrderID"),
                                    CompanyName = (item == null) ? "N/A" : item.Field<string>("CompanyName"), // item.Field<string>("CompanyName") ?? "N/A" ではだめ
                                    EmployeeID = o.Field<int?>("EmployeeID"),
                                    OrderDate = o.Field<DateTime?>("OrderDate"),
                                    Freight = o.Field<decimal?>("Freight")
                                };

            foreach (Result result in leftOuterJoin)
            {
                Console.WriteLine($"Id: {result.OrderID}, Name: {result.CompanyName}, EmpID: {result.EmployeeID}, Date: {result.OrderDate}, Freight: {result.Freight}");
            }
        }
    }
}

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/11/11 16:28 編集

    動作致しました。ありがとうございます。一応お聞きしたいのですが、どのサイトでもlinqが勧められていて処理速度もDataTableを結合するよりも早いと出ていました。上記の質問でのコードでの結合もしようとしたのですが、やはり面倒になりますか?
    //tableからバーコードのユニークリストをつくる 
    DataTable dtDistinct = ResultDT.DefaultView.ToTable(true, "Barcode");
    //そのユニークリストを使ってSQLを書く
    DataRow[] dataRows = dtDistinct.Select("");

    //オラクルにSQLを投げてOracleDTで受け取る

    //oracleDTとcsvDTをぶつけてtableに書き込む
    foreach (DataRow r in csvDt.Rows)
    {
    if(csvDt/*のカラム名*/ == oracleDT/*のカラム名*/)
    {

    }
    }

    キャンセル

  • 2020/11/11 17:04

    DataTable が適材適所かとか、開発者の知識や開発チームの方針とか、開発工数と保守工数とかを総合的に判断して決める話だと思います。

    昔ながらのアプリ、例えば WinForms + ADO.NET + DataGridView で DB の表示・編集・更新などを行うアプリとかでは DataSet / DataTable が適材適所と言えると思います。

    新規開発であれば Linq to Entities / Objects を採用する方向に進むのが選択肢の一番に来るのではとは思いますが。

    キャンセル

  • 2020/11/11 17:08

    なるほど。ご返答ありがとうございます。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 87.79%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る