为什么会发生违反UNIQUE KEY约束的情况?

时间:2015-02-08 15:10:01

标签: c# sql sql-server database

我一直在尝试学习一些基本的SQL,并且一直在处理一个想象中的项目,以便学习绳索。

我的数据库构造如下:

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();
}

我收到以下错误:

  

违反UNIQUE KEY约束' UQ__Employee__7AD04F1040881669'。"

(显然是employeeCode。)

我只是不明白为什么。 SQL总是按预期添加一个新的管理员,但异常使我的业务逻辑崩溃。

现在我的代码只是吞下了一个空的捕捉......但我仍然知道它在那里......潜伏......

任何人都知道为什么?

2 个答案:

答案 0 :(得分:2)

Administrators有三列。当你写:

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

你真的在写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;

答案 1 :(得分: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);
}

因此,员工存在,验证错误是合乎逻辑的。对不起人!