How do I rename a column in a SQLite database table? - sqlite

I would need to rename a few columns in some tables in a SQLite database.
I know that a similar question has been asked on stackoverflow previously, but it was for SQL in general, and the case of SQLite was not mentioned.
From the SQLite documentation for ALTER TABLE, I gather that it's not possible to do such a thing "easily" (i.e. a single ALTER TABLE statement).
I was wondering someone knew of a generic SQL way of doing such a thing with SQLite.

Note that as of version 3.25.0 released September 2018 you can now use ALTER TABLE to rename a column.
Example to rename Really Bad : Column Name to BetterColumnName:
ALTER TABLE your_table
RENAME COLUMN "Really Bad : Column Name" TO BetterColumnName
According to keywords the use of "double-quotes" is the standard way
Original "create new and drop old table" answer below.
Say you have a table and need to rename "colb" to "col_b":
First create the new table with a temporary name, based on the old table definition but with the updated column name:
CREATE TABLE tmp_table_name (
col_a INT
, col_b INT
);
Then copy the contents across from the original table.
INSERT INTO tmp_table_name(col_a, col_b)
SELECT col_a, colb
FROM orig_table_name;
Drop the old table.
DROP TABLE orig_table_name;
Last you rename the temporary table table to the original:
ALTER TABLE tmp_table_name RENAME TO orig_table_name;
Don't forget to re-create indexes, triggers, etc. The documentation gives a fuller picture of the gotchas and caveats.
Wrapping all this in a BEGIN TRANSACTION; and COMMIT; is also probably a good idea.

This was just fixed with 2018-09-15 (3.25.0)
Enhancements the ALTER TABLE command:
Add support for renaming columns within a table using ALTER TABLE table RENAME COLUMN oldname TO newname.
Fix table rename feature so that it also updates references to the renamed table in triggers and views.
You can find the new syntax documented under ALTER TABLE
The RENAME COLUMN TO syntax changes the column-name of table table-name into new-column-name. The column name is changed both within the table definition itself and also within all indexes, triggers, and views that reference the column. If the column name change would result in a semantic ambiguity in a trigger or view, then the RENAME COLUMN fails with an error and no changes are applied.
Image source: https://www.sqlite.org/images/syntax/alter-table-stmt.gif
Example:
CREATE TABLE tab AS SELECT 1 AS c;
SELECT * FROM tab;
ALTER TABLE tab RENAME COLUMN c to c_new;
SELECT * FROM tab;
db-fiddle.com demo
Android Support
As of writing, Android's API 27 is using SQLite package version 3.19.
Based on the current version that Android is using and that this update is coming in version 3.25.0 of SQLite, I would say you have bit of a wait (approximately API 33) before support for this is added to Android.
And, even then, if you need to support any versions older than the API 33, you will not be able to use this.

Digging around, I found this multiplatform (Linux | Mac | Windows) graphical tool called DB Browser for SQLite that actually allows one to rename columns in a very user friendly way!
Edit | Modify Table | Select Table | Edit Field. Click click! Voila!
However, if someone want to share a programmatic way of doing this, I'd be happy to know!

While it is true that there is no ALTER COLUMN, if you only want to rename the column, drop the NOT NULL constraint, or change the data type, you can use the following set of commands:
Note: These commands have the potential to corrupt your database, so make sure you have a backup
PRAGMA writable_schema = 1;
UPDATE SQLITE_MASTER SET SQL = 'CREATE TABLE BOOKS ( title TEXT NOT NULL, publication_date TEXT)' WHERE NAME = 'BOOKS';
PRAGMA writable_schema = 0;
You will need to either close and reopen your connection or vacuum the database to reload the changes into the schema.
For example:
Y:\> sqlite3 booktest
SQLite version 3.7.4
Enter ".help" for instructions
Enter SQL statements terminated with a ";"
sqlite> create table BOOKS ( title TEXT NOT NULL, publication_date TEXT NOT NULL);
sqlite> insert into BOOKS VALUES ("NULLTEST",null);
Error: BOOKS.publication_date may not be NULL
sqlite> PRAGMA writable_schema = 1;
sqlite> UPDATE SQLITE_MASTER SET SQL = 'CREATE TABLE BOOKS ( title TEXT NOT NULL, publication_date TEXT)' WHERE NAME = 'BOOKS';
sqlite> PRAGMA writable_schema = 0;
sqlite> .q
Y:\> sqlite3 booktest
SQLite version 3.7.4
Enter ".help" for instructions
Enter SQL statements terminated with a ";"
sqlite> insert into BOOKS VALUES ("NULLTEST",null);
sqlite> .q
REFERENCES FOLLOW:
pragma writable_schema
When this pragma is on, the SQLITE_MASTER tables in which database can be changed using ordinary UPDATE, INSERT, and DELETE statements. Warning: misuse of this pragma can easily result in a corrupt database file.
alter table
SQLite supports a limited subset of ALTER TABLE. The ALTER TABLE command in SQLite allows the user to rename a table or to add a new column to an existing table. It is not possible to rename a column, remove a column, or add or remove constraints from a table.

Recently I had to do that in SQLite3 with a table named points with the colunms id, lon, lat. Erroneusly, when the table was imported, the values for latitude where stored in the lon column and viceversa, so an obvious fix would be to rename those columns. So the trick was:
create table points_tmp as select id, lon as lat, lat as lon from points;
drop table points;
alter table points_tmp rename to points;
I hope this would be useful for you!

CASE 1 : SQLite 3.25.0+
Only the Version 3.25.0 of SQLite supports renaming columns. If your device is meeting this requirement, things are quite simple. The below query would solve your problem:
ALTER TABLE "MyTable" RENAME COLUMN "OldColumn" TO "NewColumn";
CASE 2 : SQLite Older Versions
You have to follow a different Approach to get the result which might be a little tricky
For example, if you have a table like this:
CREATE TABLE student(Name TEXT, Department TEXT, Location TEXT)
And if you wish to change the name of the column Location
Step 1: Rename the original table:
ALTER TABLE student RENAME TO student_temp;
Step 2: Now create a new table student with correct column name:
CREATE TABLE student(Name TEXT, Department TEXT, Address TEXT)
Step 3: Copy the data from the original table to the new table:
INSERT INTO student(Name, Department, Address) SELECT Name, Department, Location FROM student_temp;
Note: The above command should be all one line.
Step 4: Drop the original table:
DROP TABLE student_temp;
With these four steps you can manually change any SQLite table.
Keep in mind that you will also need to recreate any indexes, viewers or triggers on the new table as well.

Quoting the sqlite documentation:
SQLite supports a limited subset of
ALTER TABLE. The ALTER TABLE command
in SQLite allows the user to rename a
table or to add a new column to an
existing table. It is not possible to rename a colum, remove a column, or add or remove constraints from a table.
What you can do of course is, create a new table with the new layout, SELECT * FROM old_table, and fill the new table with the values you'll receive.

First off, this is one of those things that slaps me in the face with surprise: renaming of a column requires creating an entirely new table and copying the data from the old table to the new table...
The GUI I've landed on to do SQLite operations is Base. It's got a nifty Log window that shows all the commands that have been executed. Doing a rename of a column via Base populates the log window with the necessary commands:
These can then be easily copied and pasted where you might need them. For me, that's into an ActiveAndroid migration file. A nice touch, as well, is that the copied data only includes the SQLite commands, not the timestamps, etc.
Hopefully, that saves some people time.

change table column < id > to < _id >
String LastId = "id";
database.execSQL("ALTER TABLE " + PhraseContract.TABLE_NAME + " RENAME TO " + PhraseContract.TABLE_NAME + "old");
database.execSQL("CREATE TABLE " + PhraseContract.TABLE_NAME
+"("
+ PhraseContract.COLUMN_ID + " INTEGER PRIMARY KEY,"
+ PhraseContract.COLUMN_PHRASE + " text ,"
+ PhraseContract.COLUMN_ORDER + " text ,"
+ PhraseContract.COLUMN_FROM_A_LANG + " text"
+")"
);
database.execSQL("INSERT INTO " +
PhraseContract.TABLE_NAME + "("+ PhraseContract.COLUMN_ID +" , "+ PhraseContract.COLUMN_PHRASE + " , "+ PhraseContract.COLUMN_ORDER +" , "+ PhraseContract.COLUMN_FROM_A_LANG +")" +
" SELECT " + LastId +" , "+ PhraseContract.COLUMN_PHRASE + " , "+ PhraseContract.COLUMN_ORDER +" , "+ PhraseContract.COLUMN_FROM_A_LANG +
" FROM " + PhraseContract.TABLE_NAME + "old");
database.execSQL("DROP TABLE " + PhraseContract.TABLE_NAME + "old");

Create a new column with the desired column name: COLNew.
ALTER TABLE {tableName} ADD COLUMN COLNew {type};
Copy contents of old column COLOld to new column COLNew.
INSERT INTO {tableName} (COLNew) SELECT {COLOld} FROM {tableName}
Note: brackets are necessary in above line.

As mentioned before, there is a tool SQLite Database Browser, which does this. Lyckily, this tool keeps a log of all operations performed by the user or the application. Doing this once and looking at the application log, you will see the code involved. Copy the query and paste as required. Worked for me. Hope this helps

From the official documentation
A simpler and faster procedure can optionally be used for some changes that do no affect the on-disk content in any way. The following simpler procedure is appropriate for removing CHECK or FOREIGN KEY or NOT NULL constraints, renaming columns, or adding or removing or changing default values on a column.
Start a transaction.
Run PRAGMA schema_version to determine the current schema version number. This number will be needed for step 6 below.
Activate schema editing using PRAGMA writable_schema=ON.
Run an UPDATE statement to change the definition of table X in the sqlite_master table: UPDATE sqlite_master SET sql=... WHERE type='table' AND name='X';
Caution: Making a change to the sqlite_master table like this will render the database corrupt and unreadable if the change contains a syntax error. It is suggested that careful testing of the UPDATE statement be done on a separate blank database prior to using it on a database containing important data.
If the change to table X also affects other tables or indexes or triggers are views within schema, then run UPDATE statements to modify those other tables indexes and views too. For example, if the name of a column changes, all FOREIGN KEY constraints, triggers, indexes, and views that refer to that column must be modified.
Caution: Once again, making changes to the sqlite_master table like this will render the database corrupt and unreadable if the change contains an error. Carefully test of this entire procedure on a separate test database prior to using it on a database containing important data and/or make backup copies of important databases prior to running this procedure.
Increment the schema version number using PRAGMA schema_version=X where X is one more than the old schema version number found in step 2 above.
Disable schema editing using PRAGMA writable_schema=OFF.
(Optional) Run PRAGMA integrity_check to verify that the schema changes did not damage the database.
Commit the transaction started on step 1 above.

One option, if you need it done in a pinch, and if your initial column was created with a default, is to create the new column you want, copy the contents over to it, and basically "abandon" the old column (it stays present, but you just don't use/update it, etc.)
ex:
alter table TABLE_NAME ADD COLUMN new_column_name TYPE NOT NULL DEFAULT '';
update TABLE_NAME set new_column_name = old_column_name;
update TABLE_NAME set old_column_name = ''; -- abandon old column, basically
This leaves behind a column (and if it was created with NOT NULL but without a default, then future inserts that ignore it might fail), but if it's just a throwaway table, the tradeoffs might be acceptable. Otherwise use one of the other answers mentioned here, or a different database that allows columns to be renamed.

need to rename a few columns in some tables
Another way is to use multiple SQLite3 commands to "rename" a column,
in "some" tables, repeat as needed:
.output tmp
SELECT "ALTER TABLE """|| sqlite_master.name ||""" RENAME COLUMN old_name TO new_name;" FROM sqlite_master
WHERE type = "table" AND sqlite_master.name NOT LIKE 'sqlite_%';
.read tmp
source

Since version 2018-09-15 (3.25.0)
sqlite supports renaming columns
https://sqlite.org/changes.html

sqlite3 yourdb .dump > /tmp/db.txt
edit /tmp/db.txt change column name in Create line
sqlite2 yourdb2 < /tmp/db.txt
mv/move yourdb2 yourdb

Related

SQLite Copy Table Content from one Table to another Table and Update

I have two SQLite files, each of them has one table and the same table design. One Column is set as Primary Key. I want to copy all data from ItemsB into ItemsA. All data should be updated. The ItemsB Table is the newer one.
I've tried:
ATTACH DATABASE ItemsB AS ItemsB;
INSERT INTO ItemsA.PMItem (ItemID,VarID,Name1) SELECT ItemID,VarID,Name1 FROM ItemsB.PMItem;
Obviously this can't work due the Primary Key (which is the column VarID).
Then I tried it with ON CONFLICT:
ON CONFLICT (VarID) DO UPDATE SET Name1=excluded.Name1
But this won't work either.
Example Table:
CREATE TABLE PMItem (
ItemID INTEGER,
VarID INTEGER PRIMARY KEY,
Name1 TEXT
);
You need a WHERE clause with an always true condition, to overcome the ambiguity that is raised when ON CONFLICT is used after a SELECT statement:
INSERT INTO PMItem (ItemID,VarID,Name1)
SELECT ItemID,VarID,Name1
FROM ItemsB.PMItem
WHERE 1
ON CONFLICT(VarID) DO UPDATE
SET Name1 = EXCLUDED.Name1;

Add constraint to existing SQLite table

I'm using SQLite, which doesn't support adding a constraint to an existing table.
So I can't do something like this (just as an example):
ALTER TABLE [Customer]
ADD CONSTRAINT specify_either_phone_or_email
CHECK (([Phone] IS NOT NULL) OR ([Email] IS NOT NULL));
Are there any workarounds for this scenario?
I know:
I can add a constraint for a new table, but it isn't new (and it's generated by my ORM, EF Core)
I can do a "table rebuild" (rename table, create new one, copy old data, drop temp table) but that seems really complex
Ideas
Can I somehow make a copy of the table into a new table, with some schema changes?
Or "get" the schema somehow, and edit it in a SQL script, then add a table with that schema?
To make a copy of a table with some schema changes, you have to do the creation and the copying manually:
BEGIN;
CREATE TABLE Customer_new (
[...],
CHECK ([...])
);
INSERT INTO Customer_new SELECT * FROM Customer;
DROP TABLE Customer;
ALTER TABLE Customer_new RENAME TO Customer;
COMMIT;
To read the schema, execute .schema Customer in the sqlite3 command-line shell.
This gives you the CREATE TABLE statement, which you can edit and execute.
To change the table in place, you can use a backdoor.
First, read the actual table definition (this is the same as what you would get from .schema):
SELECT sql FROM sqlite_master WHERE type = 'table' AND name = 'Customer';
Add your CHECK constraint to that string, then enable write access to sqlite_master with PRAGMA writable_schema=1; and write your new table definition into it:
UPDATE sqlite_master SET sql='...' WHERE type='table' AND name='Customer';
Then reopen the database.
WARNING: This works only for changes that do not change the on-disk format of the table. If you do make any change that changes the record format (such as adding/removing fields, or modifying the rowid, or adding a constraint that needs an internal index), your database will blow up horribly.

Replacing white spaces in the fields of a SQLite database [duplicate]

I would need to rename a few columns in some tables in a SQLite database.
I know that a similar question has been asked on stackoverflow previously, but it was for SQL in general, and the case of SQLite was not mentioned.
From the SQLite documentation for ALTER TABLE, I gather that it's not possible to do such a thing "easily" (i.e. a single ALTER TABLE statement).
I was wondering someone knew of a generic SQL way of doing such a thing with SQLite.
Note that as of version 3.25.0 released September 2018 you can now use ALTER TABLE to rename a column.
Example to rename Really Bad : Column Name to BetterColumnName
ALTER TABLE your_table
RENAME COLUMN [Really Bad : Column Name] TO BetterColumnName
Original "create new and drop old table" answer below.
Say you have a table and need to rename "colb" to "col_b":
First create the new table with a temporary name, based on the old table definition but with the updated column name:
CREATE TABLE tmp_table_name (
col_a INT
, col_b INT
);
Then copy the contents across from the original table.
INSERT INTO tmp_table_name(col_a, col_b)
SELECT col_a, colb
FROM orig_table_name;
Drop the old table.
DROP TABLE orig_table_name;
Last you rename the temporary table table to the original:
ALTER TABLE tmp_table_name RENAME TO orig_table_name;
Don't forget to re-create indexes, triggers, etc. The documentation gives a fuller picture of the gotchas and caveats.
Wrapping all this in a BEGIN TRANSACTION; and COMMIT; is also probably a good idea.
This was just fixed with 2018-09-15 (3.25.0)
Enhancements the ALTER TABLE command:
Add support for renaming columns within a table using ALTER TABLE table RENAME COLUMN oldname TO newname.
Fix table rename feature so that it also updates references to the renamed table in triggers and views.
You can find the new syntax documented under ALTER TABLE
The RENAME COLUMN TO syntax changes the column-name of table table-name into new-column-name. The column name is changed both within the table definition itself and also within all indexes, triggers, and views that reference the column. If the column name change would result in a semantic ambiguity in a trigger or view, then the RENAME COLUMN fails with an error and no changes are applied.
Image source: https://www.sqlite.org/images/syntax/alter-table-stmt.gif
Example:
CREATE TABLE tab AS SELECT 1 AS c;
SELECT * FROM tab;
ALTER TABLE tab RENAME COLUMN c to c_new;
SELECT * FROM tab;
db-fiddle.com demo
Android Support
As of writing, Android's API 27 is using SQLite package version 3.19.
Based on the current version that Android is using and that this update is coming in version 3.25.0 of SQLite, I would say you have bit of a wait (approximately API 33) before support for this is added to Android.
And, even then, if you need to support any versions older than the API 33, you will not be able to use this.
Digging around, I found this multiplatform (Linux | Mac | Windows) graphical tool called DB Browser for SQLite that actually allows one to rename columns in a very user friendly way!
Edit | Modify Table | Select Table | Edit Field. Click click! Voila!
However, if someone want to share a programmatic way of doing this, I'd be happy to know!
While it is true that there is no ALTER COLUMN, if you only want to rename the column, drop the NOT NULL constraint, or change the data type, you can use the following set of commands:
Note: These commands have the potential to corrupt your database, so make sure you have a backup
PRAGMA writable_schema = 1;
UPDATE SQLITE_MASTER SET SQL = 'CREATE TABLE BOOKS ( title TEXT NOT NULL, publication_date TEXT)' WHERE NAME = 'BOOKS';
PRAGMA writable_schema = 0;
You will need to either close and reopen your connection or vacuum the database to reload the changes into the schema.
For example:
Y:\> sqlite3 booktest
SQLite version 3.7.4
Enter ".help" for instructions
Enter SQL statements terminated with a ";"
sqlite> create table BOOKS ( title TEXT NOT NULL, publication_date TEXT NOT NULL);
sqlite> insert into BOOKS VALUES ("NULLTEST",null);
Error: BOOKS.publication_date may not be NULL
sqlite> PRAGMA writable_schema = 1;
sqlite> UPDATE SQLITE_MASTER SET SQL = 'CREATE TABLE BOOKS ( title TEXT NOT NULL, publication_date TEXT)' WHERE NAME = 'BOOKS';
sqlite> PRAGMA writable_schema = 0;
sqlite> .q
Y:\> sqlite3 booktest
SQLite version 3.7.4
Enter ".help" for instructions
Enter SQL statements terminated with a ";"
sqlite> insert into BOOKS VALUES ("NULLTEST",null);
sqlite> .q
REFERENCES FOLLOW:
pragma writable_schema
When this pragma is on, the SQLITE_MASTER tables in which database can be changed using ordinary UPDATE, INSERT, and DELETE statements. Warning: misuse of this pragma can easily result in a corrupt database file.
alter table
SQLite supports a limited subset of ALTER TABLE. The ALTER TABLE command in SQLite allows the user to rename a table or to add a new column to an existing table. It is not possible to rename a column, remove a column, or add or remove constraints from a table.
Recently I had to do that in SQLite3 with a table named points with the colunms id, lon, lat. Erroneusly, when the table was imported, the values for latitude where stored in the lon column and viceversa, so an obvious fix would be to rename those columns. So the trick was:
create table points_tmp as select id, lon as lat, lat as lon from points;
drop table points;
alter table points_tmp rename to points;
I hope this would be useful for you!
CASE 1 : SQLite 3.25.0+
Only the Version 3.25.0 of SQLite supports renaming columns. If your device is meeting this requirement, things are quite simple. The below query would solve your problem:
ALTER TABLE "MyTable" RENAME COLUMN "OldColumn" TO "NewColumn";
CASE 2 : SQLite Older Versions
You have to follow a different Approach to get the result which might be a little tricky
For example, if you have a table like this:
CREATE TABLE student(Name TEXT, Department TEXT, Location TEXT)
And if you wish to change the name of the column Location
Step 1: Rename the original table:
ALTER TABLE student RENAME TO student_temp;
Step 2: Now create a new table student with correct column name:
CREATE TABLE student(Name TEXT, Department TEXT, Address TEXT)
Step 3: Copy the data from the original table to the new table:
INSERT INTO student(Name, Department, Address) SELECT Name, Department, Location FROM student_temp;
Note: The above command should be all one line.
Step 4: Drop the original table:
DROP TABLE student_temp;
With these four steps you can manually change any SQLite table.
Keep in mind that you will also need to recreate any indexes, viewers or triggers on the new table as well.
Quoting the sqlite documentation:
SQLite supports a limited subset of
ALTER TABLE. The ALTER TABLE command
in SQLite allows the user to rename a
table or to add a new column to an
existing table. It is not possible to rename a colum, remove a column, or add or remove constraints from a table.
What you can do of course is, create a new table with the new layout, SELECT * FROM old_table, and fill the new table with the values you'll receive.
First off, this is one of those things that slaps me in the face with surprise: renaming of a column requires creating an entirely new table and copying the data from the old table to the new table...
The GUI I've landed on to do SQLite operations is Base. It's got a nifty Log window that shows all the commands that have been executed. Doing a rename of a column via Base populates the log window with the necessary commands:
These can then be easily copied and pasted where you might need them. For me, that's into an ActiveAndroid migration file. A nice touch, as well, is that the copied data only includes the SQLite commands, not the timestamps, etc.
Hopefully, that saves some people time.
change table column < id > to < _id >
String LastId = "id";
database.execSQL("ALTER TABLE " + PhraseContract.TABLE_NAME + " RENAME TO " + PhraseContract.TABLE_NAME + "old");
database.execSQL("CREATE TABLE " + PhraseContract.TABLE_NAME
+"("
+ PhraseContract.COLUMN_ID + " INTEGER PRIMARY KEY,"
+ PhraseContract.COLUMN_PHRASE + " text ,"
+ PhraseContract.COLUMN_ORDER + " text ,"
+ PhraseContract.COLUMN_FROM_A_LANG + " text"
+")"
);
database.execSQL("INSERT INTO " +
PhraseContract.TABLE_NAME + "("+ PhraseContract.COLUMN_ID +" , "+ PhraseContract.COLUMN_PHRASE + " , "+ PhraseContract.COLUMN_ORDER +" , "+ PhraseContract.COLUMN_FROM_A_LANG +")" +
" SELECT " + LastId +" , "+ PhraseContract.COLUMN_PHRASE + " , "+ PhraseContract.COLUMN_ORDER +" , "+ PhraseContract.COLUMN_FROM_A_LANG +
" FROM " + PhraseContract.TABLE_NAME + "old");
database.execSQL("DROP TABLE " + PhraseContract.TABLE_NAME + "old");
Create a new column with the desired column name: COLNew.
ALTER TABLE {tableName} ADD COLUMN COLNew {type};
Copy contents of old column COLOld to new column COLNew.
INSERT INTO {tableName} (COLNew) SELECT {COLOld} FROM {tableName}
Note: brackets are necessary in above line.
As mentioned before, there is a tool SQLite Database Browser, which does this. Lyckily, this tool keeps a log of all operations performed by the user or the application. Doing this once and looking at the application log, you will see the code involved. Copy the query and paste as required. Worked for me. Hope this helps
From the official documentation
A simpler and faster procedure can optionally be used for some changes that do no affect the on-disk content in any way. The following simpler procedure is appropriate for removing CHECK or FOREIGN KEY or NOT NULL constraints, renaming columns, or adding or removing or changing default values on a column.
Start a transaction.
Run PRAGMA schema_version to determine the current schema version number. This number will be needed for step 6 below.
Activate schema editing using PRAGMA writable_schema=ON.
Run an UPDATE statement to change the definition of table X in the sqlite_master table: UPDATE sqlite_master SET sql=... WHERE type='table' AND name='X';
Caution: Making a change to the sqlite_master table like this will render the database corrupt and unreadable if the change contains a syntax error. It is suggested that careful testing of the UPDATE statement be done on a separate blank database prior to using it on a database containing important data.
If the change to table X also affects other tables or indexes or triggers are views within schema, then run UPDATE statements to modify those other tables indexes and views too. For example, if the name of a column changes, all FOREIGN KEY constraints, triggers, indexes, and views that refer to that column must be modified.
Caution: Once again, making changes to the sqlite_master table like this will render the database corrupt and unreadable if the change contains an error. Carefully test of this entire procedure on a separate test database prior to using it on a database containing important data and/or make backup copies of important databases prior to running this procedure.
Increment the schema version number using PRAGMA schema_version=X where X is one more than the old schema version number found in step 2 above.
Disable schema editing using PRAGMA writable_schema=OFF.
(Optional) Run PRAGMA integrity_check to verify that the schema changes did not damage the database.
Commit the transaction started on step 1 above.
One option, if you need it done in a pinch, and if your initial column was created with a default, is to create the new column you want, copy the contents over to it, and basically "abandon" the old column (it stays present, but you just don't use/update it, etc.)
ex:
alter table TABLE_NAME ADD COLUMN new_column_name TYPE NOT NULL DEFAULT '';
update TABLE_NAME set new_column_name = old_column_name;
update TABLE_NAME set old_column_name = ''; -- abandon old column, basically
This leaves behind a column (and if it was created with NOT NULL but without a default, then future inserts that ignore it might fail), but if it's just a throwaway table, the tradeoffs might be acceptable. Otherwise use one of the other answers mentioned here, or a different database that allows columns to be renamed.
need to rename a few columns in some tables
Another way is to use multiple SQLite3 commands to "rename" a column,
in "some" tables, repeat as needed:
.output tmp
SELECT "ALTER TABLE """|| sqlite_master.name ||""" RENAME COLUMN old_name TO new_name;" FROM sqlite_master
WHERE type = "table" AND sqlite_master.name NOT LIKE 'sqlite_%';
.read tmp
source
Since version 2018-09-15 (3.25.0)
sqlite supports renaming columns
https://sqlite.org/changes.html
sqlite3 yourdb .dump > /tmp/db.txt
edit /tmp/db.txt change column name in Create line
sqlite2 yourdb2 < /tmp/db.txt
mv/move yourdb2 yourdb

Copy SQLite table including metadata

I wanted to add a constraint to an existing column in my SQLite database. However, I read that it is not possible to do so.
I tried the solution from How do I rename a column in a SQLite database table?, but there seems to be missing the copying of all the metadata.
I pretty much want an exact copy of a given table, except for the new constraints.
How does the INSERT command look like to copy all the metadata, thus the indexes will increase correctly, for example.
I'm not a heavy user of sqlite3, but you can use the command line to get the data and "create table" and "create index" commands. I am using the 'History' DB from the Google chrome browser which has a table called "visits". The 'mode insert' command says to provide output in a format that can be used to input this data. The '.schema visits' command says to show the 'create table' and 'create index' statements. The 'select..' statement gives you the data. The database I used doesn't seem to have any foreign key constraints, but they could very well be part of the 'create table' information if your DB has any.
sqlite3 History
.mode insert
.schema visits
select * from visits;

How do I add a new column in between two columns?

I have a table with columns name, qty, rate. I need to add a new column COLNew in between the name and qty columns. How do I add a new column in between two columns?
You have two options.
First, you could simply add a new column with the following:
ALTER TABLE {tableName} ADD COLUMN COLNew {type};
Second, and more complicatedly, but would actually put the column where you want it, would be to create the new table with the missing column and a temporary new name:
CREATE TABLE {tempNewTableName} (name TEXT, COLNew {type} DEFAULT {defaultValue}, qty INTEGER, rate REAL);
And populate it with the old data:
INSERT INTO {tempNewTableName} (name, qty, rate) SELECT name, qty, rate FROM OldTable;
Then delete the old table:
DROP TABLE OldTable;
Then rename the new table to have the name of the OldTable:
ALTER TABLE {tempNewTableName} RENAME TO OldTable;
I'd much prefer the second option, as it will allow you to completely rename everything if need be.
You don't add columns between other columns in SQL, you just add them. Where they're put is totally up to the DBMS. The right place to ensure that columns come out in the correct order is when you select them.
In other words, if you want them in the order {name,colnew,qty,rate}, you use:
select name, colnew, qty, rate from ...
With SQLite, you need to use alter table, an example being:
alter table mytable add column colnew char(50)
You can add new column with the query
ALTER TABLE TableName ADD COLUMN COLNew CHAR(25)
But it will be added at the end, not in between the existing columns.
SQLite has limited ALTER TABLE support that you can use to add a column to the end of a table or to change the name of a table.
If you want to make more complex changes in the structure of a table, you will have to recreate the table. You can save existing data to a temporary table, drop the old table, create the new table, then copy the data back in from the temporary table.
For example, suppose you have a table named "t1" with columns names "a" and "c" and that you want to insert column "b" from this table. The following steps illustrate how this could be done:
BEGIN TRANSACTION;
CREATE TEMPORARY TABLE t1_backup(a,c);
INSERT INTO t1_backup SELECT a,c FROM t1;
DROP TABLE t1;
CREATE TABLE t1(a,b, c);
INSERT INTO t1 SELECT a,c FROM t1_backup;
DROP TABLE t1_backup;
COMMIT;
Now you are ready to insert your new data like so:
UPDATE t1 SET b='blah' WHERE a='key'
ALTER TABLE {tableName} ADD COLUMN COLNew {type};
UPDATE {tableName} SET COLNew = {base on {type} pass value here};
This update is required to handle the null value, inputting a default value as you require. As in your case, you need to call the SELECT query and you will get the order of columns, as paxdiablo already said:
SELECT name, colnew, qty, rate FROM{tablename}
and in my opinion, your column name to get the value from the cursor:
private static final String ColNew="ColNew";
String val=cursor.getString(cursor.getColumnIndex(ColNew));
so if the index changes your application will not face any problems.
This is the safe way in the sense that otherwise, if you are using CREATE temptable or RENAME table or CREATE, there would be a high chance of data loss if not handled carefully, for example in the case where your transactions occur while the battery is running out.
I was facing the same problem and the second method proposed in the accepted answer, as noted in the comments, can be problematic when dealing with foreign keys.
My workaround is to export the database to a sql file making sure that the INSERT statements include column names. I do it using DB Browser for SQLite which has an handy feature for that. After that you just have to edit the create table statement and insert the new column where you want it and recreate the db.
In *nix like systems is just something along the lines of
cat db.sql | sqlite3 database.db
I don't know how feasible this is with very big databases, but it worked in my case.
I seldom add Answers to 11 year old questions. That said the answer with a lot of votes has a misleading line of code. I say misleading because I tried it and had no success. Here is the line of code I am referencing.
ALTER TABLE {tableName} RENAME TO TempOldTable
This is the line I tried in my first try at adding a Column into a DB Table that had already been created. It FAILED but WHY might be a better question. Any way here is the failing line of code.
Dim tb As String = "IncomeTable"
Dim sqlCmd As String = "$ALTER TABLE" '{tb}' "ADD COLUMN itNumVisit INTEGER"
So here is the final code that adds a new Column in my case an INTEGER type.
Private Sub btnCopyTable_Click(sender As Object, e As EventArgs) Handles btnCopyTable.Click
Dim sqlCmd As String = "ALTER TABLE IncomeTable ADD COLUMN itNumVisit INTEGER"
Try
Using conn As New SQLiteConnection($"Data Source = '{gv_dbName}';Version=3;")
conn.Open()
Using cmd As New SQLiteCommand(sqlCmd, conn)
cmd.ExecuteNonQuery()
End Using
End Using
Catch ex As Exception
MsgBox("It Failed")
End Try
End Sub
Notice the STRING sqlCmd is all one String. Just in case someone tried the accepted Answer!

Resources