Dump SQLite table/DB without auto-generated columns (e.g id) - sqlite

I have an SQLite 3 database (db) like in this simplified example:
CREATE TABLE user(id integer primary key, name text);
INSERT INTO "user" VALUES(1,'user1');
INSERT INTO "user" VALUES(2,'user2');
If I enter .dump, sqlite will wrap these statements in a transaction and write them to the file db.sql previously defined with .output. This is fine if I need to import the data to an empty DB.
I want to be able to import the user data to a different DB with other users defined. If I try, I will most likely get something like this (as the ids may be used already in the target DB):
Error: near line 4: PRIMARY KEY must be unique
Error: near line 5: PRIMARY KEY must be unique
My approaches:
I can tweak the dumped SQL manually to remove everything but the inserts and also remove the id column (mentioning only name) in the statement, but this approach does not scale as I want to automate the process.
I can select from the db and write the SQL myself.
Is there any easy or more elegant approach that I am missing? sqlite3 will be run from a Bash script in the real world problem.

You can automate the tweaking (but this still requires that you know the table structure):
$ (echo ".mode insert"; echo "SELECT name FROM user;") | \
sqlite3 my.db | \
sed -e 's/^INSERT INTO table /INSERT INTO user(name) /'
INSERT INTO user(name) VALUES('user1');
INSERT INTO user(name) VALUES('user2');

Related

SQLite: UPDATE all rows/cols of all tables with the same (absolute) REPLACE function

How can all entries of all tables of a database be updated with - let's say - n = REPLACE(n,"abc","xyz")?
I don't know in advance, how many tables there are in the database and what are their names. Nor do I know how many columns there are in each table and what are their names.
After confirming that you do in fact want to create a new database which has a certain string replaced outside of semantic considerations, the method I already proposed in my first comment has been confirmed by you to be the solution for you.
With some additional details and explanation:
Use the .dump feature, search-and-replace in the output (stored in a text file). Then create a new database with the desired change by simply reading the from an "empty" database.
The empty database can be created with calling sqlite with a filename of a non-existing file. Feeding that call with a .dumped file fills that new database with the changed input. The result of a .dump can of course be pipe-edited with sed as one way to do a search-and-replace.
I.e. , as you commented, sqlite3 db.sqlite .dump | sed 's|FROM|TO|g' | sqlite3 db-new.sqlite should work and seems to do the trick for you.

SQLite - Trying to read a file with SQL which contains text with special characters causes strange symbols

I am trying to create a SQL script that can be used to generate a database with a set of data, but once I try to read the script in SQLite, special characters(specifically n with tilde) becomes unreadable by humans. Here is an example of a script with the issue:
create table if not exists person(
id integer primary key not null, --auto increment key
name text NOT NULL
);
begin transaction;
insert into person(name) values ('señor');
end transaction;
Running the Query "SELECT * FROM person;" returns the following result:
1|se├▒or
My class requires that I am able to show special symbols within the sqlite command line app. If I copy and paste the insert command into the sqlite console, then the value will be displayed properly.

Create empty sqlite db from command line

Is it possible to create an empty sqlite3 database from the command line (e.g. sqlite3 <someoption> dbname) which would create a database file for me empty of any tables so that I can access it from a different SQL editor?
Currently, when I do sqlite3 dbname, I get a sqlite prompt from which I can do CREATE TABLE ... but if I don't, when I exit, no file is created. So I am looking for a single command which would create an empty database for me without a need to create at least one table within that step.
Use the VACUUM command to create a valid empty SQLite database file, including the root database page and the database header.
sqlite3 file.db "VACUUM;"
I don't think there is a way to do that in just one statement.
In Linux I would workaround it this way:
sqlite3 aFile.db "create table aTable(field1 int); drop table aTable;"
This will automatically create the needed file with the table in it and then drop it leaving the database file without tables. That's the closest thing I know.
Anyway, I think most editors will even accept an empty file too. Give that a try.
The simple way is in bash, use command
touch file.db
This will just create a 0 size file and can be used as an empty sqlite file.
You can also call .databases when you enter the command prompt.
Or:
sqlite3 test.db ".databases"
Just create an empty file.
> test.db
Symbol ">" here means redirection.
Creating a blank db like this ( provided by mosty-mostacho ) has an advantage of being recognised as a valid SQLite db; better than an empty file.
$sqlite3 foo.db "create table t(f int); drop table t;"
Verify it by :
$file foo.db
foo.db: SQLite 3.x database, last written using SQLite version 3024000
from https://sqlite.org/cli.html
Start the sqlite3 program by typing "sqlite3" at the command prompt,
optionally followed by the name the file that holds the SQLite
database (or ZIP archive). If the named file does not exist, a new
database file with the given name will be created automatically. If no
database file is specified on the command-line, a temporary database
is created and automatically deleted when the "sqlite3" program exits.
my emphasis

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;

Modify a Column's Type in sqlite3

I'm pretty new to SQLite 3 and just now I had to add a column to an existing table I had. I went about doing that by doing: ALTER TABLE thetable ADD COLUMN category;.
Of course, I forgot to specify that column's type. The first thing I was thinking about doing was dropping that column and then re-adding it. However, it seems that SQLite does not have a simple way of doing this, and I would have had to backup the table and re-create it without the column.
This seems messy, and I was wondering if there were just a way of modifying/adding a column's type. I would imagine so, but my searching around yielded no results, being new to SQLite, I imagine it was due to my wording being off in the query.
SQLite doesn't support removing or modifying columns, apparently. But do remember that column data types aren't rigid in SQLite, either.
See also:
SQLite Modify Column
If you prefer a GUI, DB Browser for SQLite will do this with a few clicks.
"File" - "Open Database"
In the "Database Structure" tab, click on the table content (not table name), then "Edit" menu, "Modify table", and now you can change the data type of any column with a drop down menu. I changed a 'text' field to 'numeric' in order to retrieve data in a number range.
DB Browser for SQLite is open source and free. For Linux it is available from the repository.
There is a much simpler way:
ALTER TABLE your_main_table
ADD COLUMN new_column_name new_column_data_type
UPDATE your_main_table
SET new_column_name = CAST(old_column_name as new_data_type_you_want)
I tried this on my machine locally and it works
It is possible by recreating table.Its work for me please follow following step:
create temporary table using as select * from your table
drop your table, create your table using modify column type
now insert records from temp table to your newly created table
drop temporary table
do all above steps in worker thread to reduce load on uithread
It is possible by dumping, editing and reimporting the table.
This script will do it for you (Adapt the values at the start of the script to your needs):
#!/bin/bash
DB=/tmp/synapse/homeserver.db
TABLE="public_room_list_stream"
FIELD=visibility
OLD="BOOLEAN NOT NULL"
NEW="INTEGER NOT NULL"
TMP=/tmp/sqlite_$TABLE.sql
echo "### create dump"
echo ".dump '$TABLE'" | sqlite3 "$DB" >$TMP
echo "### editing the create statement"
sed -i "s|$FIELD $OLD|$FIELD $NEW|g" $TMP
read -rsp $'Press any key to continue deleting and recreating the table $TABLE ...\n' -n1 key
echo "### rename the original to '$TABLE"_backup"'"
sqlite3 "$DB" "PRAGMA busy_timeout=20000; ALTER TABLE '$TABLE' RENAME TO '$TABLE"_backup"'"
echo "### delete the old indexes"
for idx in $(echo "SELECT name FROM sqlite_master WHERE type == 'index' AND tbl_name LIKE '$TABLE""%';" | sqlite3 $DB); do
echo "DROP INDEX '$idx';" | sqlite3 $DB
done
echo "### reinserting the edited table"
cat $TMP | sqlite3 $DB

Resources