2012-10-22 37 views
5

問題:我如何遍歷一個臨時表在存儲過程中沒有PK

我需要通過一個表中的記錄循環,拉動員工數量和對另一個表進行比較,該員工數量看看他們是否仍然活躍的員工。如果他們不再是活躍的員工,我需要將這一行中的數據傳遞給另一個存儲過程。

研究:

我GOOGLE了周圍頗有幾分意識到,我不應該使用的遊標這一點。但是,我也發現下面的例子:

  1. http://ask.sqlservercentral.com/questions/7969/loop-through-records-in-a-temporary-table.html
  2. http://eedle.com/2010/11/11/looping-through-records-in-sql-server-stored-procedure/

然而,這似乎是他們通過記錄使用PK循環。僱員人數可以作爲多個recods一樣在我的情況

問題:

  1. 是否有可能實現什麼,我試圖不遊標?
  2. 如果可能的話,我將如何去獲取每行非唯一列?
+2

難道你們就不能使用加入? –

+0

不,我循環第一個表,比較第二個表,當比較失敗時,我從第一個表中刪除記錄。本質上,我正在刪除第一個不在公司的員工表中的recod。 –

+0

你從該行傳遞給存儲過程的數據是什麼? – podiluska

回答

6

既然你沒有給我們你的情況充分說明,我們無法給出一個完整的答案,但是,在一般情況下,它的循環要避免在基於集合的語言如SQL而不是遊標本身(與Cursosr的問題是它們需要循環)。

在你的評論中,你提供了一點信息,你想要「循環遍歷第一張表,比較第二張表,當比較失敗時,我刪除第一張表的記錄。本質上,我刪除了recods從員工誰是不再與該公司的第一個表

這裏是你如何在SQL這樣做:

DELETE From FirstTable 
WHERE FirstTable.EmployeeID NOT IN 
    (
     SELECT SecondTable.EmployeeID 
     FROM SecondTable 
     WHERE SecondTable.Flag = 'Y' 
    ) 

需要沒有循環...


如果問題則是要使用預先現有的存儲過程做刪除,再就是幾個可能性:

首先,你可以提取存儲過程的內容,並重新寫入他們爲這些前面的WHERE條件。我知道這是代碼重複,它違反了一些人的DRY本能,但是,要理解SQL是而不是面向對象的開發環境,有時候代碼重複必須發生。

第二種選擇是重構存儲過程,以便它可以接受一個TableParameter來爲其EmployeeId的Delete。雖然這很複雜,但我們需要查看該存儲過程以便爲其提供建議。

第三種選擇是使用字符串聚集來構建動態SQL調用存儲過程的每個僱員將被刪除,像這樣:

DECLARE @sql As NVarchar(MAX); 
SET  @sql = N''; 

SELECT @sql = @sql + ' 
    EXEC YourProc ''' + CAST(EmployeeID As NVARCHAR(MAX)) + '''; ' 
FROM FirstTable 
WHERE FirstTable.EmployeeID IN 
    (
     SELECT SecondTable.EmployeeID 
     FROM SecondTable 
     WHERE SecondTable.Flag = 'Y' 
    ) 

EXEC(@sql); 

這樣就避免了兩成環和Cusror問題,雖然許多也不喜歡它。我更喜歡這個解決方案,主要是因爲它的一般性。

+0

對不起,缺乏信息。第二個表中有僱員的號碼。但是,有一個標誌欄表示他們不再活躍。所以我認爲如果我將內部select語句where子句設置爲「WHERE isActive ='Y'」,這仍然可以工作。 –

+0

是的,內部where子句將起作用。我將在我的帖子中回答其餘部分... – RBarryYoung

+0

這是要執行table1中每行的內部select語句嗎?我問的原因是因爲它沒有過濾返回的行,並且內部select語句將爲table1中的每個記錄返回成千上萬的記錄。我還無法測試,或者我會嘗試。但我可以在內部選擇中做到這一點:「Where FirstTable.emp_no = SecondTable.emp_no」? –

3

如果當前員工表中沒有匹配的行,這將刪除員工數據表中的所有記錄。

我sugest您更換DELETE FROMSELECT * FROM,然後當你快樂刪除的結果將其改回DELETE

DELETE FROM 
    EmployeeDataTable 
WHERE 
    NOT EXISTS 
    (SELECT 
     NULL 
    FROM 
     CurrentEmployees 
    WHERE 
     EmployeeDataTable.EmployeeID = CurrentEmployees.EmployeeID 
    ) 

編輯:剛纔看到你的有關活動標誌的評論,這個手段查詢可改爲

DELETE FROM 
    EmployeeDataTable 
WHERE 
    EXISTS 
    (SELECT 
     NULL 
    FROM 
     CurrentEmployees 
    WHERE 
     EmployeeDataTable.EmployeeID = CurrentEmployees.EmployeeID 
     CurrentEmployees.IsActive <> 'Y' 
    ) 
+1

另一個好辦法。 – RBarryYoung

+0

@RBarryYoung感謝您的評論。員工確實存在於另一張表中,但對Y有一個不是euql的標誌,這意味着「NOT EXISTS」可以更改爲「EXISTS」,這更好。我會編輯答案 – Tobsey

+0

謝謝,你回答了我的另一個問題。 :) –

0
  1. 這將是可能的,如果你把從你想你的光標和IM裏面調用存儲過程的內容在您當前的sproc中解釋了邏輯。此時,您應該能夠使用基於集合的邏輯。你打電話的問題非常複雜嗎?
  2. 如何將一個標識列添加到臨時表中?

有時,由於各種原因,光標是正確的解決方案。

2

我會通過循環遊標來做到這一點。您還可以在光標上添加一個唯一的ID,以便您知道當前所在的行。

DECLARE @id uniqueidentifier 
DECLARE @empName VARCHAR(50) 

SELECT newId() AS Id, * 
    INTO #mytemp 
    FROM MyEmployees 
    ORDER BY EmpName 

while EXISTS(SELECT TOP 1 1 FROM #mytemp) 
BEGIN 
    --Get row from cursor to process 
    SELECT TOP 1 @id = Id, @empName = EmpName FROM #mytemp 

    --Do you processing here. Call other stored proc. 

    --Remove processed row from cursor. 
    DELETE FROM #mytemp WHERE Id = @id 
END 
DROP TABLE #mytemp 
+0

爲什麼這會被拒絕?,這個循環結構對我來說工作得很好。我必須承認我的存儲過程不是很快,我用id來傳輸45000條記錄,大約需要4分鐘。我的臨時記錄中有每條記錄表在「處理」區域中導致2或3個更新命令。 – Michiel

1

你有沒有使用MERGE聲明認爲:http://technet.microsoft.com/en-us/library/bb510625.aspx

您有條款:

  1. 當數據同時做兩表
  2. 當源存在的數據之間的匹配,但不在目標中
  3. 當數據存在目標中,但不在源中時

您可以根據匹配類型插入,更新或刪除記錄。您還可以將匹配操作輸出到臨時表以進行其他自定義操作。

舉例來說,你可以這樣做:

MERGE INTO Table1 
USING Table2 ON Table1.EmployeeID = Table2.EmployeeID 
WHEN MATCHED 
    THEN UPDATE SET Table1.SomeField = Table2.SomeOtherField 
WHEN NOT MATCHED BY SOURCE 
    THEN DELETE 
WHEN NOT MATCHED BY TARGET 
    THEN Insert (Name, Status) VALUES (EmployeeName, 'Active') 
+0

我只需要刪除,而不是插入或更新。另外我正在使用SQL Server 2005 :) –

+0

好的。如果不使用最新版本,或者至少有5年以來沒有過期,那麼您應該指定您在問題中使用的SQL Server版本;-) –

+0

代碼看起來相當簡單。不幸的是,我無法讓它在MS SQL Server 2008 R2上運行。哪些SQL Server版本支持此語法? – Michiel

相關問題