2013-03-09 12 views
0

我有一個表MyTable的數據是這樣的:如何用適當的ISO國家更新表格?

[Production],[Region Country],[CustID] 
computer,US,123 
phone,CA,321 
shirt,NZ,111 

我想要做的是改變的2個字母國家代碼(ISO)將其全國名在該表中的所有記錄(300萬條記錄)。

我有一個表Countries有所有的2個字母的國家代碼和他們的「全名」..所以我可以查看這張表更新。

CREATE TABLE [dbo].[Countries](
[NumericalCode] [char](3) NOT NULL, 
[CountryNameLowerCase] [nvarchar](50) NOT NULL, 
[CountryNameUpperCase] [nvarchar](50) NOT NULL, 
[ISO_ALPHA3] [char](3) NOT NULL, 
[ISO_ALPHA2] [char](2) NOT NULL 
) ON [PRIMARY] 

US,將有這樣的數據:

840,United States of America,UNITED STATES,USA,US 

最終的結果將是一個過程,着眼於MyTable的記錄,和更新基於Countries表它的全名Region Country(中列CountryNameLowerCase)。

這樣做的最佳方式是什麼(性能明智)?

+0

對不起,關於..全名是「CountryNameLowerCase」。 – exxoid 2013-03-09 20:31:15

+0

包含所有ISO國家/地區數據的表稱爲「國家/地區」。 – exxoid 2013-03-09 20:34:03

回答

3

最簡單的方法是使用UPDATEJOIN單一,強力更新:

UPDATE m 
    SET [Region Country] = c.CountryNameLowerCase 
    FROM dbo.MyTable AS m 
    INNER JOIN dbo.Countries AS c 
    ON m.[Region Country] = c.ISO_ALPHA2; 

現在,它可能是這樣的更新會生成日誌的大量,以及頁面拆分因爲您將更多信息擠入每一行(如果使用數據壓縮,還會考慮開銷)。在某些情況下,分批執行更新可能會更好,例如,一個方法是將光標每個國家組合(這將工作最好的,如果你的國家都分佈相對均勻,但幫助不大,如果90%的數據是US):

DECLARE @old NVARCHAR(255), @new NVARCHAR(255); -- use the right type here 

DECLARE c CURSOR LOCAL FAST_FORWARD 
    FOR SELECT m.[Region Country], c.CountryNameLowerCase 
    FROM dbo.MyTable AS m 
    INNER JOIN dbo.Countries AS c 
    ON m.[Region Country] = c.ISO_ALPHA2 
    GROUP BY m.[Region Country], c.CountryNameLowerCase; 

OPEN c; 

FETCH NEXT FROM c INTO @old, @new; 

WHILE @@FETCH_STATUS = 0 
BEGIN 
    BEGIN TRANSACTION; 

    UPDATE dbo.MyTable 
    SET [Region Country] = @new 
    WHERE [Region Country] = @old; 

    COMMIT TRANSACTION; 

    -- experiment with CHECKPOINT if simple 
    -- or BACKUP LOG if full. This will depend 
    -- on your current log size and autogrow 
    -- settings; it can make things worse. 

    --CHECKPOINT; 
    --BACKUP LOG yourdb TO DISK ...; 
END 

另一種方式限制行數,例如替換代碼的相關部分,以這樣的事情,你在哪裏有時間限制的更新,說,1000行:

DECLARE @rc INT; 

WHILE @@FETCH_STATUS = 0 
BEGIN 

    SET @rc = 1; 

    WHILE @rc <> 0 
    BEGIN 
    BEGIN TRANSACTION; 

    UPDATE TOP (1000) dbo.MyTable 
     SET [Region Country] = @new 
     WHERE [Region Country] = @old; 

    SET @rc = @@ROWCOUNT; 

    COMMIT TRANSACTION; 
    END 

的關鍵是要保持個人事務簡短。更新所有300萬行可能是可以容忍的(取決於你何時執行這項工作 - 例如非工作時間,維護窗口等),但是有幾種技巧可以將這些更新批量分塊並最大限度地降低對事務日誌和併發性的影響。在某些情況下,這種分塊會使更新花費更長的時間,但不是全部,通常速度不是主要關注的問題(因爲您會發現第一次鎖定更新整個表的系統時)。

(順便說一句,現在正在寫關於這類事情的博客文章。)

+0

有趣。我經常需要執行像這樣的巨大更新,但我通常有一個主鍵來處理,即。 '鍵<@Count AND key> = @ Count'。但是,我更喜歡你的'@@ ROWCOUNT'方法,將來會嘗試使用它。您是否也可以在我的方法中包含性能指標?真的很期待博客文章。 – 2013-03-09 23:49:55

+0

@JLo我不太喜歡關鍵範圍方法 - 因爲這些關鍵字通常基於IDENTITY列是自然鍵,所以確定在1-1000,1001-2000等之間存在多少實際行非常困難。 ,我不可能對您的架構,數據,硬件等的性能指標發表評論。這是您不得不測試的內容。 – 2013-03-09 23:51:42

相關問題