2014-07-11 62 views
0

假設我們有下面的數據塊(SQL表):無法插入重複鍵:MySQL來SQL服務器

Col-A Col-B Col-C Col-D 
    1  1  1  1 
    1  1  1  2 
    1  1  1  3 
    2  2  2  4 
    2  2  2  5 

在MySQL表中被定義爲:

CREATE TABLE `my_table` (
    `Col-A` INT(10) UNSIGNED NOT NULL DEFAULT '0', 
    `Col-B` INT(10) UNSIGNED NOT NULL DEFAULT '0', 
    `Col-C` INT(10) UNSIGNED NOT NULL DEFAULT '0', 
    `Col-D` INT(10) UNSIGNED NOT NULL DEFAULT '0', 
    PRIMARY KEY (`Col-A`, `Col-B`, `Col-C`), 
    KEY `my_index` (`Col-D`) USING BTREE 
); 

我需要將MySQL數據庫轉換爲SQL Server。這是我最初的嘗試:

CREATE TABLE my_table (
    Col-A INT NOT NULL DEFAULT(0), 
    Col-B INT NOT NULL DEFAULT(0), 
    Col-C INT NOT NULL DEFAULT(0), 
    Col-D INT NOT NULL DEFAULT(0), 
    CONSTRAINT my_pk PRIMARY KEY NONCLUSTERED (Col-A, Col-B, Col-C) 
) 

CREATE INDEX my_idx ON my_table(Col-D) 

當我嘗試導入數據(我用bcp),出現以下錯誤:

Cannot insert duplicate key ... The duplicate key is (1, 1, 1) 

我懷疑這東西是錯誤的my_pkmy_idx定義。任何指針或建議?

+1

這條消息對我來說很清楚嗎?您的數據有多個記錄,列A,B和C分別爲1,1,1。這些組合應該是唯一的,以便能夠充當主鍵,但顯然前3個和後2個記錄包含多行,獨特的價值。修復或刪除主鍵約束並創建(集羣或非集羣)索引。爲什麼MySQL首先允許這些數據進入表中(除非主鍵稍後添加,而MySQL沒有檢查已經存在的值)。 (你也可以擴展PK來包含col-D) – RobIII

+1

當然,你的數據組合1,1,1在你的數據中是三次的,所以它不能滿足'PRIMARY KEY'約束。丟棄重複數據或丟棄主鍵。 – Quassnoi

+0

但爲什麼在MySQL中起作用? – Andrej

回答

2

你知道主鍵的定義嗎?

http://en.wikipedia.org/wiki/Primary_key

在數據庫設計的關係模型中,一個唯一的密鑰或主鍵是一組其值唯一地定義每一行的特徵屬性。

當上校-A +的Col-B +的Col-C的組合唯一你違反了主鍵約束,因此SQL服務器不會允許它。

的選項有:

  1. 擴展PK到包括Col-d
  2. 掉落的PK和使用上的Col-A(羣集或不)指數,色柱-B和Col-C
  3. 修正數據,這樣就不會違反PK約束(既可以丟棄記錄或改變/糾正不正確的記錄)
  4. 添加synthetic (or surrogate) key(見mrjoltcola's answer

選擇哪個選項取決於您的要求。我們無法僅根據您的問題中的信息回答您的問題。

爲什麼MySQL允許這些數據首先進入... *聳聳肩* MySql是一個「有趣」的野獸。也許PK約束是在數據已經在表中之後添加的,也許它是一個非常舊的版本,也許你使用的是MyISAM而不是InnoDB。我不確定是哪一個,但是每個原因(或它們的組合)都是一個很好的猜測,或者至少在某些時間/版本之前是不錯的猜測。無論哪種方式:它不應該已成爲可能(即使PK約束後來添加; MySQL應該拒絕添加它,因爲表中的數據是衝突的),但MySQL已經,並且確實有,它有自己奇怪的方式對這些事情的推理。嚴格模式有助於我記得正確,但我不記得是否只適用於InnoDB表或MyISAM等。無論哪種方式;他們在當天就把它搞得一團糟;我(或你)不必擔心記住潛在的MyISAM/InnoDB/Whatevs等的差異。或者哪個特定的版本允許什麼(不)發生,或者如果你需要嚴格模式或者不需要這樣或那樣的基本的東西,如PK的正常工作*

*每個RDBMS有它的怪癖;我確信有些開關/切換/設置/ whatevs可以調整一些細節,我說PK無論如何都應該是PK的。

1

對於您的數據要求,您不能使用cols(A,B,C)作爲主鍵。您需要將(D)添加到密鑰,或添加代理鍵。爲什麼請參閱RobIII的回答https://stackoverflow.com/a/24703970/257090

我建議你去後者,添加一個ID主鍵,讓您擁有一個單場關鍵:

CREATE TABLE my_table (
    ID INT IDENTITY PRIMARY KEY, 
    ColA INT NOT NULL DEFAULT(0), 
    ColB INT NOT NULL DEFAULT(0), 
    ColC INT NOT NULL DEFAULT(0), 
    ColD INT NOT NULL DEFAULT(0), 
    UNIQUE(ColA,ColB,ColC,ColD) 
) 


INSERT INTO my_table(cola, colb, colc, cold) VALUES(1,1,1,1) 
INSERT INTO my_table(cola, colb, colc, cold) VALUES(1,1,1,2) 
INSERT INTO my_table(cola, colb, colc, cold) VALUES(1,1,1,3) 
INSERT INTO my_table(cola, colb, colc, cold) VALUES(2,2,2,4) 
INSERT INTO my_table(cola, colb, colc, cold) VALUES(2,2,2,5) 

SELECT * FROM my_table 
ID   ColA  ColB  ColC  ColD 
----------- ----------- ----------- ----------- ----------- 
1   1   1   1   1 
2   1   1   1   2 
3   1   1   1   3 
4   2   2   2   4 
5   2   2   2   5 

(5 row(s) affected) 

現在,我可以通過一個鍵值標識每一行。

delete from my_table where ID = 5 

這對於您針對您使用的數據庫或ORM編寫的任何代碼而言更實用。

注意:使用代理(或合成鍵),添加任何其他約束以強制實際數據的數據完整性仍然很重要。代理鍵不會阻止您多次插入1,1,1,1,因此除了主鍵ID之外,還要爲這些字段添加唯一的約束/索引。

+1

也稱爲「合成密鑰」。我只是把它添加到我的答案中;我引用了你的(例如這個)答案。 – RobIII