:I have this table:
id | name | chapter | book
1 hamlet I Hamlet
2 Ismael IV Moby Dick
The behaviour I expect for new values is:
Same name && same book => Character exists so Same id than the existing one:
2 Ismael X Moby Dick
Same name && different book => Character doesn't exist so Changes the id:
3 Ismael XX The Bible
My question is:
Do I have to make the query before insert new values and then insert the new value?
or there is a way to do it in a automatic way by setting up a trigger or something?
My CREATE TABLE statement
db.execSQL("CREATE TABLE characters (id INTEGER NOT NULL ,
name TEXT NOT NULL , chapter TEXT NOT NULL , book TEXT NOT NULL );");
I think the most elegant way of doing so would be for you to isolate the properties of your rows which permit to identify them UNIQUELY. Lets say for instance that name + book make the line unique, then you could concatenate these strings into one identifier in your object, add a column to your database, put and index on it and search on this index when you want to insert new elements.
Related
I am using SQLite Database for my application. I have 4 columns- Student_Name,Student_Enroll, Student_Mob, Student_Address in my database. Now I can add new record if and only if one of four column value is different or all values are different. If all column values are same then no new record should be generated.
Can you please guide me to solve this issue?
To enforce that a set of columns must be unique, add a UNIQUE constraint:
create table Students (
/* ID INTEGER PRIMARY KEY, */
Student_Name TEXT,
Student_Enroll TEXT,
Student_Mob TEXT,
Student_Address TEXT,
UNIQUE (Student_Name, Student_Enroll, Student_Mob, Student_Address)
);
This allows new rows only if at least one of the four columns has a different value.
With a plain INSERT, attempting to insert a duplicate row will result in an error. If you simply want to ignore it instead, use INSERT OR IGNORE:
INSERT OR IGNORE INTO Students ...;
Despite of set your column as UNIQUE you also need to resolve the conflict created on each column when you try to insert new data.
To do so, define the behavior to solve the conflict:
"CREATE TABLE table (your columns here...(UNIQUE unique colums here...) ON CONFLICT REPLACE);"
During Create Database line insert UNIQUE ...for each column to insert only unique record.
Solution 1: (Simple)
Define all columns as unique:
create table TableName (id integer primary key autoincrement,
Student_Name text not null unique,
Student_Enroll text not null unique,
Student_Mob text not null unique);
You can add Student_Address as well, if you need to
Solution 2: (bit complex)
Use AND Operator with WHERE clause
INSERT INTO TableName (Student_Name, Student_Enroll, Student_Mob)
SELECT varStudentName, varStudentEnroll, varStudentMob
WHERE NOT EXISTS(SELECT 1 FROM TableName WHERE Student_Name = varStudentName OR Student_Enroll = varStudentEnroll OR Student_Mob = varStudentMob );
//If a record already contains a row, then the insert operation will be ignored.
You can find more information at the sqlite manual.
Live Example:
Open SQLite Online
Paste following code:
INSERT INTO demo (id,name,hint)
SELECT 4, 'jQuery', 'is a cross-platform JavaScript library designed to simplify the client-side scripting of HTML'
WHERE NOT EXISTS(SELECT 1 FROM demo WHERE name = 'jQuery' OR hint = 'is a cross-platform JavaScript library designed to simplify the client-side scripting of HTML' );
SELECT * from demo
Hit RUN
This won't insert 4th record and if you modify both values of WHERE clause then record will be inserted.
I visited sqlfiddle.com and made some tests.
I wanted to get a SQL statement that would let me insert a row, and have a field (below is called active) whose value depends on the table being empty or not.
I used the following schema:
CREATE TABLE kids (
identifier INTEGER PRIMARY KEY,
name VARCHAR,
surname VARCHAR,
active INTEGER);
INSERT INTO
kids
VALUES
(1, "name1", "surname1", CASE WHEN EXISTS (SELECT * FROM kids) THEN 0 ELSE 1 END);
INSERT INTO
kids
VALUES
(2, "name2", "surname2", CASE WHEN EXISTS (SELECT * FROM kids) THEN 0 ELSE 1 END);
And I get the following result when performing a SELECT * FROM kids:
+---+-------+----------+---+
| 1 | name1 | surname1 | 1 |
+---+-------+----------+---+
| 2 | name2 | surname2 | 0 |
+---+-------+----------+---+
This is perfect. The thing is, how do I perform this insert in Android using SQLite and ContentProviders?. Both insert (on ContentProviders and SQLite instance take a ContentValues as a parameter, and I can't add a subquery there, it would be literally read and written.
Is it even possible to achieve this ? If you can think of any other approach, it is also welcome.
Thank you.
Another way of achieving your requirement would be to check the value of underlying field before insertion and then insert the entire data along with computed value in active field
ContentValues ensures that it contents are never interpreted as SQL, so this is not possible.
Unless you actually need to provide data to other apps, do not use content providers. (And if you need to give data to other apps, it would be a bad idea to allow them to execute arbitrary SQL.)
I have a table which contains values from 2 tree map. I couldn't merge them into one and pass as a single map because the input contains duplicates . In short, the data in my table looks like
APPLE 1
BANANA 4
ORANGE 5
GRAPES 1
POTATO 9
I want to sort the integers in ascending order. I tried using order by clause in select statement and used that select statement for creating another table in sorted manner but I couldn't do as there is some missing parenthesis in exec statement.
db.execSQL(INSERT INTO my_ordered_table (name, num) SELECT name,num FROM my_table ORDER BY name ;
I tried writing this but I don't know where to insert parenthesis, " " etc . The column values are dynamic ones and not hard coded values .
I even want INSERT IF EXISTS ELSE UPDATE condition in the insert statement.Any help would be great !! Thanks
db.execSQL(INSERT INTO my_ordered_table (name, num) SELECT name,num FROM my_table ORDER BY num ASC ;
this will work fine.......
I am trying to search a String in column of my table .The values are stored in
column in this format
My Search String is similar as above. i.e: comma separated String
My query is to find out whether any value in search String is present is my column or not.
Things I have Tried:
using Like : Like does it.But it matches individual values i.e for 3 search string values I have to make 15 like condition(costly for large table)
SELECT * from A WHERE mycol LIKE 'myval,%' or mycol LIKE '%, myval,%' or mycol or LIKE '%, myval'
using instr function : instr matches the String but only the First Occurance.
e.g: select * from A where instr ('123' ,'12')
using In : This donot search within the String .But Matches the values individually.
I have tried Like function Like(X , Y) from docs Here
So my Question is there a way , instead of Individually searching my search string in the column using Like Operator or In function . I could search my values values in single query something like combination of In and Any(not supported in Sqlite) function does in other Db
i.e select * from A where Any('my search string') in ('my column value')
Any Answer or comment is HIGHLY Appreciated.Hoping for reply.
You have problems because your database is not properly normalized.
To have multiple search IDs for each MyTable row, create a second table that can have multiple rows, with one search ID in each row:
CREATE TABLE MyTable (
MyTableID INTEGER PRIMARY KEY,
[...]
);
CREATE TABLE MyTableSearchIDs (
MyTableID INTEGER REFERENCES MyTable(MyTableID),
SearchID INTEGER -- or TEXT or whatever
);
To search for a MyTable row, search its ID first:
SELECT *
FROM MyTable
WHERE MyTableID IN (SELECT MyTableID
FROM MyTableSearchIDs
WHERE SearchID = 'myvalue')
The same can be done with a join:
SELECT MyTable.*
FROM MyTable
JOIN MyTableSearchIDs USING (MyTableID)
WHERE MyTableSearchIDs.SearchID = 'myvalue'
I have a table orders, consisting of 3 columns:
order_id int primary key,
cust_id integer,
order_date integer
with data:
order_id | cust_id | order_date
1 | 10 | 1325376000
2 | 10 | 1325548800
3 | 10 | 1325894400
4 | 11 | 1325462400
5 | 11 | 1325721600
6 | 12 | 1325721600
7 | 12 | 1326326400
I'm trying to write a query to give a Cursor containing the most recent order for a given customer that I can then pass to a SimpleCursorAdapter and bind to a ListView, such that the user sees the following:
10 1325894400 (formatted as human readable date)
11 1325721600
12 1326326400
I've tried joining the table to itself in various ways without any luck:
http://sqlfiddle.com/#!2/77b22d/1/0
If I have to populate an ArrayList and use an ArrayAdapter I will, but I'd like to exhaust this option first. Thanks!
EDIT: Apologize for the differences between here and the SQLFiddle, brain running on two separate threads. The Fiddle is the 'correct' data set.
2nd EDIT: Added a new wrinkle (ignore table above, see the SQL fiddle). Adding a field for free-form text and then running the query returns the first record in the GROUP BY, plus the field for the max_date. I need to pull the whole record containing the date that equals max_date. Adding a WHERE clause breaks the query. Thoughts?
Try this
select
order_number
, cust_number
, order_date
from orders o1
where order_number =
(
select order_number
from orders o2
where o2.cust_number = o1.cust_number
and order_date =
(
select max(order_date)
from orders o3
where o3.cust_number = o2.cust_number
)
)
This will get you the correct records and you can format the date as you like in the main query.
Note: My answer is a bit different form your display since the example here and the Fiddle are different. used the Fiddle one
create table orders (order_number integer primary key,
cust_number integer not null,
order_date integer not null);
insert into orders values (1001,10,1005),
(1,10,1325376000),
(2,10,1325548800),
(3,11,1325894400),
(4,11,1325462400),
(5,11,1325721600),
(6,12,1325721600),
(7,12,1326326400),
(8,12,1326326460);
If you just want the latest record for each customer, I think this will work:
SELECT order_number, cust_number, max(order_date) as max_date FROM orders GROUP BY cust_number
The values you put on the link are different from the ones you posted here but you are looking for:
select o1.cust_number, max(o1.order_date)
from orders o1
group by o1.cust_number
order by o1.cust_number ASC
This will give you for each customer the most recent order.