Insert only if id doesn't exist - sqlite

Alright, so we have a phonegap app with a table setup like
tblTest (actualid INTEGER PRIMARY KEY, id INTEGER, name TEXT)
The actualid is a unique id for the device and the id is maintained in a server side database. We've had issues with webservices returning duplicate records and while we're fixing that I wanted to add something to our sql that would prevent duplicates from being added (fixing bad data is a pain).
Our current insert statement is setup like
INSERT INTO tblTest (id, name) VALUES (101, 'Bob')
If you run that twice the database will end up looking like
actualid | id| name
1 | 101| Bob
2 | 101| Bob
And what I'd like for it to look like is
actualid | id| name
1 | 101| Bob
Insert or Replace would give me an actualid 2 in the example and any example I've found using a where clause was setup like
INSERT INTO tblTest SELECT ..... WHERE.....
Which doesn't work because none of the data is in a table yet (unless I'm making a newbie mistake, I'm not very good at sqlite or general sql).

Use INSERT OR IGNORE:
INSERT OR IGNORE INTO tblTest (id, name) VALUES (101, 'Bob')
(This requires a unique index on the id column, which you already have.)

You might want to try this:
INSERT INTO tblTest
(id, name)
SELECT 101 as id, 'Bob' as name
FROM tblTest
WHERE NOT EXISTS(SELECT * FROM tblTest WHERE id = 101 and name = 'Bob')

Related

SQLite query to get records with certain condition

My SQLite table name is Invoices, having columns Part Number and Manufacturer.
My problem is to query the table in such a manner that it shows only records where part number have at least 2 different unique manufacturers.
I researched the stack over flow and I tried this solution
QString Filter = "PART_NUMBER in (select PART_NUMBER FROM Invoices GROUP BY "
"PART_NUMBER HAVING count(PART_NUMBER)>1)";
model->setFilter(Filter);
model->select();
But this solution's problem is it shows part number having same manufacturer also.
Edit:
In this example it should return part 2 only
You need to count Manufacturer:
select PART_NUMBER FROM Invoices GROUP BY "
"PART_NUMBER HAVING count(MANUFACTURER)>1
Ok, so you're saying that your data looks like this:
PART_NUMBER | MANUFACTURER
1 | A
2 | A
2 | A (duplicate entry)
3 | A
3 | B
4 | A
4 | B
Then you'd need to select HAVING COUNT(DISTINCT(MANUFACTURER)).
In sqlite, this looks a bit more complex:
SELECT COUNT(MANUFACTURER) FROM (SELECT DISTINCT MANUFACTURER FROM Table WHERE ...);
See this blog post.
But that's more than QSqlQueryModel can do with setFilter(...).
This problem looks like a database design issue. Do you know about database normalization?
When you've normalized your tables, the problem becomes significantly simplified.

How to solve a spool space error with rank () over partition by SQL optimising?

I have a table holding information about contacts made to many different customers in the format
email_address | treatment_group | customer_id | contact_date |
I am trying to add a column that looks at each distinct customer and numbers the contacts they've received from longest ago to most recent. I'm using this code:
explain create table db.responses_with_rank
as
( select a.*,
rank () over (partition by customer_id order by contact_date asc)as xrank
from db.responses_with_rank
)
with data
primary index (email_address, treatment_group)
My query is spooling out. There is a primary index of email_address, treatment_group that leads to a skew factor of 1.1 and a secondary primary index on customer_id. I've collected statistics on both sets of indexes. The table is quite large - around 200M records. Is there something I can try to optimize this query?
There is not enough information to determine the cause of the error.
For start, please add the following to your question:
TD version (select * from dbc.dbcinfo)
Execution plan
The statistics collection commands you have used
customer_id top frequencies (select top 10 customer_id,count(*) from db.responses_with_rank group by 1 order by 2 desc)
Do you have wide text columns in your table?
P.s.
I strongly recommend to use create multiset table and not create table.

How could you get if a table is autoincrement or not from the metadata of an sqlite table?

In case you have several tables inside any sqlite database how could the get the information that they have an auto increment primary key or not?
For instance I am already aware that you could get some info concerning the columns of a table by simply querying this: pragma table_info(tablename_in_here)
It would be much better to get the auto increment column dynamically rather than setting up each corresponding model inside the source code with a boolean value.
Edit:
Let me use this table as an example:
CREATE TABLE "test" (
"id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
"name" TEXT NOT NULL
)
and this is the result table after executing pragma table_info("test")
cid | name | type | notnull | dflt_value | pk
0 | id | INTEGER | 1 | null | 1
1 | name | TEXT | 1 | null | 0
As you can see there is no information whether the id column is autoincrement or not
Edit2:
I looking for a solution that involves sqlite directly through a statement.
Special situations where the sqlite3 command in the terminal can be used to somehow parse the required information from inside are not acceptable. They do not work in situations where you are not allowed to execute commands in a terminal programmatically. Like in an Android app.
Autoincrementing primary keys must be declared as INTEGER PRIMARY KEY or some equivalent, so you can use the table_info date to detect them.
A column is an INTEGER PRIMARY KEY column if, in the PRAGMA table_info output,
the type is integer or INTEGER or any other case-insensitive variant; and
pk is set; and
pk is not set for any other column.
To check whether the column definition includes the AUTOINCREMENT keyword, you have to look directly into the sqlite_master table; SQLite has no other mechanism to access this information.
If this query returns a record, you have the AUTOINCREMENT keyword somewhere in the table definition (which might return a wrong result if this word is commented out):
SELECT 1
FROM sqlite_master
WHERE type = 'table'
AND name = 'tablename_in_here'
AND sql LIKE '%AUTOINCREMENT%'
You can parse the output of .schema. That will give you the sql commands as you used them to create your tables. If autoincrement was declared, you will see it in the output. This has the advantage that it will list all your tables too.

Oracle: Custome auto-increment: C0001 C0002

i am trying to create a table in Oracle sql.
I have no trouble creating the table and the sequence i created works fine.
Right now i can use form to dial in name and email and the table will create the PK for me.
The PK ID would looked like this:
10001 | xxx | xxxx
10002 | xxx | xxxx
10003 | xxx | xxxx
My question is, how can i use function or trigger to auto update my ID, make it into:
QWER10001 | xxx | xxxx
QWER10002 | xxx | xxxx
QWER10003 | xxx | xxxx
I know how to update it manually, but i want it can put that custom text in front of my ID when i put in information.
the text can be set, no need to change it when the number reach max.
I spend hours looking for solution but can't find the right one, please help!
I also did some more research online, right now i have this:
CREATE OR REPLACE TRIGGER "PROFILE_T1"
BEFORE INSERT OR UPDATE
ON "PROFILE"
FOR EACH ROW
BEGIN
:NEW.PROFILEID := 'WCCU' sequence.PROFILEIDUSE
END;
but this did not work. PROFILEID is the PK and is auto incremented. PROFILEIDUSE is the sequence to make it auto increment. WCCU is the text i want to add to the PK when every data is entered.
create or replace trigger "PROFILE_T1"
BEFORE
insert on "PROFILE"
for each row
begin
:new.PROFILEID := 'WCCU' || PROFILEIDUSE.nextval;
end;
Since you have already created the sequence, you simply have to use it in your INSERT statement where you should explicitly specify the column value. If you don't want to explicitly specify the value in the insert statement, you can use a before inert trigger to set the value for the column.
In INSERT statement
insert into your_table values('QWER'||your_sequence.nextval,....);
Using TRIGGER
CREATE OR REPLACE TRIGGER your_trigger
BEFORE INSERT ON your_table
FOR EACH ROW
DECLARE
BEGIN
:new.your_primary_key_column := 'QWER' || your_sequence.nextval;
END your_trigger;
Now, you can exclude this primary column from your insert statement. Trigger will add it for you.

how to relate two table by after insert trigger in sql server 2008r2

I am trying to create a trigger such that if i am inserting some values in 1st table than the two field of the 2nd table automatically updated.
case is that i have a table in which i'm storing user details
First Table
1st name | last name | userId | password | adress | email
and 2nd login table which have two field
Second Table
userId | password
now i want if i change value of password in 1st table is automatically reflect in the 2nd table what is the query for that.
as long as the userid and password for the second table are mapped as foreign keys to the first table, i think you should be able to set "on update cascade" on the rows
you can do like this....
CREATE TRIGGER trgTest ON Test
FOR INSERT
AS
INSERT Test2
(Id, value)
SELECT Id, Value
FROM Inserted
or if you're using stored procedures you can easily manage this
CREATE PROCEDURE sp_Insert
#Value varchar(10)
AS
insert into table1 (...,...) values (#value,...)
insert into table2 (...,...) values (#value,...)
You've mostly answered your own question, Prakash. Check out the MSDN documentation on triggers for the specific syntax you need. Jon's comment in regard to the duplication of data points out that your schema is somewhat denormalized so you may want to take a look at changing that unless it's required for your situation.
From MSDN
INSERT INTO auditEmployeeData
(audit_log_type,
audit_emp_id,
audit_emp_bankAccountNumber,
audit_emp_salary,
audit_emp_SSN)
SELECT 'NEW',
ins.emp_id,
ins.emp_bankAccountNumber,
ins.emp_salary,
ins.emp_SSN
FROM inserted ins

Resources