Хорошо, ребята, я думаю, что я сам это выясню. Вдохновленный предыдущими ответами и комментариями, я сделал следующее. (Можете ли вы, ребята, быстро взглянуть, не перегружен ли я этим ребенком?)
0,1. Создано представление Index'd, представляющее поле «Тема», которое необходимо очистить. Это поле должно быть уникальным ... но прежде чем мы сможем сделать его уникальным, нам нужно сгруппировать его по нему.
-- Create the view.
CREATE VIEW ContentsCleanSubjectView with SCHEMABINDING AS
SELECT ContentId, ContentTypeId,
[dbo].[ToUriCleanText]([Subject]) AS CleanedSubject
FROM [dbo].[Contents]
GO
-- Index the view with three index's. Custered PK and a non-clustered,
-- which is where most of the joins will be done against.
-- Last one is because the execution plan reakons i was missing statistics
-- against one of the fields, so i added that index and the stats got gen'd.
CREATE UNIQUE CLUSTERED INDEX PK_ContentsCleanSubjectView ON
ContentsCleanSubjectView(ContentId)
CREATE NONCLUSTERED INDEX IX_BlahBlahSnipSnip_A ON
ContentsCleanSubjectView(ContentTypeId, CleanedSubject)
CREATE INDEX IX_BlahBlahSnipSnip_B ON
ContentsCleanSubjectView(CleanedSubject)
0,2. Создайте код триггера, который теперь
а) захватывает все «измененные» предметы (ничего нового / сложного в этом нет)
б) упорядочивает все вставленные строки, пронумерованные с разделением строк по чистой теме
c) обновить единственную строку, о которой мы говорим, в главном предложении обновления.
вот код ...
ALTER TRIGGER [dbo].[UpdateUniqueSubjectAfterInsertUpdate]
ON [dbo].[Contents]
AFTER INSERT,UPDATE
AS
BEGIN
SET NOCOUNT ON
DECLARE @InsertRows TABLE (ContentId INTEGER PRIMARY KEY,
ContentTypeId TINYINT,
CleanedSubject NVARCHAR(300))
DECLARE @UniqueSubjectRows TABLE (ContentId INTEGER PRIMARY KEY,
UniqueSubject NVARCHAR(350))
DECLARE @UniqueSubjectRows TABLE (ContentId INTEGER PRIMARY KEY,
UniqueSubject NVARCHAR(350))
-- Grab all the records that have been updated/inserted.
INSERT INTO @InsertRows(ContentId, ContentTypeId, CleanedSubject)
SELECT ContentId, ContentTypeId, [dbo].[ToUriCleanText]([Subject])
FROM INSERTED
-- Determine the correct unique subject by using ROW_NUMBER partitioning.
INSERT INTO @UniqueSubjectRows
SELECT SubResult.ContentId, UniqueSubject = CASE SubResult.RowNumber
WHEN 1 THEN SubResult.CleanedSubject
ELSE SubResult.CleanedSubject + CAST(SubResult.RowNumber - 1 AS NVARCHAR(5)) END
FROM (
-- Order all the cleaned subjects, partitioned by the cleaned subject.
SELECT a.ContentId, a.CleanedSubject, ROW_NUMBER() OVER (PARTITION BY a.CleanedSubject ORDER BY a.ContentId) AS RowNumber
FROM ContentsCleanSubjectView a
INNER JOIN @InsertRows b ON a.ContentTypeId = b.ContentTypeId AND a.CleanedSubject = b.CleanedSubject
GROUP BY a.contentId, a.cleanedSubject
) SubResult
INNER JOIN [dbo].[Contents] c ON c.ContentId = SubResult.ContentId
INNER JOIN @InsertRows d ON c.ContentId = d.ContentId
-- Now update all the effected rows.
UPDATE a
SET a.UniqueSubject = b.UniqueSubject
FROM [dbo].[Contents] a INNER JOIN @UniqueSubjectRows b ON a.ContentId = b.ContentId
END
Теперь подзапрос правильно возвращает все очищенные объекты, правильно разделенные и пронумерованные. Я никогда не знал ничего о команде 'PARTITION', так что этот трюк был большим ответом здесь:)
Тогда я просто присоединился к подзапросу со строкой, которая обновляется в родительском запросе. Номер строки правильный, так что теперь я просто делаю дело. если это первый раз, когда очищенный объект существует (например, row_number = 1), не изменяйте его. в противном случае добавьте row_number минус один. Это означает, что 2-й экземпляр того же субъекта будет уникальным: => cleansubject + '1'.
Причина, по которой я считаю, что мне нужно иметь индексированное представление, заключается в том, что если у меня есть два очень похожих предмета, то, когда вы удалили (т.е. очистили) все плохие символы (которые я определила как плохие) ) .. возможно, что два чистых предмета одинаковы. Таким образом, мне нужно делать все мои объединения на очищенном объекте, а не на теме. Теперь, для огромного количества строк, это дерьмо для производительности, когда у меня нет представления. :)
Так ... это слишком спроектировано?
Редактировать 1:
Изменен код триггера, поэтому он стал более производительным.