Маскировка или скрытие неточно введенных данных в SQL Server 2008 - PullRequest
1 голос
/ 30 сентября 2011

ОК, поэтому моя тема не очень описательная, но вот сценарий:

Конечный пользователь по закону обязан предоставить данные транзакции в государственное учреждение. Транзакции содержат имя и адрес различных лиц и организаций. ОДНАКО конечные пользователи часто неправильно пишут имена сообщаемых лиц и организаций, или они плохо искажают адрес и т. Д.

Информация, предоставленная конечным пользователем, является юридическим «документом», поэтому она не может быть изменена агентством, которое ее получило. Кроме того, транзакции могут быть просмотрены и найдены публикой. Когда правительственное агентство замечает очевидную ошибку или неправильный адрес, они хотели бы «спрятать» или «замаскировать» эту плохую ценность с известной хорошей ценностью. Например, если конечный пользователь ввел «Арни Шварцегер», агентство может заменить это имя на «Арнольд Шварценеггер». Публика, которая просматривает данные, увидит (и найдет) правильное написание, но сможет просмотреть исходные данные, введенные конечным пользователем, после того, как они найдут соответствующую запись данных.

Надеюсь, это достаточно хорошо объясняет экономическое обоснование ... в части 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

Надеюсь, если мой образец не слишком запутанный, вы можете увидеть, что если агентство введет исправление имени, оно заменит все вхождения имени с ошибкой. С точки зрения бизнес-логики это работает совершенно правильно: сотрудники агентства вносят только несколько исправлений, и исправления могут быть отменены везде, где есть имена с ошибками.

С точки зрения производительности сервера это решение ЗАМЕТИТ. Рассчитанный столбец SomeUserEnteredData.MappedName не может быть проиндексирован, и ни одно представление, считывающее этот столбец, также не может быть проиндексировано! Там нет никакого способа, которым это может работать для наших нужд, если мы не можем индексировать значения MappedName.

Единственная альтернатива, которую я смог увидеть в качестве возможности, - это создать дополнительную таблицу связи между данными, созданными конечным пользователем, и данными, созданными агентством - когда агентство вводит запись исправления, запись создается в таблица ссылок для каждого вхождения неверного значения столбца. Обратной стороной этого является, по-видимому, реальная вероятность создания / уничтожения многих (сотен тысяч) этих связывающих записей для каждого исправления, введенного пользователем агентства ...

Есть ли у кого-нибудь из вас гениев SQL отличные идеи о том, как решить эту проблему?

1 Ответ

1 голос
/ 30 сентября 2011

Я не уверен, что это ответ на ваш вопрос напрямую, но я постараюсь упростить все это: прекратить использование функций, сохранить «вычисленные» значения и использовать логику приложения (возможно, в хранимой процедуре) для управления данными .

Предполагая, что одно исправление агентства может быть применено ко многим введенным пользователем именам, тогда у вас может быть что-то вроде этого:

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

Я предполагаю, что в действительности все гораздо сложнее, и исправления вносятся на основе адресов и других данных, а также только имен, но описываемые вами основные отношения кажутся достаточно простыми. Как вы сказали, функции увеличивают накладные расходы, и неясно (для меня), какую выгоду они получают от простого хранения необходимых данных напрямую.

Наконец, я не понимаю ваш комментарий о создании / уничтожении ссылок; Правильно обрабатывать изменения данных зависит от вашей прикладной логики.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...