Найти ссылки на записи с более молодой датой по сравнению с исходной записью

#sql #sql-server #sql-server-2005

#sql #sql-сервер #sql-server-2005

Вопрос:

Может кто-нибудь, пожалуйста, помочь мне с sql.

У меня есть таблица с полями:

ИДЕНТИФИКАТОР (guid), DocumentNumber (varchar), RefDocumentNumber (varchar), DocumentDate (datetime).

Документы сопряжены, что означает:

(исходный документ)

  • Идентификатор: 1111-111…
  • Номер документа: 1
  • RefDocumentNumber: пустая строка
  • Дата: 2014-06-25 12:11:24.890

(документ, на который ссылаются)

  • Идентификатор: 2222-2222
  • Номер документа: 2
  • RefDocumentNumber: 1
  • Дата: 2014-06-25 12:12:24.890

Проблема в том, что у меня есть некоторые ситуации, когда справочный документ имеет «более молодую дату». Поэтому мне нужно обновить его дату с помощью функции DATEADD (добавить 60 секунд).

Это произошло из-за сбоя во времени сервера…

Может кто-нибудь, пожалуйста, помочь мне с:

  1. Поиск этих записей (я хочу знать, сколько ссылочных документов необходимо обновить)
  2. Помогите мне с «безопасным» обновлением этих документов, на которые ссылаются (на самом деле цикл ОБНОВЛЕНИЯ MyTable УСТАНАВЛИВАЕТ documentdate= DATEADD (ss, 60, documentdate), где documentnumber = ‘1’

Спасибо.

Ответ №1:

Что-то вроде этого:

 UPDATE OD SET OD.Date = RD.Date
FROM Dokument OD
JOIN Dokument RD ON OD.DocumentNumber = RD.RefDocumentNumber
WHERE OD.Date < RD.Date
  

или:

 UPDATE OD SET OD.Date = DATEADD(second,-120,OD.Date)
FROM Dokument OD
JOIN Dokument RD ON OD.DocumentNumber = RD.RefDocumentNumber
WHERE OD.Date < RD.Date
  

только выбранный штамент:

 Select DISTINCT OD.Id
FROM Dokument OD
JOIN Dokument RD ON OD.DocumentNumber = RD.RefDocumentNumber
WHERE OD.Date < RD.Date
  

Комментарии:

1. Первое обновление устанавливает дочернюю дату такой же, как родительская дата, не старше. Кроме того, добавление 60 секунд к дате делает ее моложе, а не старше.

2. Отредактировано. В любом случае, если ссылочная запись должна быть копией исходного документа, поэтому первое обновление было бы лучшим подходом

Ответ №2:

Вы можете использовать курсор для перебора всех записей:

 DECLARE curYoungRecords CURSOR FOR
 SELECT a.Id, a.DocumentDate
   FROM Documents a
        INNER JOIN Documents b ON b.DocumentNumber = a.RefDocumentNumber
               AND b.DocumentDate < a.DocumentDate

DECLARE @DocId UNIQUEIDENTIFIER
DECLARE @DocDate DATETIME

OPEN curYoungRecords
FETCH NEXT FROM curYoungRecords INTO @DocId, @DocDate

WHILE @@FETCH_STATUS = 0
BEGIN
    -- Make record "older" by 120 seconds
    UPDATE Documents
       SET DocumentDate = DATEADD(second, -120, @DocDate)
     WHERE Id = @DocId

    FETCH NEXT FROM curYoungRecords INTO @DocId, @DocDate
END

CLOSE curYoungRecords
DEALLOCATE curYoungRecords
  

INNER JOIN Гарантирует, что включены только «дочерние» документы, в которых дата документа моложе родительской.

Комментарии:

1. Обратите внимание, что инструкция update установит для «дочерних» документов ту же дату и время, что и для родительских; это предполагаемый результат или он должен быть старше?

2. цель состоит в том, чтобы убедиться, что родительский документ имеет более старую дату, чем ссылочный (дочерний) документ. В настоящее время из-за неправильного времени сервера дочерние документы выглядят так, как будто они были созданы раньше родительских…

3. Учитывая, что пример данных в вопросе составляет 60 секунд между родительским и дочерним, я изменил UPDATE на 120 секунд.