Insert row with same key after delete throws key constraint error - sql-server

I have a situation where we need to change an employee record to have a different ID. I've deleted the record that caused this, and intend to move the still intact record to the new ID.
However when I attempt to do the insert, I'm getting a key constraint error.
Msg 2627, Level 14, State 1, Line 1
Violation of PRIMARY KEY constraint 'PK_Employee'. Cannot insert duplicate key in object 'dbo.Employee'. The duplicate key value is (2682).
Upon reading, I understand that I'd need to rebuild indexes to accomplish this. I've done this for the non clustered indexes on the table. Does this also need to be done for the clustered indexes?
Edited to include SQL query and insert:

With that SELECT statement you're using to select the rows to be inserted (without any WHERE clause), you're inserting ALL the existing employees back into the table again.
While the first INSERT with ID = 2682 will work (since the entry with ID = 2682 has been removed before that), once SQL Server tries to insert the second employee fetched in the SELECT, also with ID = 2682, it will **fail ** (since there's already a new entry with that ID) ...

Related

Violation of PRIMARY KEY constraint 'PK_Address'. etc...what am I doing wrong?

Evening all. I am fairly new to SQL but have been doing quite a bit of fooling around. I am following a guide I found online to learn SQL in 21 days and I am having a bit of trouble figuring out what the error I am receiving is causing.
I am trying to INSERT data into an existing table. The Primary Key for this table is AddressID. The data I am trying to enter is in the code below:
INSERT INTO [dbo].[Address]
(AddressID,Street,City,State,ZipCode)
VALUES
(1,'2400 Broadway','New York','NY',11201),
(2,'320 21st Street','Atlanta','GA',303),
(3,'439 Skyline Blvd','Seattle','WA',98101),
(4,'56 Park Avenue','Dallas','TX',75201);
GO
I keep getting this error:
Msg 2627, Level 14, State 1, Line 2 Violation of PRIMARY KEY
constraint 'PK_Address'. Cannot insert duplicate key in object
'dbo.Address'. The duplicate key value is (1).
I have tried just about everything I can think of but I am unable to get my table updated. My column names at under the INSERT INTO portion are correct and my VALUES are also correct. I did find that I can use a single INSERT statement to get my data in the table. Originally I was using 4 separate statements.
What am I doing wrong?
In this case I think it's safe to let the database choose the primary key by not specifying it. There's probably already data in the table.
INSERT INTO [dbo].[Address]
(Street,City,State,ZipCode)
VALUES
('2400 Broadway','New York','NY',11201),
('320 21st Street','Atlanta','GA',303),
('439 Skyline Blvd','Seattle','WA',98101),
('56 Park Avenue','Dallas','TX',75201);
GO
From the error message it is very clear that already AddressID = 1 exist in the table since you have a primary key on AddressID you cannot insert duplicate values.
Try this query to insert into the table
INSERT INTO [dbo].[Address]
(Street,City,State,ZipCode)
SELECT Street,City,State,ZipCode
FROM ( VALUES (1,'2400 Broadway','New York','NY',11201),
(2,'320 21st Street','Atlanta','GA',303),
(3,'439 Skyline Blvd','Seattle','WA',98101),
(4,'56 Park Avenue','Dallas','TX',75201))
v(addressid, street, city, state, zipcode)
WHERE NOT EXISTS (SELECT 1
FROM [dbo].[address] A
WHERE a.addressid = v.addressid)
If addressid columns has identity property then remove the addressid column from insert column list and select list.
What you doing wrong is:
You already have AddressId (1) in your table Address table.
Primary key should be unique. You cannot insert duplicate values in the primary key column.
What you can probably do is:
update the existing value and insert the new values. That means update the row with AddressId 1 and insert new rows with new AddressIds.
It's better you let the Sql Server decide on your primary key value by creating `identity column'. You could create identity column while creating a table as follows:
CREATE TABLE [dbo].[Address]
(
[AddressId] [int] IDENTITY(1,1) NOT NULL,
[OtherColumns] [int] NULL,
CONSTRAINT [PK_Address] PRIMARY KEY CLUSTERED (AddressId ASC)
)
Please note that, if you have created a table with Idenity column, you do not need to supply any values during insert operation because Sql Server implicitly creates and inserts that values for you.
Primary Keys have to be unique. If AddressID is your primary key you cannot have two rows in your table that have the same AddressID number. Primary Keys are usually set automatically so you don't have to set them yourself.
Think of the Primary Key as a unique identifier for each row. The duplicate key error is telling you that you already have a row in your address table that has an AddressID value of 1. To avoid these errors you should set your AddressID column to IDENTITY and not worry about setting the value. Try inserting your records without setting the AddressID. Something like so:
INSERT INTO [dbo].[Address]
(Street,City,State,ZipCode)
VALUES
('2400 Broadway','New York','NY',11201),
('320 21st Street','Atlanta','GA',303),
('439 Skyline Blvd','Seattle','WA',98101),
('56 Park Avenue','Dallas','TX',75201)
('56 Park Avenue','Dallas','TX',75201);
GO

How to delete record in Parent table without affecting the Child table?

I have 2 tables in my database, Table A and Table B.
Table A is a Master table and table B is a Transaction table. Table B have Foreign Key (IdTableA)
Example :
I already have a record in table B with IdTableA in it.
INSERT INTO Table_B VALUES (IdTableB, IdTableA, 500000);
and when I tried to delete record in Table A which is IdTableA there is an error.
I want to delete a record in Table A without affecting record in Table B
what should i do ? is it possible ?
You didn't post the error message, but most likely the IdTableA column is a foreign key to Table A. That means a row in Table A can't be deleted if any row in Table B references that row. There is no way to get around this except to permanently remove the foreign key.
The purpose of a foreign key is to prevent exactly this scenario. It prevents data integrity problems where rows would otherwise make no logical sense because other rows they reference do not actually exist.
http://en.wikipedia.org/wiki/Foreign_key

Can a trigger on a table with a primary key ever be fired with the same primary key appearing twice in either the inserted or deleted table?

If I have a table, T, with a primary key, ID,
CREATE TABLE T (
ID INT NOT NULL PRIMARY KEY,
Data BIT NOT NULL DEFAULT (0)
)
and create an after insert trigger on it
CREATE TRIGGER T_Trigger ON T
FOR INSERT, UPDATE, DELETE
AS
BEGIN
-- Trigger body
END
is it ever possible that the INSERTED table will have duplicate values for the ID column? Or for the DELETED table to have duplicate values for the ID column?
Clearly it's possible for the ID to appear once in each of the INSERTED and DELETED tables.
I can't imagine a DML statement that could lead to a trigger firing with the same primary key occurring twice in either the INSERTED or DELETED table. Even MERGE is carefully documented to say that "The MERGE statement cannot update the same row more than once, or update and delete the same row." The PRIMARY KEY constraint on ID and the limited power of each DML statement seem like they should combine to keep it unique in each trigger firing.
No. The INSERTED and DELETED tables are the final (i.e. "after") state of the operation, in terms of FOR / AFTER triggers. For INSTEAD OF triggers, the INSERTED and DELETED tables are what would have been the final state. Well, the DELETED table is really the prior state of those rows whereas INSERTED is the current state.

foreign key data deletion should display error for primary key

i have two tables Table1 and Table2. Where table1 column primary key is referred to table2 column as foreign key.
Now i have to display a error message of constraint violation when ever i delete records from table2 which is having foreign key column of table1.
If I get it right your column A (say) in table 1 references column B (say) in table 2.
What you can do is set the ON DELETE to NO ACTION which will prevent deletion of records from table 2 if any children of it still exists in table 1.
You can can do this by:
ALTER TABLE TABLE1 ADD FOREIGN KEY (A) REFERENCES TABLE2 (B) ON DELETE NO ACTION;
You don't have a constraint violation if you delete records from the child table and not the parent. It is normal to delete child records. For instance if I have a user table and a photos tables that contains the userid from the users table, why would I want to stop that action and throw an error if I want to delete a photo? Deleting a child record doesn't also delete the parent.
If you really want to do that, then you must do it through a trigger (make sure to handle multiple record deletes) or if the FK is a required field, then simply don't grant permissions to delete to the table. Be aware that this may mean you can never delete any records even when you try to delete. A simple method may be to not have a delete function available in the application.
I suspect what you really need to a to get a better definition of what is needed in the requirements document. In over 30 years of dealing with hundreds of databases, I have never seen anyone need this functionality.

Create PK for #temp table failed when the script is run in parallel

I have the following code in a stored procedure.
....
select ... into #temp from ....
alter table #temp add constraint PK_mytemp13 primary key (....)
....
And I will get the following error message from time to time if the stored procedure is run in parallel.
There is already an object named 'PK_perf322dsf' in the database.
Could not create constraint. See previous errors.
I think it can be avoid by the following approaches. Is there any other more elegant solution?
Create a temp table with primary key first. Then insert the rows.
create table #temp (... primary key (....))
Create PK dynamically with session id dynamically.
declare #s varchar(500) = 'alter table #temp add constraint PK_temp' + ##spid + ' primary key (....)
This can only happen if the same client connection instantiation (which equals one SPID or connection in SQL Server) is being re-used for 2 different calls. Two parallel calls should have different connection instantiations and separate SPIDs
SPIDs are completely isolated from each other with local (single #temp tables)
Edit:
Ignore above
I've never named constraints on temp tables before. I use indexes as I need them or just add PRIMARY KEY after the column. Constraint names are database-unique in sys.objects
A PK is basically a non-unique clustered index. So use CREATE UNIQUE CLUSTERED INDEX instead as index names are unique per table in sys.indexes.
This fails when run in 2 SSMS Query windows
CREATE TABLE #gbn (foo int NOT NULL);
ALTER TABLE #gbn ADD CONSTRAINT PK_gbn PRIMARY KEY (foo);
Msg 2714, Level 16, State 5, Line 2
There is already an object named 'PK_gbn' in the database.
Msg 1750, Level 16, State 0, Line 2
Could not create constraint. See previous errors.
Curiously, the error and the constraint name match unlike your error
This works
CREATE TABLE #gbn (foo int NOT NULL);
CREATE UNIQUE CLUSTERED INDEX PK_gbn ON #gbn (foo);
I was trying to remember how to do this, but you can create a nameless primary key on a temp table and avoid this error. This is different than putting a column-level PK, as it supports more than 1 column. Here is an example:
CREATE TABLE #test
(
AccountNumber INT NOT NULL,
TransactionNumber INT NOT NULL,
PRIMARY KEY CLUSTERED (tranid, sys_process_dt)
);
This allows the end goal plus prevents name duplication. Querying will show that SQL Server will put a GUID in the name of the PK for you in sys.sysobjects:
SELECT *
FROM tempdb.sys.sysobjects
WHERE name LIKE '%#test%'
name | xtype
--------------------------------
#test___..._000000000407 | U
PK__#test_____B88A05A770B3A6A6 | PK
You can have your cake and eat it too.
you try to insert to the same temporary table from different connections (which is impossible, instead of global temp tables),
or you try to insert into different tables.
if 2nd - you simply may do the following - ALTER TABLE #temp ADD PRIMARY KEY(...)
if 1st - you have to create the table (regular or global temporary) with key prior to use it in parallel operations
I know this has been answered and accepted but still did not see the correct point has been call out.
when you create Named constraint, name of the constraint has to be precise at table level. they are scoped at database level. so either do not create named constrained and let sql pick its own name or if you give name make sure it s unique in that DB. even for TEMP DB.
Even more to the point, ANY named constraint on a temp table must be uniquely named across sessions. This also means that a default constraint (say you're setting a field to default to a value of -1) and that default constraint is explicitly named, SQL Server will throw an error when you attempt to create a temp table in another session window even though it's not a key constraint.
For example, open two query windows and run the following code in one and then the other (without closing either window first):
DROP TABLE IF EXISTS #TempTbl1;
CREATE TABLE #TempTbl_1 (
[TestCol1] INT
,[TestCol2] BIGINT CONSTRAINT [DF_Tc2] DEFAULT (-1)
);
The first window will execute fine, but the second will throw an error stating
Msg 2714, Level 16, State 5, Line 2
There is already an object named 'DF_Tc2' in the database.
Msg 1750, Level 16, State 1, Line 2
Could not create constraint or index. See previous errors.
This is in spite of the fact that the table has no PKs or indexes, just a named default constraint.

Resources