ОК, поэтому моя тема не очень описательная, но вот сценарий:
Конечный пользователь по закону обязан предоставить данные транзакции в государственное учреждение. Транзакции содержат имя и адрес различных лиц и организаций. ОДНАКО конечные пользователи часто неправильно пишут имена сообщаемых лиц и организаций, или они плохо искажают адрес и т. Д.
Информация, предоставленная конечным пользователем, является юридическим «документом», поэтому она не может быть изменена агентством, которое ее получило. Кроме того, транзакции могут быть просмотрены и найдены публикой. Когда правительственное агентство замечает очевидную ошибку или неправильный адрес, они хотели бы «спрятать» или «замаскировать» эту плохую ценность с известной хорошей ценностью. Например, если конечный пользователь ввел «Арни Шварцегер», агентство может заменить это имя на «Арнольд Шварценеггер». Публика, которая просматривает данные, увидит (и найдет) правильное написание, но сможет просмотреть исходные данные, введенные конечным пользователем, после того, как они найдут соответствующую запись данных.
Надеюсь, это достаточно хорошо объясняет экономическое обоснование ... в части 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 отличные идеи о том, как решить эту проблему?