2009-06-08 32 views
5

我想用腳本來改變SQL Server中的表。在過去,我總是通過GUI來完成這種事情,但現在我需要生成一個腳本來爲客戶做。使用腳本在SQL Server中的其他列之間插入列

我有一個SQL Server數據庫表是這樣的:

 
MyTable 
------- 
ColA int NOT NULL 
ColB int NOT NULL 
ColC int NOT NULL 
ColD VARCHAR(100) 

主鍵跨可樂,COLB和COLC定義。

我想要的SQL腳本來更改表所示:

 
MyTable 
------- 
ColA int NOT NULL 
ColB int NOT NULL 
ColX int NOT NULL (new column, default 0 for existing data) 
ColC int NOT NULL 
ColD VARCHAR(100) 

主鍵將目前由可樂,COLB,COLX和COLC定義。

這很容易通過SQL Server GUI來完成。但是當我從它那裏生成一個腳本時,它似乎不必要的複雜。基本上,腳本使用新模式創建臨時表,將舊錶中的所有數據,索引和約束複製到臨時表中,刪除舊錶,然後將新表重命名爲舊錶。此外,它有這樣的臺詞:

ALTER TABLE dbo.Tmp_MyTable ADD CONSTRAINT 
    MyTable21792984_ColC_DF DEFAULT ((0)) FOR ColC 

我擔心的是,這些隨機找數有(即21792984)將不會對所有的客戶數據庫實例相同。它們看起來像是SQL Server在創建數據庫時生成的,每個實例都是唯一的。

是否有更簡單的通過SQL命令更改表的方法?我看過網上,但我發現大多是基本的和/或通用的。

更新:從我收到的答案,它看起來像困難在於把新列「之間」兩欄。我意識到,列的順序並不重要(如果我錯了,可以隨時留下一個答案來糾正我)。在我的情況下,如果我只是將列添加到表的末尾,則更改更簡單,代碼中的任何內容都不依賴於特定的列順序。

回答

8

沒有其他方式在SQL Server表「之間」現有列中插入列 - 您需要構建臨時表並重新構建舊錶。也就是說,列順序無關緊要 - 您確定該列需要按順序插入嗎?

可能最好的辦法就是使用GUI,編寫腳本,然後在腳本中將約束名稱更改爲合理的名稱。你說得對,數字約束名稱並不理想,並且允許SQL Server確定你的對象名稱不是一個好習慣。

+0

謝謝,經過進一步檢查,列順序並不重要(美學除外)。只有將列添加到最後才能使其變得更容易。 – Kip 2009-06-08 17:18:40

+0

如果您確實希望更改訂單,則可以使用SQL Compare中的強制列順序來執行此操作。這需要完整的表格重建,所以如果您有大量數據可能需要時間。現有數據將由SQL Compare保存。 – 2010-06-12 10:32:25

3

如果你插入一個字段到表的中間,你必須刪除當前的表並重新創建它,這是SQL服務器正在做什麼。

隨機數字確保約束具有唯一的名稱。如果你保留這個腳本並在多個數據庫上運行它們,那麼它們都是一樣的。如果你要通過gui修改每一個,那麼是的,他們很可能會有所不同。

要修改主鍵,您只需找到主鍵約束名稱並將其刪除即可。只需添加一個定義主鍵的新約束即可。假設您沒有在其他地方將外鍵列爲外鍵。

1

如果你想要這樣的中間列,那就是你必須做的。我發現它生成的腳本非常好,僅包含了一些神奇的作品。

如果你要在最後例如添加一列,你只需要做:

ALTER TABLE ADD COLUMN ColX int NOT NULL DEFAULT(0) 

而且你會看到在它生成的腳本。

只要修改主鍵,它可以被刪除(在所有現有的列上)並重新創建而不用重寫表,但是如果它是聚集的或不是,你可能會得到一個不同的腳本。

1

以示例代碼&對其進行修改。如果你想讓列落在特定的地方,你必須去臨時表重新定義/重命名路線。您也可以按照這種方式命名索引和約束。

1

你用什麼工具生成腳本。我使用Red-Gate Sql compare tool,它的作品非常漂亮。

+0

我只是使用Microsoft SQL Server Management Studio,我認爲它與SQL Server一起提供。 – Kip 2009-06-08 17:15:22

2

如果在您剛纔指定的CREATE TABLE中指定了例如PRIMARY KEY (ColA, ColB, ColC),那麼您告訴SQL Server您並不在意這個約束的名稱,也就是說您不必直接引用它 - 所以SQL Server完全有理由爲它生成一些半隨機看起來的獨特名稱,如MyTable21792984_ColC_DF,這正確地擔心你(儘管該特定的一個似乎是一個ColC特定的單列約束,相同類型的命名將適用於其他約束)。

雖然這個問題可能爲時已晚修爲當前的模式,它會如果你遵循的原則始終命名約束幫助你在未來的 - 因爲它通常是相當可能的,你可能需要參考給他們,所以你希望這個名字完全在你的控制之下,就像任何其他模式對象(表,列等等)的名字一樣。在這種情況下,在CREATE TABLE中使用CONSTRAINT PK_MyTable PRIMARY KEY (ColA, ColB, ColC)這樣的條款會有所幫助。 (如果您用於DBA任務的GUI工具不允許您控制這類事情,那麼它們不適合DBA的合適工具:找到更好的工具 - )。

+0

不幸的是,我正在接觸現有數據,因此我無法控制數據庫的創建方式。但他們至少將其主鍵一致地命名爲PK_TableName。 – Kip 2009-06-08 17:26:59

2

依賴於數據庫表中任何列的「自然」或「固有」排序是不好的做法。所有列在任何官方生成的查詢中按名稱引用,以按查詢指定的順序按名稱返回列。如果未遵循該規則,則任何未來的模式更改都是絕對的噩夢,因爲每次更新數據庫模式時可能需要更改系統代碼。

這裏唯一令人討厭的事情是在用戶手動編碼的生產/測試/開發數據庫上運行使用SELECT * FROM ...的一次性查詢,並讓您的新列顯示在列列表的末尾。不過,我相信很多查詢工具可以讓你重新排列來自某種GUI的列。

3

我只想指出爲什麼你永遠不想使用GUI在現有表的中間插入一列。當你這樣做時,創建一個speatare新表,移動舊錶中的數據,重命名舊錶,將新表重命名爲舊錶名並刪除舊錶。如果你有一個小數據庫,這已經夠糟糕了。在桌子可能很大的生產環境中,您可能會將用戶鎖定在桌子上幾個小時。在添加新列時需要重新排列數據庫中列的順序的任何數據庫設計都是一個以災難爲導向的數據庫。因爲有人堅持這樣做,這也是Select *也是一個等待發生的問題的另一個原因。你真的不希望狀態出現在報表的壓縮列中,因爲有人重新排列了表中的列,並且依賴於列順序中的select *。

0

將新列添加到現有表中(將其添加到所有列的末尾) 然後使用此表創建一個新表,並在用於構建新表的子查詢中提及列你希望他們在新表中的順序..

例:

create table person(name varchar2(10),age number); 
alter table person add salary number; (now salary is added at last position) 
desc person 
name ... 
age ... 
salary ... so now salary is at the end. 

現在說我想用這個人表創建EMPLOYEE表。

create table employee as select name,salary,age from person; 

當您描述員工表時,它具有與人員表一樣的定義以及數據。

相關問題