在SQL Server 2008中屏蔽或隐藏不准确输入的数据

时间:2011-09-30 08:29:58

标签: sql sql-server 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 个答案:

答案 0 :(得分: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. 中创建一个新行
  6. 使用CorrectedNameId
  7. 在dbo.UserEnteredData中创建一个新行

    我假设现实情况相当复杂,并且根据地址和其他数据以及名称进行更正,但您描述的基本关系似乎很简单。正如你所说,这些功能增加了很多开销,而且(对我而言)他们提供的优势不仅仅是直接存储您需要的数据。

    最后,我不理解你关于创建/销毁链接记录的评论;由您的应用程序逻辑来正确处理数据更改。