2011-09-30 32 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)。 –