Reputation: 149
I have been trying to learn some basic SQL and have been working with an imaginary project in order to learn the ropes.
My database has been constructed like this:
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,
)
I've managed to execute the following query:
INSERT INTO Administrators
VALUES ('A001', (SELECT Employees.Id FROM Employees
INNER JOIN People
ON People.Email = @email))
But when I call this procedure:
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
With this code:
(The p-variable is an instance of the class "administrator" sent to the method. Administrator inherits from person).
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();
}
I get the following error:
Violation of UNIQUE KEY constraint 'UQ__Employee__7AD04F1040881669'."
(It's the employeeCode
, apparently.)
And I just don't understand why. SQL always adds a new admin, as expected, but the exception makes my business-logic crash.
Right now my code just swallows this in an empty catch... but I still know it's there... lurking...
Anyone got any idea why?
Upvotes: 0
Views: 87
Reputation: 149
It seems I've made a logic error when writing my C#.
if (person is Administrator)
{
NewPersonProcedureCall("InsertNewAdministrator", person);
}
if (person is Employee)
{
NewPersonProcedureCall("InsertNewEmployee", person);
}
So my method is called right after an employee has been created. Made a quick fix.
if (person is Administrator)
{
NewPersonProcedureCall("InsertNewAdministrator", person);
}
else if (person is Employee)
{
NewPersonProcedureCall("InsertNewEmployee", person);
}
So the validation-error is logical since the employee exists. Sorry people!
Upvotes: 0
Reputation: 1270873
Administrators
has three columns. When you write:
INSERT INTO Administrators
VALUES ('A001', (SELECT Employees.Id FROM Employees
INNER JOIN People
ON People.Email=@email))
You are really writing Administrators(ID, AdministratorCode, EmployeeId)
. I have no idea why this works when you run it. You are missing a column.
Instead, when you use insert
, always list the columns (there is very occasionally an except to this, but definitely not in this simple case). Because the first column is an identity, you do not need to assign it.
Second, your join
is missing a join
condition between the two tables. In general, you should have at least one equality condition between two tables in an on
clause. This is not required and there are exceptions, but for simple cases like this, remember the rule.
You should also learn insert . . . select
syntax -- it is more powerful than insert . . . values
. I'm guessing that you intend:
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;
Upvotes: 2