2015-02-08 123 views
0

我一直在嘗試學習一些基本的SQL,並且一直在用一個想象中的項目來學習繩索。爲什麼違反UNIQUE KEY約束會發生?

我的數據庫已經建成這樣的:

CREATE TABLE [dbo].[People] 
(
    [Id] [int] PRIMARY KEY IDENTITY(1,1) NOT NULL, 
    [SocialSecurityNumber] [nvarchar](13) NOT NULL, 
    [FirstName] [nvarchar](50) NOT NULL, 
    [LastName] [nvarchar](50) NOT NULL, 
    [Email] [varchar](50) NOT NULL 
) 

CREATE TABLE [dbo].[Employees] 
(
    [Id] [int] PRIMARY KEY IDENTITY(1,1) NOT NULL, 
    [EmployeeCode] [varchar](50) NOT NULL, 
    [PersonId] [int] FOREIGN KEY REFERENCES People (Id) NOT NULL 
) 

CREATE TABLE [dbo].[Administrators] 
(
    [Id] [int] PRIMARY KEY IDENTITY(1,1) NOT NULL, 
    [AdministratorCode] [varchar](50) NOT NULL, 
    [EmployeeId] [int] FOREIGN KEY REFERENCES Employees (Id) NOT NULL, 
) 

我已經成功地執行以下查詢:

INSERT INTO Administrators 
VALUES ('A001', (SELECT Employees.Id FROM Employees 
          INNER JOIN People 
          ON People.Email = @email)) 

但是,當我把這個過程:

CREATE PROCEDURE [dbo].[InsertNewAdministrator] 
(
    @email VARCHAR(50), 
    @administratorCode VARCHAR(50) 
) 
AS 
BEGIN 
    SET NOCOUNT ON 

    INSERT INTO Administrators 
    VALUES (@administratorCode, (SELECT Employees.Id 
           FROM Employees 
           INNER JOIN People ON People.Email = @email)) 
END 

使用此代碼:

(p變量是發送到方法的類「管理員」的實例。管理員繼承人)。

using (var conn = new SqlConnection(connectionString)) 
using (var command = new SqlCommand(procedureName, conn)) 
{ 
    if (procedureName == "InsertNewAdministrator") 
    { 
     var a = p as Administrator; 
     command.Parameters.Add(new SqlParameter("@administratorCode", a.AdministratorCode));       
    } 
    else if (procedureName == "InsertNewEmployee") 
    { 
     ... 
    } 
    else 
    { 
     ... 
    } 

    command.Parameters.Add(new SqlParameter("@email", p.Email)); 
    command.CommandType = CommandType.StoredProcedure; 

    conn.Open(); 
    command.ExecuteNonQuery(); 
} 

我得到以下錯誤:

Violation of UNIQUE KEY constraint 'UQ__Employee__7AD04F1040881669'."

(這是employeeCode,顯然)

而我只是不明白爲什麼。按照預期,SQL總是添加一個新的管理員,但異常會導致我的業務邏輯崩潰。

現在我的代碼只是燕子一個空的捕捉...但我仍然知道它的存在... ...潛伏

任何人有任何想法,爲什麼?

+0

您是否向我們展示了DDL中的所有內容?似乎有一個唯一的關鍵指標被遺漏。 – 2015-02-08 15:16:05

+0

這種爲我解決了它。讓我看起來更多。原來是一個邏輯錯誤。打擾我... – Ize 2015-02-08 15:35:35

回答

0

看來我編寫我的C#時犯了一個邏輯錯誤。

if (person is Administrator) 
{ 
NewPersonProcedureCall("InsertNewAdministrator", person); 
} 
if (person is Employee) 
{ 
NewPersonProcedureCall("InsertNewEmployee", person); 
} 

所以我的方法是在創建員工後立即調用的。做了一個快速修復。

if (person is Administrator) 
{ 
NewPersonProcedureCall("InsertNewAdministrator", person); 
} 
else if (person is Employee) 
{ 
NewPersonProcedureCall("InsertNewEmployee", person); 
} 

所以驗證錯誤是合理的,因爲員工存在。對不起人!

2

Administrators有三列。當你寫:

INSERT INTO Administrators 
    VALUES ('A001', (SELECT Employees.Id FROM Employees 
           INNER JOIN People 
           ON [email protected])) 

你真的寫的Administrators(ID, AdministratorCode, EmployeeId)。我不知道爲什麼當你運行它時會起作用。您錯過了一列。

取而代之,當您使用insert時,請始終列出列(除非是這種情況,否則絕對不會出現這種情況)。因爲第一列是一個身份,所以你不需要分配它。

其次,join缺少兩個表之間的join條件。通常,在on子句中,兩個表之間至少應該有一個相等條件。這不是必需的,但也有例外,但對於這樣的簡單情況,請記住規則。

您還應該學習insert . . . select語法 - 它比insert . . . values更強大。我猜你打算:

INSERT INTO Administrators(AdministratorCode, EmployeeId) 
    SELECT 'A001', e.Id 
    FROM Employees e INNER JOIN 
     People p 
     ON p.id = e.PersonId 
    WHERE p.Email = @email; 
+0

有效分數。我會窺視你前進的建議。 – Ize 2015-02-08 15:26:37