Insert or replace 2 unique values - android

I'm using sqlite in android app and I want to make insert in table by 2 unique row values. For example:
id| column1 | column2 | column3|
1. 1 2 3
2. 2 3 4
Unique columns - COLUMN1 and COLUMN2
INSERT OR REPLACE INTO HISTORY (id, column1, column2, column3) VALUES (null, 2, 3, 6);
But this query shouldn't works 'cause 1st and 2nd values isn't unique in table
Thnx.

If I understand your question, simply use the UNIQUE constraint when building your table:
CREATE TABLE History (
_id INTEGER PRIMARY KEY,
column1 INTEGER,
column2 INTEGER,
column3 INTEGER,
UNIQUE (column1, column2));
Then if you try these INSERT statements:
INSERT INTO History (column1, column2, column3) VALUES (2, 3, 0);
INSERT INTO History (column1, column2, column3) VALUES (2, 3, 6);
The second will fail because column1 and column2 already exist.
Understand that if you use INSERT OR REPLACE in my example, the second statement will replace the first (no exception thrown).
but how can i add unique to existed table?
Typically you would use ALTER TABLE to add a constraint to your existing tables, but SQLite does not allow this... However you can workaround this limitation:
CREATE UNIQUE INDEX name ON History(column1, column2);

Related

How to insert the data into a table with different number of columns in SQL

I'm trying to copy the data from one table to other. Please find the below code:
//Dummy table for reference
database.execSQL("CREATE TABLE IF NOT EXISTS `New_Temp1` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `data1` TEXT DEFAULT '', `data2` INTEGER NOT NULL, `data3` TEXT DEFAULT '', `data4` TEXT DEFAULT '', `data5` TEXT DEFAULT '')");
database.execSQL("INSERT INTO New_Temp1 SELECT * FROM Temp1");
database.execSQL("DROP TABLE Temp1");
database.execSQL("ALTER TABLE New_Temp1 RENAME TO Temp1");
The Temp1 table is already there in database. I don't know the schema of that. Means I don't know the columns of that table. So I am creating a new table New_temp1. When I try to copy the data from Temp1 to New_Temp1, application crashes.
**Caused by: android.database.sqlite.SQLiteException: table New_Temp1 has 33 columns but 28 values were supplied (code 1): , while compiling: INSERT INTO New_Temp1 SELECT * FROM Temp1**
How to solve this, I don't know which columns are missing in Temp1 table.
This statement raises the error:
INSERT INTO New_Temp1 SELECT * FROM Temp1
It looks like the target table does not have the same columns as the original (there are more columns in the target).
If you want to copy the table without knowing the structure, you can combine the table creation and the copy in a single statement like that:
CREATE TABLE New_Temp1 AS
SELECT * FROM Temp1
On the other hand, if you don't want to copy all the columns, and you know the corresponding column names in the source table, then you can enumerate them in the select clause:
INSERT INTO New_Temp1 (data1, data2, data3)
SELECT data1, data2, data3 FROM Temp1
You can get the column names of the table Temp1 with this query:
SELECT name FROM pragma_table_info('Temp1')
You can execute the above statement with rawQuery() and by iterating through the rows of the cursor you will have all the column names and you can use them to create the new table.
If you execute:
SELECT * FROM pragma_table_info('Temp1')
you will get additional info for each column, like:
cid name type notnull dflt_value pk
0 column1 INTEGER 0 0
1 column2 INTEGER 0 0
...........................................

Android sqlite INSERT multiple rows with same constant

I'm trying to execute the following sqlite command to copy some values in a table:
INSERT OR IGNORE INTO table (column1, column2) VALUES((SELECT DISTINCT column1 FROM table WHERE column2 = '2'), 1);
What I want is for the 1 to be used for all the SELECTed rows, but it's only used once. How do I fix that?
I was thinking using a temp table with the default value to what I want. I know temp tables are used for complex queries, but it feels like this isn't that complicated and there could be an easier solution to this.
Example:
I want the following table...
column1 column2
1 2
4 2
5 3
4 4
...to become the following table...
column1 column2
1 2
4 2
5 3
4 4
1 1
4 1
Looks like you want to put the fixed column2 value in the select:
INSERT OR IGNORE INTO table (column1, column2) SELECT DISTINCT column1, 1 FROM table WHERE column2 = '2';
Also note the absence of VALUES.

SQLite alter column to remove constraint

I have a column with a NOT NULL constraint. I need to alter the database to remove the constraint. But when I try I get a duplicate column exception from android
db.execSQL("ALTER TABLE " + AnimalContract.DogEntry.TABLE_NAME
+ " ADD COLUMN " + AnimalContract.DogEntry.COLUMN_NAME+" TEXT DEFAULT NULL");
I also tried without DEFAULT
The constraint was UNIQUE NOT NULL
There's no direct way to ALTER COLUMN in SQLite.
I believe your only option is to:
Rename the table to a temporary name
Create a new table without the NOT NULL constraint
Copy the content of the old table to the new one
Remove the old table
This other Stackoverflow answer explains the process in details
Furthermore,
MODIFY COLUMN IN TABLE
You can not use the ALTER TABLE statement to modify a column in SQLite. Instead you will need to rename the table, create a new table, and copy the data into the new table.
Syntax
The syntax to MODIFY A COLUMN in a table in SQLite is:
PRAGMA foreign_keys=off;
BEGIN TRANSACTION;
ALTER TABLE table1 RENAME TO _table1_old;
CREATE TABLE table1 (
( column1 datatype [ NULL | NOT NULL ],
column2 datatype [ NULL | NOT NULL ],
...
);
INSERT INTO table1 (column1, column2)
SELECT column1, column2
FROM _table1_old;
COMMIT;
PRAGMA foreign_keys=on;
Example
Let's look at an example that shows how to modify a column in a SQLite table.
For example, if we had an employees table that had a column called last_name that was defined as a CHAR datatype:
CREATE TABLE employees
( employee_id INTEGER PRIMARY KEY AUTOINCREMENT,
last_name CHAR NOT NULL,
first_name VARCHAR,
hire_date DATE
);
And we wanted to change the datatype of the last_name field to VARCHAR, we could do the following:
PRAGMA foreign_keys=off;
BEGIN TRANSACTION;
ALTER TABLE employees RENAME TO _employees_old;
CREATE TABLE employees
( employee_id INTEGER PRIMARY KEY AUTOINCREMENT,
last_name VARCHAR NOT NULL,
first_name VARCHAR,
hire_date DATE
);
INSERT INTO employees (employee_id, last_name, first_name, hire_date)
SELECT employee_id, last_name, first_name, hire_date
FROM _employees_old;
COMMIT;
PRAGMA foreign_keys=on;
This example will rename our existing employees table to _employees_old.
Then it will create the new employees table with the last_name field defined as a VARCHAR datatype. Then it will insert all of the data from the _employees_old table into the employees table.

inserting data into 2 tables with the same generated unique id using android sqlite

I am trying to insert data into two table with unique id being generated in Table1 and use the generate unique id in Table2.
Example:
I want to insert empl_no and empl_name into table 1 and table 2. After inserting the empl_no in Table1 it will auto-generate an id for that row. This id would need to be used to on Table2 to insert the empl_name.
Table 1
empl_id | empl_no
-----------------
1 | e00001
Table 2
empl_id | empl_name
-------------------
1 | Andy
What I have in mind is to insert empl_no into Table1 to then do a select to get the last row to retrieve the empl_id. Then use the empl_id to insert into Table2.
Is there a better to do this? It looks inefficient because each time to insert a data it will need to select from the Table just to get the generated unique id.
If you define empl_id as INTEGER PRIMARY KEY in Table1 (optionally with AUTOINCREMENT, but it's better not to use it unless you explicitly need it) then you won't need the extra SELECT statement. The insert() method will return its value.
From the SQLite documentation:
If a table contains a column of type INTEGER PRIMARY KEY, then that
column becomes an alias for the ROWID. You can then access the ROWID
using any of four different names, the original three names described
above or the name given to the INTEGER PRIMARY KEY column. All these
names are aliases for one another and work equally well in any
context.
And from the Android documentation:
public long insert (String table, String nullColumnHack, ContentValues values)
Returns the row ID of the newly inserted row, or -1 if an error occurred.

How do I get "insert or update" behaviour without using CONFLICT_REPLACE?

My Android app is using an SQLite FTS3 table to provide full text search. I'm using insertWithOnConflict with CONFLICT_REPLACE to update my database, inserting a new row if need be or updating an existing row if it's present.
I was very surprised to find that my table ended up containing duplicate rows — but it looks like this is a documented "feature" of SQLite's FTS modules:
From the SQLite FTS3 and FTS4 Extensions page:
Datatypes and column constraints are specified along with each column.
These are completely ignored by FTS and SQLite.
It's pretty easy to replicate the duplication from the command line:
sqlite> CREATE VIRTUAL TABLE test_duplicates USING FTS3
...> (id INTEGER PRIMARY KEY, name TEXT);
sqlite> INSERT INTO test_duplicates (id, name) VALUES (1, "George");
sqlite> INSERT INTO test_duplicates (id, name) VALUES (1, "George");
sqlite> INSERT OR REPLACE INTO test_duplicates (id, name) VALUES (1, "George");
sqlite> SELECT * FROM test_duplicates;
1|George
1|George
1|George
sqlite>
My question is: what's the best (simplest, most robust) way to replicate the behaviour of CONFLICT_REPLACE?
My ideas at the moment are either to (A) do a SELECT, then an UPDATE or INSERT based on the result or (B) blindly try DELETE the existing row (which may or may not be present) and then INSERT.
refering to the fts document, i found this paragraph:
... each FTS table has a "rowid" column. The rowid of an FTS table behaves in the same way as the rowid column of an ordinary SQLite table, except that the values stored in the rowid column of an FTS table remain unchanged if the database is rebuilt using the VACUUM command. For FTS tables, "docid" is allowed as an alias along with the usual "rowid", "oid" and "oid" identifiers. Attempting to insert or update a row with a docid value that already exists in the table is an error, just as it would be with an ordinary SQLite table.
which means you could use the built-in docid column as your primary key and let the fts table apply it's constraint on it.
I have the same problem. I found out that when we CREATE VIRTUAL TABLE test_duplicates USING FTS3 it will create a column named rowid and it's primary key of this table so that we just need using rowid instead id that will work correctly.
If you change:
INSERT INTO test_duplicates (id, name) VALUES (1, "George");
to:
INSERT INTO test_duplicates (rowid, id, name) VALUES (1, 1, "George");
INSERT INTO test_duplicates (rowid, id, name) VALUES (2, 2, "George");
i won't take credit for this. but i can't find the original link i got this from.
you do a query, then:
if (cursor.moveToFirst()) {
// record exists
} else {
// record not found
I use the following query for INSERT OR REPLACE
INSERT OR REPLACE INTO test_duplicates (`rowid`, `name`) VALUES
((SELECT `rowid` FROM test_duplicates WHERE `name` = "George" LIMIT 1), "George")
And it works. But in this case, you can't supply the rowid. rowid will be handled by Database itself.

Categories

Resources