2015-09-09 43 views
1

我有一個TSQL視圖。除了幾列以外,它非常基本,它只是簡單地進行一些連接,然後將所有東西粘合在一起,以呈現應有的美觀。然而,幾個不那麼簡單的列使得視圖代碼很難擴展,現在新的需求已經出現,使複雜的列的業務邏輯無效。A(T)包含太多業務邏輯的Sql視圖

沒有去過多細說,有我在數據庫中的表:

tblEmployment 

這包括「外水」的行。每次連續列的任何,對於給定的就業變化(假設的employmentTitle變化),那麼當前行推入另一個表tblEmploymentHistory,並在tblEmployment該行更改,因此它包含了最新的employmentTitle

本質上,該視圖所做的是,它試圖加入tblEmploymenttblEmploymentHistory與唯一EmploymentIdentifier,這是有道理的。

視圖中更復雜的列將嘗試通過從它已連接在一起的行(即從tblEmployment and tblEmploymentHistory)進行各種計算來計算一個數(每個行爲elapsedTime)。爲了獲得經過的時間,它基於口述的業務邏輯來執行計算,例如,只有歷史記錄表中的特定日期時間列應該計算在總時間間隔內,並且只有當該行中的其他列設置爲特定值時才應該這樣做。

現在新的要求已經出現,業務邏輯很多比以前更復雜。我發現很難擴展視圖來包含它,因爲它變得非常混亂,我認爲這可以在業務邏輯的其他部分所在的應用程序層更加結構化地完成!

是否「正確」廢棄視圖,而是將其移動到我的應用程序的應用程序層?顯然,通過觀點得到的好處是速度很快,並且在代碼中對大約100.000行進行計算需要一些時間。但是,可以通過過濾行來使其數量在10.000左右進行優化。

什麼是「標準」和解決這個問題的最乾淨的方法?

+0

爲什麼一個視圖而不是一個存儲過程? – Paolo

+0

@Paolo我不知道。存儲過程是否會成爲這裏的途徑?我自己並沒有創造出這個觀點,我的任務就是擴展它,但這很難做到。如果我使用存儲過程,會更好嗎? – DSF

+0

使用存儲過程可以依賴於CTE和臨時表,imho將極大地簡化您的任務。你沒有分享任何代碼,所以我無法確定,但很可能是這樣。 – Paolo

回答

3

答案取決於幾件事情。首先,確保數據庫正在進行基於集合的工作。如果你開始進入遊標(一般來說)或某種循環,你最好把它放在應用程序中。關係數據庫的效率不高。我會考慮的另一件事是你工作環境的標準是什麼?數據庫中保存的其他東西就像你在哪裏?如果是這樣,你可能想保持一致。

最後,無論如何最有效地返回這些結果,並且不影響其他查詢,應該是答案。

+0

對於我工作的環境,我很少看到視圖中的業務邏輯。根據我的理解,它應該只是作爲一個虛擬表,因此只顯示已經存在但列表不同的列。最多一個案例陳述。我不知道這是否應該使用視圖的一般方式?你以前在視圖中看過「複雜」的列嗎?列的基礎是幾行計算? 我注意到你說過基於集合的工作,所以也許我可以減少視圖來執行基於集合的工作,然後將其拉入應用程序層並應用基於此的業務邏輯? – DSF

+1

我見過各種各樣的...我經常使用的許多視圖都有點複雜。我認爲,只要所有相關方都瞭解正在發生的事情,最後一句話,在視圖和應用程序中進行基於集合的工作是一個體面的想法。這樣做的好處是您將擁有更通用的視圖,即應用程序的更多位可以使用。 –

+0

好點!實際上還有另外一個視圖,它們在很大程度上進行了相同的連接,但是後來有幾個列出現了一些業務邏輯。因此,將其減少到一個視圖,然後在應用程序中使用它來應用不同的業務邏輯似乎是一種乾淨的方式。 – DSF

1

正如所承諾的,我給你的UDF-方法的一個例子: 在我的項目之一,我用這個擁有超過40層不同的和分層結構的UDF獲得了近1000列設置回的結果。

CREATE TABLE dbo.TestTable(Col1 INT,Col2 INT,Col3 INT); 
INSERT INTO dbo.TestTable VALUES(1,2,3),(4,5,6),(7,8,9); 
GO 

CREATE FUNCTION dbo.TestFunc(@Prm1 INT,@Prm2 INT) 
RETURNS TABLE 
AS 
RETURN 
    SELECT @Prm1 AS Func_Prm1 --use names, which will be unique in any usage, this makes things much easier! 
      ,@Prm2 AS Func_Prm2 
      ,@Prm1 * @Prm2 AS Func_Calculated; 
GO 

--This would be your simple VIEW, consisting of any columns you can easily get 
SELECT * 
FROM dbo.TestTable 
--This is how you join the "buiness logic" to your view 
CROSS APPLY dbo.TestFunc(TestTable.Col1,TestTable.Col2) AS func 

DROP TABLE dbo.TestTable; 
GO 
DROP FUNCTION dbo.TestFunc;  
GO 
+0

謝謝:)。給我一些關於是否使用你的方法的想法,或者只是創建一個簡單的視圖,然後在應用程序的應用程序層中執行一些業務邏輯。 – DSF

+1

@ D.Singh,兩者都應該沒問題......如果您需要計算的其他列沒有應用程序(例如報告,統計數據...),則純SQL解決方案應該更好。如果你的應用程序是「單點入口」,我更喜歡應用程序。 – Shnugo