Цикл sql2000 в хранимой процедуре - PullRequest
2 голосов
/ 03 марта 2009

Я очень плохо знаком с SQL, я могу довольно легко работать с базовыми операторами, но я еще не определил циклы.

Foreach(JobHeaderID AS @OldJobHeaderID in dbo.EstimateJobHeader WHERE EstimateID=@OldEstimateID)  
{  
  INSERT EstimateJobHeader (ServiceID,EstimateID) 
  SELECT ServiceID, @NewEstimateID 
  FROM EstimateJobHeader 
  WHERE EstimateID=@OldEstimateID;  

  SELECT @err = @@error 
  IF @err <> 0 
  BEGIN 
    ROLLBACK TRANSACTION 
    SET @RETURN_VALUE = 4 
    RETURN 4 
  END  

  SET @NewJobHeaderID = CAST(SCOPE_IDENTITY() AS INT)  

  SELECT @err = @@error 
  IF @err <> 0 
  BEGIN 
    ROLLBACK TRANSACTION 
    SET @RETURN_VALUE = 3 
    RETURN 3 
  END  

  INSERT EstimateDetail (JobHeaderID, OtherCols) 
  SELECT (@NewJobHeaderID,OtherCols) 
  FROM EstimateDetail 
  WHERE JobHeaderID=@OldJobHeaderID

  SELECT @err = @@error 
  IF @err <> 0 
  BEGIN 
    ROLLBACK TRANSACTION 
    SET @RETURN_VALUE = 3 
    RETURN 3 
  END  

  INSERT EstimateJobDetail (JobHeaderID, OtherCols) 
  SELECT (@NewJobHeaderID, OtherCols) 
  FROM EstimateJobDetail 
  WHERE JobHeaderID=@OldJobHeaderID  

  SELECT @err = @@error 
  IF @err <> 0 
  BEGIN 
    ROLLBACK TRANSACTION 
    SET @RETURN_VALUE = 3 
    RETURN 3 
  END  
}

Ответы [ 2 ]

6 голосов
/ 03 марта 2009

Вы должны избегать циклов в хранимых процедурах.

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

Смотрите это:
Почему так сложно сделать цикл в T-SQL


Вы спрашивали, как это сделать, используя методы на основе множеств. Я сделаю все возможное, но в начале вашего кода есть ошибка, из-за которой трудно быть уверенным, что я правильно ее читаю. Условие в первом операторе INSERT соответствует условию в цикле FOREACH. Таким образом, либо цикл будет выполняться только один раз (одна запись возвращается туда), либо ваша вставка вставляет несколько новых записей за одну итерацию (да, операторы вставки могут добавлять более одной записи за раз). И если он добавляет несколько записей, почему вы получаете только идентификатор, созданный последней вставкой?

Тем не менее я думаю, что понимаю это достаточно хорошо, чтобы показать вам кое-что. Похоже, вы просто делаете копию оценки. Вы также не объясняете, откуда берется значение @NewEstimateID. Если есть родительская таблица, пусть будет так, но было бы полезно узнать о ней.

/* Where'd @NewEstimateID come from? */
/* If there are several records in EstimateJobHeader with @OldEstimateID,
 *  this will insert one new record for each of them */
INSERT EstimateJobHeader (ServiceID,EstimateID)
     SELECT ServiceID, @NewEstimateID 
     FROM EstimateJobHeader
     WHERE EstimateID= @OldEstimateID

/* Copy EstimateDetail records from old estimate to new estimate */
INSERT EstimateDetail (JobHeaderID, OtherCols) 
    SELECT (new.JobHeaderID,ed.OtherCols) 
    FROM EstimateJobHeader new
    INNER JOIN EstimateJobHeader old ON old.EstimateID= @OldEstimateID 
        AND new.EstimateID= @NewEstimateID AND old.ServiceID=new.ServiceID
    INNER JOIN EstimateDetail ed ON ed.JobHeaderID= old.JobHeaderID

/* Copy EstimateJobDetail records from old estimate to new estimate */
INSERT EstimateJobDetail (JobHeaderID, OtherCols)
    SELECT (new.JobHeaderID,ed.OtherCols) 
    FROM EstimateJobHeader new
    INNER JOIN EstimateJobHeader old ON old.EstimateID= @OldEstimateID 
        AND new.EstimateID= @NewEstimateID AND old.ServiceID=new.ServiceID
    INNER JOIN EstimateJobDetail ejd ON ejd.JobHeaderID= old.JobHeaderID

Приведенный выше код предполагает, что ServiceID + EstimateID уникален в таблице EstimateJobHeader. Если это не так, мне нужно знать, какой столбец или столбцы однозначно идентифицируют строки в таблице, чтобы я мог соединить старую запись с новой и быть уверенным, что соотношение равно 1: 1.

Наконец, для краткости проверка ошибок была опущена.

5 голосов
/ 03 марта 2009

Посмотрите на утверждение WHILE:

http://msdn.microsoft.com/en-us/library/aa260676(SQL.80).aspx

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

...