簡體   English   中英

C#:Inner Join 4表SQL Server

[英]C#: Inner Join 4 tables SQL Server

我在一個SQL語句中加入了4個表,這些表將數據讀入對象並填充gridview。

我的問題 :這是一個好習慣嗎? 從數據庫中讀取時有沒有像性能這樣的副作用? 如果是這樣,請提供一些改進建議。

protected void OrdersGridView_SelectedIndexChanged(object sender, EventArgs e)
{
    string OID = OrdersGridView.SelectedRow.Cells[0].Text;
    OrderIDlbl.Text = "Order# " + OID;

    using (SqlConnection con = new SqlConnection(cData.CS))
    {
        con.Open();
        {
            string sql = "select o.*, c.*, oi.*, p.* from Orders as o INNER JOIN Customers as c ON o.CustID = c.CustomerID INNER JOIN OrderItems as oi ON o.OrderID = oi.InvoiceID INNER JOIN Products as p ON p.PartNumber = oi.PartNumb where OrderID ='" + OID + "'";

            SqlCommand myCommand = new SqlCommand(sql, con);
            myCommand.CommandTimeout = 15;
            myCommand.CommandType = CommandType.Text;

            using (SqlDataReader myReader = myCommand.ExecuteReader())
            {
                while (myReader.Read())
                {
                    passid.Text = (myReader["CustID"].ToString());
                    TermsDropdown.Value = (myReader["PaymentTerms"].ToString());
                    PaymentDate.Value = ((DateTime)myReader["PaymentDate"]).ToString("MMMM dd, yyyy");
                    OrderDate.Value = ((DateTime)myReader["OrderDate"]).ToString("MMMM dd, yyyy");
                    SalesRep.Value = (myReader["SalesRep"].ToString());
                    comenttxtbox.Value = (myReader["Comments"].ToString());
                    Discountlbl.Text = "Discount: " + (myReader["Discount"].ToString() + " AED");
                    Totallbl.Text = "Total: " + (myReader["Total"].ToString() + " AED");
                    Statuslbl.Text = (myReader["OrderStatus"].ToString());
                    SelectCustomertxtbox.Value = (myReader["Company"].ToString());
                    Name.Text = "Name: " + (myReader["FName"].ToString()) + " " + (myReader["LName"].ToString());
                    Phone.Text = "Phone: " + (myReader["Phone"].ToString());
                    Mail.Text = "Mail: " + (myReader["Personal_Email"].ToString());
                }
            }

            DataTable dt = new DataTable();

            using (SqlDataAdapter da = new SqlDataAdapter(myCommand))
            {
                da.Fill(dt);

                OrderItemsGridview.DataSource = dt;
                OrderItemsGridview.EmptyDataText = "No Items";
                OrderItemsGridview.DataBind();
            }
        }
    }
}

訂購POPUP

我不一定會說這是一個不好的做法,但你絕對應該擺脫你的查詢中出現的別名。*模式。 沒有明確選擇您需要的列是代碼中的錯誤做法。

至於連接,如果您無法控制數據庫設計,通常它是唯一的方法。 但是,您可以通過創建一個為您提供這些連接的視圖來大大簡化您的代碼內SQL查詢。 但是,我會質疑INNER JOIN是否是您真正想要的。 請記住,內部聯接僅顯示在聯接兩側包含匹配項的結果。

在您的特定情況下,我建議將訂單信息和訂單項本身的查詢分開。 您通過在每個訂單商品上添加訂單信息來添加冗余信息。 此外,只要您的查詢需要外部輸入,請確保使用參數化查詢:

myCommand.CommandText = "select o.Date, o.Title, o.Id from Orders where Id = @Id";
myCommand.Parameters.Add("@Id", SqlDbType.Int);
myCommand.Parameters["@Id"].Value = 3;

不要忘記刪除別名。*有利於明確選擇列的東西。

我建議在數據庫中創建一個存儲過程,其參數為Order ID。 然后從.net調用存儲過程而不是直接調用SQL。 這具有以下優點

  1. 刪除SQL注入安全問題。
  2. SQL會緩存查詢計划,並在下次處理時執行得更快,而不是您正在觸發的adhoc查詢。

僅在數據中包含必要的列。 您正在提取許多您不需要的額外數據,這會產生額外的服務器和網絡開銷,並且絕對會讓事情變得更慢。

此外,您需要為任何參數使用SqlParameter 您的SQL受sql注入。

string sql = "select <only columns you need> from Orders as o INNER JOIN Customers as c ON o.CustID = c.CustomerID INNER JOIN OrderItems as oi ON o.OrderID = oi.InvoiceID INNER JOIN Products as p ON p.PartNumber = oi.PartNumb where OrderID ='@OrderId";
            SqlCommand myCommand = new SqlCommand(sql, con);
            myCommand.CommandTimeout = 15;
            myCommand.CommandType = CommandType.Text;
            myCommand.Parameters.AddWithValue("@OrderId", oid);

這取決於您查詢數據的方式。 如果它只是簡單的SELECT ... FROM ... WHERE ID = X那么它完全沒問題。

但是有些情況下這種連接會導致性能顯着下降。 讓我們說你做了類似的事情

SELECT TOP 10 * FROM Table1 INNER JOIN Table2 ON..  
INNER JOIN Table3 ON .. 
INNER JOIN Table4 ON.. 
WHERE Table1.Column1 = 1 AND 
      Table2.Column1 = 2 AND 
      Table3.Column1 = 3 AND 
      Table4.Column1 = 4 
ORDER BY Table1.Column1, Table2.Column1, Table3.Column1, Table4.Column1

這種情況不太可能發生,但是如果遇到這樣的情況,Sql很可能會進行全表掃描,因為索引只能在自己的表中包含列,但是所有4個表中的包含列的順序也是如此條款。

為了解決此類問題,您可以使用物化視圖,您可以添加索引以覆蓋所有列。 但是在你需要像這樣的4個連接之前就可以了。

除了Jakotheshadows所回答的內容之外,在根據他的建議進行更改並在多個調用中獲取數據(單獨查詢)之前,請問自己以下問題:

什么對你更重要?

  1. 保存您獲得的冗余數據量? 如果是,那么繼續他的建議。
  2. 速度更重要嗎? 如果是,那么保持連接,但遵循Jakotheshadows的建議並使用參數並刪除別名等。

如果您一次性獲取數據,就像您使用連接一樣,這意味着一次訪問數據庫,但更多的冗余數據。 如果您進行單獨的查詢,則超過1次旅行(每次查詢1次),因此可能需要更長時間。 所以做出一個信息豐富的決定。

簡單來說,如果你去雜貨店購物,你想要一次性(重旅行)獲得所有東西,或者做更多的旅行,但要讓它們更輕松。 (雖然這個雜貨店的例子沒有冗余,但你明白了......)

請記住,性能(速度)不應成為您關注的問題,直到它成為瓶頸。 但是,你知道這一點很好。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM