Replacing a varchar FK with a new Int FK in SQL Server - sql-server

I have two tables which we will call Event and EventResponse
Event has PK eventGuid varchar(36) and several other columns
EventResponse has FK eventGuid varchar(36) and other columns
I can easily add an INT identity column to Event with:
ALTER TABLE dbo.[Event]
ADD eventId INT IDENTITY;
And adding a column to EventResponse table is Ok.
How do I update all the eventIds in the response table?
Is this possible with a neat query or do I have to loop through?
Final state should be:
Event has PK eventId, eventGuid varchar(36), other columns
EventResponse has FK eventId, eventGuid varchar(36), other columns

No looping required. Words to live by :)
This should be just about all you need. Use your existing foreign key to update the values for your new key, then drop the old relationship and add the new one.
UPDATE er
SET er.eventID = e.eventID
FROM
dbo.EventResponse AS er
JOIN
dbo.Event as e
ON er.eventGuid = e.eventGuid;
GO
ALTER TABLE dbo.EventResponse
DROP CONSTRAINT <FK_Name>
GO
ALTER TABLE dbo.EventResponse
ADD CONSTRAINT <FK_Name> FOREIGN KEY (eventId)
REFERENCES dbo.Event(eventId)
[ON DELETE CASCADE
ON UPDATE CASCADE]
GO
Then, probably, if you want to save some space in your database:
ALTER TABLE dbo.Event
DROP COLUMN eventGuid;
GO
ALTER TABLE dbo.EventResponse
DROP COLUMN eventGuid;
GO

try this:
update a set a.eventId=b.eventId
from EventResponse a
inner join Event b on a.eventGuid = b.eventGuid

Related

Alter sql server table Issue

I already created table in database. Now, I need to add "Identity" Column. Please suggest.
Create Cus(id int Pk,Name varchar2(50),Age int);
insert into Cus(id,Name,Age) values (1,'abc',12);
// here i need to add "Identity"
alter table Cus alter column id Identity(1,1)
You cannot use Alter command to add an identity to the table.
Here, you need to create dummy column and drop existing one.
Create table Cus(id int ,[Name] varchar(50),Age int);
insert into Cus(id,[Name],Age) values (1,'abc',12);
Alter Table Cus Add dummyid int identity(1,1)
Alter Table Cus Drop Column id
Exec sp_rename 'Cus.dummyid ', 'id', 'Column'
No you cannot make any column identity after creating from the query.
You have 2 options, either make it from SQL Management Studio or Create another column and copy with identity .
From Management Studio.
Step 1: Select Table design.
Step 2: Change Column properties.
Step 3: Save
Or
You need to create new column with identity.
Create column with identity `Alter table Tablename add newcol int identity(1,1)
Then copy your data from previous column to this column by setting Identity_Insert ON.
Then drop your previous column.
After that change column name by using sp_rename.
Note: But this will change the ordinal position of your column.
ANOTHER OPTION
Create new table with similar structure just make your column
identity whichever you want to be.
Copy data from your old table to new table.
Drop old table.
Change name of new table with old table.
Edit:
For case of Foreign Key relationship
If they are not so many and feasible, then you may drop the constraint.
ALTER TABLE Yourtable
DROP FOREIGN KEY FK_PersonOrder;
Then follow the above steps and recreate them at the last.
ALTER TABLE Yourtable
ADD FOREIGN KEY (yourid) REFERENCES Persons(PersonID);
Finally i got Solution,
I added new column in 'Cus' table.
alter table Cus add tempCusId int identity;
i removed FK relation in User's Table
and i updated identity values in User Table
update user set id=1 where id= 1;
I Compared Id and TempCusId. After update I removed "Pk" relation in Cus table droped Column "Id",i made "TempCusId" as a "Pk" and identity. Finally User table it self "Id" Column I made FK relation.
And if u have multiple values there than go for a "While" loop
DECLARE #NumberofRowint int=30;
DECLARE #inirow INT=23;
Declare #Grade int ;
WHILE #inirow<= #NumberofRow
BEGIN
DECLARE #ProductID INT=(select Id from [Cus] where id=#inirow)
Set #Grade=(select id from Cus where id=#ProductID)
IF(#Grade= #inirow)
BEGIN
updatetbl_Users set Id=#inirow where id=#ProductID
END
SET #inirow = #inirow + 1;
END;

How can we update an column with Foreign key constraint in DB2?

I have 2 Tables , please check images attached
PK: PK
FK: FK
P_Id in Pk table is the primary key
and P_Id in FK table is the foreign key.
I need to add 10 to all records in P_Id column of both PK and FK table( meaning they need to match always)
I know in MS SQL we can easily update cascade as follows:
ALTER TABLE FK
ADD CONSTRAINT FK_P_Id
FOREIGN KEY (P_Id)
REFERENCES PK (P_Id) ON UPDATE CASCADE
and then update the rows of PK , which will automatically update FK too.
update A
set A.P_Id= A.P_Id + 10
from PK A inner join FK B
on A.P_Id = B.P_Id
But, i am not sure how this works in DB2.. can someone please help?
How can i get this to work?
Thanks in advance
Swat
use
SET FOREIGN_KEY_CHECKS = 0;
update both the tables;
and then
SET FOREIGN_KEY_CHECKS = 1;
--remove you foreign key
ALTER TABLE YOURLIB.FK
drop CONSTRAINT YOURLIB.FK_P_Id;
--update FK table
update YOURLIB.FK
set P_Id=P_Id+10;
--update PK table (force)
update YOURLIB.PK overriding system value
set P_Id=P_Id+10;
--recreate foreign key
ALTER TABLE YOURLIB.FK
ADD CONSTRAINT YOURLIB.FK_P_Id
FOREIGN KEY (P_Id)
REFERENCES YOURLIB.PK (P_Id)
ON DELETE RESTRICT;
--If you id on PK is autoincremented, restart it (here 123456 in example but you must found max of id in your PK table --> select max(p_id) from yourlib.pk)
ALTER TABLE YOURLIB.PK
ALTER COLUMN P_Id
RESTART with 123456;
you can modify a key to force like this, only if you update dont create double value key (example your key + 10 already exist in your table), else you must remove the primary key before update (Dangerous, be carefull if someone are working on your table). Ok course you must remove foreign key for do it
update pk f0 overriding system value
set f0.id=f0.id+10
where exists
(
select * from fk f1
where f0.id=f1.id
)

Primary Key on existing data

I need to delete existing PK from table and create new in new column. Because column for new PK was added later (after table creation) - we have nulls for old rows. Should I use UPDATE statement or there is some option in "ADD CONSTRAINT" clause which automatically determine NULLs and generate GUIDs for them?
Thanks for help.
This is what you have to do.
UPDATE TABLE1
SET GUID = NEWID()
WHERE GUID IS NULL
Now to add a new contstraint, you will have tod elete the old one. This is how you can do it:
ALTER TABLE TABLE1
DROP CONSTRAINT PrimaryKeyName
ALTER TABLE TABLE1
ADD CONSTRAINT PrimaryKeyName PRIMARY KEY (GUID)

Add primary key column in SQL table

I am student of RDBMS.
I have very basic question let say I have one existing Table in SQL server. What will be script to alter table.
Drop Column 'RowId' if exist.
Drop contraint if exist.
Add one new column 'RowId' into table.
Make this column as primary key.
Autoincrement type int.
In SQL Server 2005 or newer, you could use this script:
-- drop PK constraint if it exists
IF EXISTS (SELECT * FROM sys.key_constraints WHERE type = 'PK' AND parent_object_id = OBJECT_ID('dbo.YourTable') AND Name = 'PK_YourTable')
ALTER TABLE dbo.YourTable
DROP CONSTRAINT PK_YourTable
GO
-- drop column if it already exists
IF EXISTS (SELECT * FROM sys.columns WHERE Name = 'RowId' AND object_id = OBJECT_ID('dbo.YourTable'))
ALTER TABLE dbo.YourTable DROP COLUMN RowId
GO
-- add new "RowId" column, make it IDENTITY (= auto-incrementing)
ALTER TABLE dbo.YourTable
ADD RowId INT IDENTITY(1,1)
GO
-- add new primary key constraint on new column
ALTER TABLE dbo.YourTable
ADD CONSTRAINT PK_YourTable
PRIMARY KEY CLUSTERED (RowId)
GO
Of course, this script may still fail, if other tables are referencing this dbo.YourTable using foreign key constraints onto the pre-existing RowId column...
Update: and of course, anywhere I use dbo.YourTable or PK_YourTable, you have to replace those placeholder with the actual table / constraint names from your own database (you didn't mention what they were, in your question.....)
Note: this answer was added before questions update
Add new column (note: you can only have one IDENTITY column per table)
Drop old primary key
Add new primary key
Drop old column if needed
Sample script:
CREATE TABLE whatever (
OldPKColumn uniqueidentifier NOT NULL,
CONSTRAINT PK_whatever PRIMARY KEY (OldPKColumn)
)
ALTER TABLE whatever
ADD RowId int NOT NULL IDENTITY (1,1);
ALTER TABLE whatever
DROP CONSTRAINT PK_whatever;
ALTER TABLE whatever WITH CHECK
ADD CONSTRAINT PK_whatever PRIMARY KEY CLUSTERED (RowId);
ALTER TABLE whatever
DROP COLUMN oldPKcolumn;
And a random thought... are you trying to reset an IDENTITY column?
If so, then use DBCC CHECKIDENT
Just a comment to improve these great answers (can't use comments yet - I'm one reputation point away from that privilege) and as future reference for myself:
A new IDENTITY (autonumber) column can be added and made the primary key in a single statement as well:
ALTER TABLE [TableName] ADD [ColumnName] int IDENTITY PRIMARY KEY;
I prefer not to bother with constraint names when it doesn't help.
You can specify seed (and increment) values between parantheses after the IDENTITY keyword.

How do I use cascade delete with SQL Server?

I have 2 tables: T1 and T2, they are existing tables with data. We have a one to many relationship between T1 and T2. How do I alter the table definitions to perform cascading delete in SQL Server when a record from T1 is deleted, all associated records in T2 also deleted.
The foreign constraint is in place between them. I don't want to drop the tables or create a trigger to do the deletion for T2. For example, when I delete an employee, all the review record should be gone, too.
T1 - Employee,
Employee ID
Name
Status
T2 - Performance Reviews,
Employee ID - 2009 Review
Employee ID - 2010 Review
To add "Cascade delete" to an existing foreign key in SQL Server Management Studio:
First, select your Foreign Key, and open it's "DROP and Create To.." in a new Query window.
Then, just add ON DELETE CASCADE to the ADD CONSTRAINT command:
And hit the "Execute" button to run this query.
By the way, to get a list of your Foreign Keys, and see which ones have "Cascade delete" turned on, you can run this script:
SELECT
OBJECT_NAME(f.parent_object_id) AS 'Table name',
COL_NAME(fc.parent_object_id,fc.parent_column_id) AS 'Field name',
delete_referential_action_desc AS 'On Delete'
FROM sys.foreign_keys AS f,
sys.foreign_key_columns AS fc,
sys.tables t
WHERE f.OBJECT_ID = fc.constraint_object_id
AND t.OBJECT_ID = fc.referenced_object_id
ORDER BY 1
And if you ever find that you can't DROP a particular table due to a Foreign Key constraint, but you can't work out which FK is causing the problem, then you can run this command:
sp_help 'TableName'
The SQL in that article lists all FKs which reference a particular table.
Hope all this helps.
Apologies for the long finger. I was just trying to make a point.
You will need to,
Drop the existing foreign key constraint,
Add a new one with the ON DELETE CASCADE setting enabled.
Something like:
ALTER TABLE dbo.T2
DROP CONSTRAINT FK_T1_T2 -- or whatever it's called
ALTER TABLE dbo.T2
ADD CONSTRAINT FK_T1_T2_Cascade
FOREIGN KEY (EmployeeID) REFERENCES dbo.T1(EmployeeID) ON DELETE CASCADE
You can do this with SQL Server Management Studio.
→ Right click the table design and go to Relationships and choose the foreign key on the left-side pane and in the right-side pane, expand the menu "INSERT and UPDATE specification" and select "Cascade" as Delete Rule.
Use something like
ALTER TABLE T2
ADD CONSTRAINT fk_employee
FOREIGN KEY (employeeID)
REFERENCES T1 (employeeID)
ON DELETE CASCADE;
Fill in the correct column names and you should be set. As mark_s correctly stated, if you have already a foreign key constraint in place, you maybe need to delete the old one first and then create the new one.
ON DELETE CASCADE
It specifies that the child data is deleted when the parent data is deleted.
CREATE TABLE products
( product_id INT PRIMARY KEY,
product_name VARCHAR(50) NOT NULL,
category VARCHAR(25)
);
CREATE TABLE inventory
( inventory_id INT PRIMARY KEY,
product_id INT NOT NULL,
quantity INT,
min_level INT,
max_level INT,
CONSTRAINT fk_inv_product_id
FOREIGN KEY (product_id)
REFERENCES products (product_id)
ON DELETE CASCADE
);
For this foreign key, we have specified the ON DELETE CASCADE clause which tells SQL Server to delete the corresponding records in the child table when the data in the parent table is deleted. So in this example, if a product_id value is deleted from the products table, the corresponding records in the inventory table that use this product_id will also be deleted.
First To Enable ONCascade property:
1.Drop the existing foreign key constraint
2.add a new one with the ON DELETE CASCADE setting enabled
Ex:
IF EXISTS(SELECT 1 FROM sys.foreign_keys WHERE parent_object_id = OBJECT_ID(N'dbo.Response'))
BEGIN
ALTER TABLE [dbo].[Response] DROP CONSTRAINT [FK_Response_Request]
ALTER TABLE [dbo].[Response] WITH CHECK ADD CONSTRAINT [FK_Response_Request] FOREIGN KEY([RequestId])
REFERENCES [dbo].[Request] ([RequestId])
ON DELETE CASCADE
END
ELSE
BEGIN
ALTER TABLE [dbo].[Response] WITH CHECK ADD CONSTRAINT [FK_Response_Request] FOREIGN KEY([RequestId])
REFERENCES [dbo].[Request] ([RequestId])
ON DELETE CASCADE
END
Second To Disable ONCascade property:
1.Drop the existing foreign key constraint
2.Add a new one with the ON DELETE NO ACTION setting enabled
Ex:
IF EXISTS(SELECT 1 FROM sys.foreign_keys WHERE parent_object_id = OBJECT_ID(N'dbo.Response'))
BEGIN
ALTER TABLE [dbo].[Response] DROP CONSTRAINT [FK_Response_Request]
ALTER TABLE [dbo].[Response] WITH CHECK ADD CONSTRAINT [FK_Response_Request] FOREIGN KEY([RequestId])
REFERENCES [dbo].[Request] ([RequestId])
ON DELETE CASCADE
END
ELSE
BEGIN
ALTER TABLE [dbo].[Response] WITH CHECK ADD CONSTRAINT [FK_Response_Request] FOREIGN KEY([RequestId])
REFERENCES [dbo].[Request] ([RequestId])
ON DELETE NO ACTION
END
If the one to many relationship is from T1 to T2 then it doesn't represent a function and therefore cannot be used to deduce or infer an inverse function that guarantees the resulting T2 value doesn't omit tuples of T1 join T2 that are deductively valid, because there is no deductively valid inverse function. ( representing functions was the purpose of primary keys. ) The answer in SQL think is yes you can do it. The answer in relational think is no you can't do it. See points of ambiguity in Codd 1970. The relationship would have to be many-to-one from T1 to T2.
I think you cannot just delete the tables property what if this is actual production data, just delete the contents that dont affect the table schema.

Resources