2011-09-30 21 views
1

OK,所以我的主題行是不是很描述性的,但這裏的情景:掩蔽或隱藏在SQL Server不準確輸入的數據2008年

的最終用戶有法律義務向交易數據提交給政府機構。這些交易包含各種個人和組織的名稱和地址。然而,最終用戶經常拼錯報告的個人和組織的名稱,或者他們嚴重損壞地址等。

由最終用戶提交的信息是合法的「文檔」,因此它不能被代理商更改收到它。此外,交易可以被公衆查看和搜索。當政府機構發現一個明顯的拼錯或錯誤的地址時,他們希望用已知的良好價值「隱藏」或「掩蓋」該不良价值。例如,如果最終用戶輸入了「Arnie Schwarzeger」,該機構可以用「Arnold Schwarzenegger」取代該名稱。查看數據的公衆將看到(並搜索)正確的拼寫,但可以查看最終用戶在找到相關數據記錄後輸入的原始數據。

希望這可以很好地解釋業務案例...對SQL部分!因此,要解決這個問題,我們有看起來像這樣的表:

CREATE TABLE [dbo].[SomeUserEnteredData](
    [Id] [uniqueidentifier] NOT NULL, 
    [LastOrOrganizationName] [nvarchar](350) NOT NULL, // data as entered by end-user 
    [FirstName] [nvarchar](50) NULL, // data as entered by end-user 
    [FullName] AS ([dbo].[FullNameValue]([FirstName],[LastName])) PERSISTED, // data as entered by end-user 
    [MappedName] AS ([dbo].[MappedNameValue]([FirstName],[LastName]))) // this is the 'override' data from the agency 

CREATE TABLE [dbo].[CorrectionsByAgency](
    [Id] [uniqueidentifier] NOT NULL, 
    [ReplaceName] [nvarchar](400) NOT NULL, 
    [KeepName] [nvarchar](400) NOT NULL) 

CREATE FUNCTION [dbo].[FullNameValue] 
(
    @FirstName as NVARCHAR(40), 
    @LastOrOrganizationName as NVARCHAR(350) 
) 
RETURNS NVARCHAR(400) 
WITH SCHEMABINDING 
AS 
BEGIN 
    DECLARE @result NVARCHAR(400) 
    IF @FirstName = '' OR @FirstName is NULL 
     SET @result = @LastOrOrganizationName 
    ELSE 
     SET @result = @LastOrOrganizationName + ', ' + @FirstName 
    RETURN @result 
END 

CREATE FUNCTION [dbo].[MappedNameValue] 
(
    @FirstName as NVARCHAR(50), 
    @LastOrOrganizationName as NVARCHAR(350) 
) 
RETURNS NVARCHAR(400) 
AS 
BEGIN 
    DECLARE @result NVARCHAR(400) 
    DECLARE @FullName NVARCHAR(400) 
    SET @FullName = dbo.FullNameValue(@FirstName, @LastOrOrganizationName) 
    SELECT top 1 @result = KeepName from CorrectionsByAgency where ReplaceName = @FullName 
    if @result is null 
     SET @result = @FullName 
    RETURN @result 
END 

我們希望,如果我的樣品是不是太令人費解的,你可以看到,如果該機構輸入名稱修正,它將替換所有出現拼寫錯誤的名字。從業務邏輯的角度來看,這是正確的:機構人員只會輸入一些更正,並且更正可以在任何地方覆蓋拼寫錯誤的名稱。

從服務器性能的角度來看,這個解決方案STINKS。計算得到的SomeUserEnteredData.MappedName列無法編制索引,也沒有從該列讀取的視圖可以編入索引!如果我們無法索引MappedName值,則無法滿足我們的需求。

我已經能夠看到作爲一種可能性是最終用戶創建的數據以及該機構創建的數據之間創建一個額外的鏈接表,唯一的選擇 - 當機構進入校正記錄,是創造了一個紀錄在每個發生錯誤列值的鏈接表中。這似乎是一個非常可能的創建/銷燬許多(數十萬)那些鏈接記錄爲機構用戶輸入的每一個更正...

做你們任何SQL天才那裏有關於如何解決這個問題的好主意?

回答

1

我不知道這是否是直接回答你的問題,但我會盡量簡化整個事情:停止使用功能,堅持「計算」值,並使用應用程序邏輯(可能在存儲過程)來管理數據。

假設一個機構校正可以應用到很多用戶輸入的名字,那麼你可以有這樣的事情:

create table dbo.UserEnteredData (
    DocumentId uniqueidentifier not null primary key, 
    UserEnteredName nvarchar(1000) not null, 
    CorrectedNameId uniqueidentifier null, 
    constraint FK_CorrectedNames foreign key (CorrectedNameId) 
    references dbo.CorrectedNames (CorrectedNameId) 
) 

create table dbo.CorrectedNames (
    CorrectedNameId uniqueidentifier not null primary key, 
    CorrectedName nvarchar(1000) not null 
) 

現在,你需要確保你的應用程序邏輯可以做這樣的事情:

  1. 外部用戶輸入髒數據
  2. 機構用戶評論中的髒數據,並確定雙方的不正確的名稱和校正的名字
  3. 個應用程序檢查糾正名已經存在
  4. 如果沒有,請在DBO新行。CorrectedNames
  5. 在dbo.UserEnteredData創建一個新的行,與CorrectedNameId

我假設的東西,而在現實中更復雜和修正是基於地址和其他數據以及剛剛名發出,但你描述的基本關係似乎很簡單。正如你所說,這些函數會增加很多開銷,而且對於直接存儲所需數據而言,它們提供的好處並不明確(對我而言)。

最後,我不明白你對創建/銷燬鏈接記錄的評論;取決於您的應用程序邏輯來正確處理數據更改。

+0

澄清創建/銷燬的評論...如果進行修正的代理機構用戶改變了主意(或者更可能導致他們自己的錯誤),那麼需要重新評估所有以前應用的修正。 –

+0

我想我會追求你建議的路徑,但不要直接更新'髒'數據表。我將在兩個數據表之間放置一個鏈接表。 (即UserEnteredData.Id = SomeLinkingTable.DataId和SomeLinkingTable.CorrectionId = CorrectedNames.Id)。 –