удалить записи из промежуточной таблицы после их добавления в реальную таблицу - PullRequest
1 голос
/ 16 февраля 2011

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

вот мой код хранимой процедуры

    INSERT INTO dashboardtasks
SELECT [tour], tourname, [taskname], [deptdate], [tasktype], [desc], [duedate], [compdate], [comments], [agent], [compby], [graceperiod], completed , canceled
FROM staggingtasks
WHERE NOT EXISTS(SELECT * 
                 FROM dashboardtasks 
                 WHERE (staggingtasks.tour=dashboardtasks.tour and
                       staggingtasks.taskname=dashboardtasks.taskname and 
staggingtasks.deptdate=dashboardtasks.deptdate and 
staggingtasks.duedate=dashboardtasks.duedate and
staggingtasks.tourname=dashboardtasks.tourname 

)
                 )




END

Ответы [ 6 ]

3 голосов
/ 16 февраля 2011

Возможно, вы могли бы сделать DELETE со своего промежуточного стола в сочетании с предложением OUTPUTINSERT результат предложения OUTPUT в вашей основной таблице, чтобы сделать все это в одном атомарном операторе.

OUTPUT deleted.* into dashboardtasks 

* В BOL перечислены * 1008 некоторые ограничения, которые могутсделать этот подход нежизнеспособным.

Таблица выходных данных не может:

  • Включены триггеры, определенные для него.
  • Участвовать с обеих сторон ограничения внешнего ключа.
  • Имеют ограничения CHECK или включенные правила.

Полный синтаксис для вашего запроса ...

DELETE FROM staggingtasks
OUTPUT DELETED.[tour],
       DELETED.tourname,
       DELETED.[taskname],
       DELETED.[deptdate],
       DELETED.[tasktype],
       DELETED.[desc],
       DELETED.[duedate],
       DELETED.[compdate],
       DELETED.[comments],
       DELETED.[agent],
       DELETED.[compby],
       DELETED.[graceperiod],
       DELETED.completed,
       DELETED.canceled
INTO dashboardtasks
WHERE  NOT EXISTS(SELECT *
                  FROM   dashboardtasks
                  WHERE  ( staggingtasks.tour = dashboardtasks.tour
                           and staggingtasks.taskname = dashboardtasks.taskname
                           and staggingtasks.deptdate = dashboardtasks.deptdate
                           and staggingtasks.duedate = dashboardtasks.duedate
                           and staggingtasks.tourname = dashboardtasks.tourname
                         ))  
2 голосов
/ 16 февраля 2011

Помните, что удаление будет регистрировать все, поэтому со временем ваш журнал может стать слишком большим.Если вас не волнуют данные в вашей промежуточной таблице, попробуйте вместо вставки команду TRUNCATE:

TRUNCATE TABLE staggingtasks

Как и другие говорят, вы можете поместить все это в транзакции на всякий случай .Плюс в Truncate заключается в том, что он быстрый, поскольку для каждой записи, которую вы удаляете из таблицы, не требуется дополнительная регистрация.

2 голосов
/ 16 февраля 2011

Имеется оператор удаления с теми же критериями, что и для вставки, за исключением того, что теперь вы используете EXISTS вместо NOT EXISTS .

Примерно так:

INSERT INTO dashboardtasks
SELECT [tour], tourname, [taskname], [deptdate], [tasktype], [desc], [duedate], [compdate], [comments], [agent], [compby], [graceperiod], completed , canceled
  FROM staggingtasks
 WHERE NOT EXISTS
  (
        SELECT * 
         FROM dashboardtasks 
         WHERE (
                        staggingtasks.tour=dashboardtasks.tour and
                      staggingtasks.taskname=dashboardtasks.taskname and 
                        staggingtasks.deptdate=dashboardtasks.deptdate and 
                        staggingtasks.duedate=dashboardtasks.duedate and
                        staggingtasks.tourname=dashboardtasks.tourname 
                    )
  )


DELETE FROM staggingtasks
 WHERE EXISTS
  (
        SELECT * 
         FROM dashboardtasks 
         WHERE (
                        staggingtasks.tour=dashboardtasks.tour and
                      staggingtasks.taskname=dashboardtasks.taskname and 
                        staggingtasks.deptdate=dashboardtasks.deptdate and 
                        staggingtasks.duedate=dashboardtasks.duedate and
                        staggingtasks.tourname=dashboardtasks.tourname 
                    )
  )
1 голос
/ 16 февраля 2011

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

Вам необходимо вставить данные во временную таблицу, затем вставить данные из временной таблицы, а затем удалить данные из промежуточной таблицы на основе записей в временной таблице. Это гарантирует, что вы удалили только те записи, которые вы вставили, а не некоторые другие, добавленные во время вставки. И, конечно, вы должны поместить все это в транзакцию, как показывал @Ardman.

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

SELECT [tour], tourname, [taskname], [deptdate], [tasktype], [desc], [duedate], [compdate], [comments], [agent], [compby], [graceperiod], completed , canceled 
INTO #TasksToInsert
FROM staggingtasks 
WHERE NOT EXISTS(SELECT * 
                FROM dashboardtasks 
                WHERE (staggingtasks.tour=dashboardtasks.tour 
                    AND staggingtasks.taskname=dashboardtasks.taskname 
                    AND staggingtasks.deptdate=dashboardtasks.deptdate 
                    AND staggingtasks.duedate=dashboardtasks.duedate 
                    AND staggingtasks.tourname=dashboardtasks.tourname)
                )

INSERT INTO dashboardtasks ([tour], tourname, [taskname], [deptdate], [tasktype], [desc], [duedate], [compdate], [comments], [agent], [compby], [graceperiod], completed , canceled )
SELECT [tour], tourname, [taskname], [deptdate], [tasktype], [desc], [duedate], [compdate], [comments], [agent], [compby], [graceperiod], completed , canceled 
FROM #TasksToInsert

DELETE FROM staggingtasks  
WHERE EXISTS   (SELECT *
                FROM #TasksToInsert          
                WHERE (staggingtasks.tour=#TasksToInsert.tour 
                        AND staggingtasks.taskname=#TasksToInsert.taskname 
                        AND staggingtasks.deptdate=#TasksToInsert.deptdate 
                        AND staggingtasks.duedate=#TasksToInsert.duedate 
                        AND staggingtasks.tourname=#TasksToInsert.tourname)
                )   

И если он еще не запущен в производство, пожалуйста, исправьте неправильную написание StagingTasks. Или это будет раздражать ваших разработчиков на годы! Я также хотел бы рассмотреть вопрос о добавлении суррогатного ключа в таблицу dashboardTasks, так как PK с несколькими полями, как у вас, может вызвать проблемы с производительностью, которые не будут вызывать меньший ключ int, особенно если есть дочерние таблицы. Но все же сделайте уникальный индекс по натуральному ключу.

0 голосов
/ 16 февраля 2011

Вы можете выполнить несколько запросов в одной хранимой процедуре, поэтому, если я что-то упустил, вы можете просто добавить

DELETE staggingtasks WHERE <any criteria you need>

после запроса INSERT ...

0 голосов
/ 16 февраля 2011

Вы можете запустить оператор DELETE, который очищает таблицу

DELETE FROM myTable

Я бы предложил использовать BEGIN TRY и BEGIN CATCH, так что если что-то случится, выне удалил данные из промежуточной таблицы.

BEGIN TRY
    BEGIN TRAN
    INSERT statement....

    // All successful
    DELETE statement...

END TRY

BEGIN CATCH

    IF @@TRANCOUNT > 0
        ROLLBACK TRAN

END CATCH

IF @@TRANCOUNT > 0
    COMMIT TRAN
...