SQLite: Add column with primary key to existing table whilst persisting data - database

Within the context of SQLite.
I have an existing table which is currently populated with numerous rows of data.
I am trying to add a new primary key column to this table whilst persisting the original data.
As demonstrated below, I have tried the following
Add a new column to the existing table (Id INTEGER).
Change the name of the existing table.
Create a new table which includes the new primary key (Id INTEGER PRIMARY KEY).
Insert all data from the renamed table into the newly created table.
Drop the renamed table.
The reason I thought this would work is because according to SQlite documentation,
A column declared INTEGER PRIMARY KEY will autoincrement.
However I am receiving the following error.
ErrorCode : 19
Message : constraint failed
UNIQUE constraint failed: Person.Id
Result : Constraint
Here is my code.
--Add a new column to the existing table(Id INT).
ALTER TABLE [Person]
ADD Id INTEGER;
--Change the name of the existing table.
ALTER TABLE [Person] RENAME TO Person_temp;
--Create a new table which includes the new PK.
CREATE TABLE Person(
Id INTEGER PRIMARY KEY,
FirstName nvarchar(100) NULL,
LastName nvarchar(100) NULL
);
--Insert all data from the renamed table into the new table.
INSERT INTO Person SELECT * FROM Person_temp;
--Drop the renamed table.
DROP TABLE Person_temp;
Could anyone be kind enough to shed some light?

Since you do not declare column names in your insert query, the column order depends on the order in witch they where created / added. Try to specify the column names. This is usually a good practice anyway
--Insert all data from the renamed table into the new table.
INSERT INTO Person(Id, FirstName, LastName) SELECT Id, FirstName, LastName FROM Person_temp;
By the way, you probably don't need to add the Id column in the first table :
--Insert all data from the renamed table into the new table.
INSERT INTO Person(FirstName, LastName) SELECT FirstName, LastName FROM Person_temp;
the implicit null value for Id will be replaced by the autoincrement

It sure seems like your Id column does not contain unique value in each row. Since you just added the column, each row will have the same value.
The auto increment is there to help when you insert new rows. (You don't have to select max(id), and insert the new row with id = max+1). It won't auto-populate an existing table of data.
SQLite already has a column that could work for what you want. It's called ROWID. Try using that instead of duplicating it with your Id column.

Related

Is there anyway of adding any values to a new column in sql

enter image description hereI created a table and inserted 8 rows. Then I added a new column called Childname using alter. How can I add or insert different values into the new column at once without using update and Set for each row within the new column? I mean the Childname column showing the null values. I highlighted it with a red arrow.
As far as I understand your question;
You created table then add new column:
CREATE TABLE foo(id int, name varchar(255), city varchar(255));
INSERT INTO foo(id, name, city) VALUES (1, "John", "NYC");
INSERT INTO foo(id, name, city) VALUES (2, "Bill", "Boston");
....
# Alter table
ALTER TABLE foo ADD uid int;
After ALTER operation, surnames were null
If you want to add values to surname column of rows that already existed in the table, you need to use UPDATE like in below sql:
UPDATE foo SET uid = 1 WHERE id = 1
WHERE parameter can change by the case.
UPDATE:
After adding a new column to table which has rows, you could set that column with auto-increment property in SQL Server:
ALTER TABLE foo ADD uid INT IDENTITY(1, 1)

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;

SQL UPDATE set and ID with another ID min value

Im trying to update a table I have the same Data but with different ID's so i would like to set the ID of both communs to the lowest ID register for the results.
UPDATE TABLENAME
SET EXAMPLEID = LOWER(EXAMPLEID)
WHERE
TID = TID
AND
KID = KID
AND
STREET = STREET
I'm getting the following error:
Msg 8102, Level 16, State 1, Line 1 Cannot update identity column
'EXAMPLEID'
Identity Column is generally used with Primary Key column. In your case if ExampleID is your primary key and also identity Column, You cannot have same ExampleID on two different rows.
Primary Key Column is unique for every row
On the other hand If your column is not PK but Identity Column, then SQL Server does not allow you to update Identity Key Column Value.
But there is a dirty workaround alternative for this (Not Recommended)
You can't update an identity column. You may insert new records with an explicit value using IDENTITY_INSERT, but SQL Server won't let you do an update.
If you really need to do this, the only option you have is to copy the full table temporarily and recreate your final table again with the updated values. This is strongly NOT recommended:
Create a copy of your table, with all related objects (indexes, constraints, etc.), but with no rows (only schema objects).
CREATE TABLE TABLENAME_Mirror (
ExampleID INT IDENTITY,
TID VARCHAR(100),
KID VARCHAR(100),
STREET VARCHAR(100))
Set IDENTITY_INSERT ON on this new table and insert the records with the updated values.
SET IDENTITY_INSERT TABLENAME_Mirror ON
INSERT INTO TABLENAME_Mirror (
ExampleID,
TID,
KID,
STREET)
SELECT
/*Updated values*/
FROM
--....
SET IDENTITY_INSERT TABLENAME_Mirror OFF
Drop the original table and rename the copied one to the original name:
BEGIN TRANSACTION
IF OBJECT_ID('dbo.TABLENAME') is not null
DROP TABLE dbo.TABLENAME
EXEC sys.sp_rename
'dbo.TABLENAME_Mirror',
'TABLENAME'
COMMIT
You might need to reseed the identity with a proper value once the rows are inserted, if you want to keep the same seed as before.

SQL server - how does adding identity column in existing table works internally?

I have a table with 100 rows, but my primary key column is not with identity property.(but values of this column seems like identity column and sequential: 1-100)
Now i tried to add new identity column with below code
alter table tableA add new_Iden_col bigint identity(1,1)
but i find that the new column identity values are not in sorted order as per my primary key column.
my output of old Primary key col and new inserted identity column
So can someone explain me why the newly added column is not same as my primary key column even though my old column values are populated naturally in same way and not dynamically sorted for output.
Thanks in advance. :)
The IDENTITY function can be used to create a new IDENTITY column and assign incremental values in the sequence specified by the ORDER BY clause of SELECT...INTO. Below is an example creates a new IDENTITY column for use as a new primary key from the old primary key column order.
SELECT
IDENTITY(bigint, 1,1) AS new_Ident_col
, OtherData
INTO FROM dbo.TableA_New
FROM dbo.TableA
ORDER BY old_PK_col;
DROP TABLE dbo.TableA;
EXEC sp_rename 'dbo.TableA_New', 'TableA';
ALTER TABLE dbo.TableA ADD CONSTRAINT PK_TableA PRIMARY KEY(new_Ident_col);

How to get both the new pk and old pk when inserting a subset of a table into itself?

I'm inserting a subset of a table into the same table and in order to create records in some mapping tables need to capture both the newly created identity PK, and the matching old PK..
If SQL would support it, something like:
Create table Test (pk identity, description varchar(10))
Declare #PKVALUES TABLE (NewPK int, OLdPk int)
INSERT INTO Test (description)
OUTPUT INSERTED.PK, Test.PK into #PKVALUES
Select description
From Test
Where ...
But, of course, SQL doesn't support Output of values from the FROM table during an INSERT operation..
The only set based alternative I've come across requires locking the whole table while creating the new PKs in a temporary table and then inserting them into the Test table using identity insert.
Is there some way I can accomplish this, (without having to resort to a one record at a time
approach or having to lock the whole table) ?
Thanks,
Ilmar
My preference would be to add a column to store the old pk in and then you can return it from the output clause. However, it is not always possible to change the table.
So, I have a sneaky trick but it involves doing twice as much work on your db. What you do is put the Old PK in the description field in the intial insert. Then you update the description to the value of teh old PK by joining on the description field to the PK.
Create table Test (pk identity, description varchar(10))
Declare #PKVALUES TABLE (NewPK int, OLdPk varchar(10)
INSERT INTO Test (description)
OUTPUT INSERTED.PK, INSERTED.Description into #PKVALUES
SELECT PK from Test where....
UPDATE tnew
SET description = told.description
FROM test told
JOIN test tnew ON CAST(told.PK AS varchar (10)) = t.description

Resources