2016-01-08 118 views
1

確定SQL Server粉絲我有一個遺留存儲過程存在問題,該存儲過程位於SQL Server 2008 R2實例內部,我還繼承了至少可怕的PROD數據。另外,我不能對數據和表格結構進行任何更改。TSQL更新問題

所以這裏是我的問題,有問題的存儲過程每天運行並用於更新employee表。從我的示例中可以看到,傳入數據(#New_Employees)包含更新的數據,我需要使用它來更新Employee中的數據,數據存儲在#Existing_Employees表中。在過去的幾年中,EMP_ID價值的不同格式已被使用,並且必須保持原樣(我戰鬥並且失敗了那場戰鬥)。謝天謝地,我已成功更改#New_Employees表中的EMP_ID列的格式(是的!),並且任何新記錄都會很好地使用這種格式!

所以,現在你可以看到我的問題,我需要從#Existing_Employees表,通過匹配ID以更新#New_Employees表中的列IDEMP_ID列(沒錯,你猜對了)。因此,我想出了一種極其棘手的方式來處理EMP_ID列的不同格式,但考慮到需要處理的行數(1M +),它非常慢。

我想創建一個臨時表,我可以簡單地把EMP_ID列的INT,然後回NVARCHAR每個表中刪除前導零的,我有點傾向這種方式,但我想看看是否還有另一種方式來處理這種功能失調的數據。任何建設性的意見,歡迎。

 IF OBJECT_ID(N'TempDB..#NEW_EMPLOYEES') IS NOT NULL 
      DROP TABLE #NEW_EMPLOYEES 

     CREATE TABLE #NEW_EMPLOYEES(
          ID INT 
          ,EMP_ID NVARCHAR(50) 
          ,NAME NVARCHAR(50)) 
     GO 

     IF OBJECT_ID(N'TempDB..#EXISTING_EMPLOYEES') IS NOT NULL 
      DROP TABLE #EXISTING_EMPLOYEES 

     CREATE TABLE #EXISTING_EMPLOYEES(
          ID INT PRIMARY KEY 
          ,EMP_ID NVARCHAR(50) 
          ,NAME NVARCHAR(50)) 
     GO 

     INSERT INTO #NEW_EMPLOYEES 
     VALUES(NULL, '00123', 'Adam Arkin') 
       ,(NULL, '00345', 'Bob Baker') 
       ,(NULL, '00526', 'Charles Nelson O''Reilly') 
       ,(NULL, '04321', 'David Numberman') 
       ,(NULL, '44321', 'Ida Falcone') 

    INSERT INTO #EXISTING_EMPLOYEES 
     VALUES(1, '123', 'Adam Arkin') 
       ,(2, '000345', 'Bob Baker') 
       ,(3, '526', 'Charles Nelson O''Reilly') 
       ,(4, '0004321', 'Ed Sullivan') 
       ,(5, '02143', 'Frank Sinatra') 
       ,(6, '5567', 'George Thorogood') 
       ,(7, '0000123-1', 'Adam Arkin') 
       ,(8, '7', 'Harry Hamilton') 

     -- First Method - Not Successful 
     UPDATE NE 
      SET ID = EE.ID 
     FROM 
      #NEW_EMPLOYEES NE 
       LEFT OUTER JOIN #EXISTING_EMPLOYEES EE 
        ON EE.EMP_ID = NE.EMP_ID 

     SELECT * FROM #NEW_EMPLOYEES 

     -- Second Method - Successful but Slow 
     UPDATE NE 
      SET ID = EE.ID 
     FROM 
      dbo.#NEW_EMPLOYEES NE 
       LEFT OUTER JOIN dbo.#EXISTING_EMPLOYEES EE 
        ON CAST(CASE WHEN NE.EMP_ID LIKE N'%[^0-9]%' 
         THEN NE.EMP_ID 
         ELSE LTRIM(STR(CAST(NE.EMP_ID AS INT))) END AS NVARCHAR(50)) = 
         CAST(CASE WHEN EE.EMP_ID LIKE N'%[^0-9]%' 
         THEN EE.EMP_ID 
         ELSE LTRIM(STR(CAST(EE.EMP_ID AS INT))) END AS NVARCHAR(50)) 

     SELECT * FROM #NEW_EMPLOYEES 
+1

你可以創建索引視圖來工作嗎?這會給你帶來的好處,即在可能的情況下能夠計算修剪或數字ID值一次併爲其性能建立索引。任何以通配符開頭的'''''模式都將無法使用索引(除了更快的方式執行表掃描)。 [Ref](https://msdn.microsoft.com/en-us/library/dd171921%28SQL.100%29.aspx)和[ref](https://msdn.microsoft.com/en-us/library /ms191432%28v=sql.105%29.aspx)。 – HABO

+0

不,我堅持我所擁有的,他們拒絕做出改變。 –

+1

請投票的人可以解釋一下嗎? –

回答

0

我需要處理(1M +)的行數。

A million million employees?每天?

我想我會添加一個第三表:

create table #ids (id INT not NULL PRIMARY KEY 
        , emp_id not NULL NVARCHAR(50) unique); 

使用LTRIM(STR(CAST,啊哈,算法和更新員工填寫此表直接從連接這三個表。

我建議使用ANSI 更新,不是微軟的非標準update ... from因爲ANSI版本防止在FROM產生多行的情況下不確定性的結果。