Sqllite - IntegrityError: UNIQUE constraint failed: - sqlite

I am wondering why in the following example my Sqllite3 in Python command does not work:
I am creating the following table
query = """
CREATE TABLE customers2 (
"customer_id" serial PRIMARY KEY,
"name" VARCHAR UNIQUE,
"name2" VARCHAR UNIQUE,
"email" VARCHAR NOT NULL,
"active" bool NOT NULL DEFAULT TRUE,
constraint test unique(name, name2)
)
"""
cur.execute(query)
Then I am inserting some values
query = """
INSERT INTO customers2(name, name2, email)
VALUES
('IBM', 'a','contact#ibm.com'),
('Microsoft','b', 'contact#microsoft.com'),
('Intel', 'c','contact#intel.com');
"""
cur.execute(query)
Then I would like to insert a combination of name = "Microsoft" and name2 = "a" which values already exist but not in combination. The following command gives an error
query = """
INSERT INTO customers2 (name, name2, email)
VALUES('Microsoft','a','hotline#microsoft.com')
ON CONFLICT (name, name2)
DO UPDATE SET name2 = name2+"b";
"""
cur.execute(query)
IntegrityError: UNIQUE constraint failed: customers2.name2
What is the reason for this?

Related

How to insert data from R into Oracle table with identity column?

Assume I have a simple table in Oracle db
CREATE TABLE schema.d_test
(
id_record integer GENERATED AS IDENTITY START WITH 95000 NOT NULL,
DT DATE NOT NULL,
var varchar(50),
num float,
PRIMARY KEY (ID_RECORD)
)
And I have a dataframe in R
dt = c('2022-01-01', '2005-04-01', '2011-10-02')
var = c('sgdsg', 'hjhgjg', 'rurtur')
num = c(165, 1658.5, 8978.12354)
data = data.frame(dt, var, num)%>%
mutate(dt = as.Date(dt))
I'm trying to insert data into Oracle d_test table using the code
data %>%
dbWriteTable(
oracle_con,
value = .,
date = T,
'D_TEST',
append = T,
row.names=F,
overwrite = F
)
But the following error returned
Error in .oci.WriteTable(conn, name, value, row.names = row.names, overwrite = overwrite, :
Error in .oci.GetQuery(con, stmt, data = value) :
ORA-00947: not enough values
What's the problem?
How can I fix it?
Thank you.
This is pure Oracle (I don't know R).
Sample table:
SQL> create table test_so (id number generated always as identity not null, name varchar2(20));
Table created.
SQL> insert into test_so(name) values ('Name 1');
1 row created.
My initial idea was to suggest you to insert any value into the ID column, hoping that Oracle would discard it and generate its own value. However, that won't work.
SQL> insert into test_so (id, name) values (-100, 'Name 2');
insert into test_so (id, name) values (-100, 'Name 2')
*
ERROR at line 1:
ORA-32795: cannot insert into a generated always identity column
But, if you can afford recreating the table so that it doesn't automatically generate the ID column's value but use a "workaround" (we used anyway, as identity columns are relatively new in Oracle) - a sequence and a trigger - you might be able to "fix" it.
SQL> drop table test_so;
Table dropped.
SQL> create table test_so (id number not null, name varchar2(20));
Table created.
SQL> create sequence seq_so;
Sequence created.
SQL> create or replace trigger trg_bi_so
2 before insert on test_so
3 for each row
4 begin
5 :new.id := seq_so.nextval;
6 end;
7 /
Trigger created.
Inserting only name (Oracle will use a trigger to populate ID):
SQL> insert into test_so(name) values ('Name 1');
1 row created.
This is what you'll do in your code - provide dummy ID value, just to avoid
ORA-00947: not enough values
error you have now. Trigger will discard it and use sequence anyway:
SQL> insert into test_so (id, name) values (-100, 'Name 2');
1 row created.
SQL> select * from test_so;
ID NAME
---------- --------------------
1 Name 1
2 Name 2 --> this is a row which was supposed to have ID = -100
SQL>
The way you can handle this problem is to create table with GENERATED BY DEFAULT ON NULL AS IDENTITY like this
CREATE TABLE CM_RISK.d_test
(
id_record integer GENERATED BY DEFAULT ON NULL AS IDENTITY START WITH 5000 NOT NULL ,
DT date NOT NULL,
var varchar(50),
num float,
PRIMARY KEY (ID_RECORD)
)

SQlite Error: no such table: while using join

I have two tables joined together with third many-to-many relation. I'm trying to do select, but SQLite (version 3.11.0) keep telling me that my one of them doesn't exist which is not true! I have no idea what am I doing wrong.
Here are my tables:
DROP TABLE IF EXISTS traits;
CREATE TABLE traits(
trait_id INTEGER UNIQUE NOT NULL CHECK(TYPEOF(trait_id) = 'integer'),
name VARCHAR UNIQUE NOT NULL CHECK(TYPEOF(name) = 'text'),
uri VARCHAR UNIQUE NOT NULL CHECK(TYPEOF(uri) = 'text'),
PRIMARY KEY (trait_id)
);
DROP TABLE IF EXISTS trait_categories;
CREATE TABLE trait_categories(
trait_category_id INTEGER UNIQUE NOT NULL CHECK(TYPEOF(trait_category_id) = 'integer'),
efo_id VARCHAR UNIQUE NOT NULL CHECK(TYPEOF(efo_id) = 'text'),
name VARCHAR UNIQUE NOT NULL CHECK(TYPEOF(name) = 'text'),
uri VARCHAR UNIQUE NOT NULL CHECK(TYPEOF(uri) = 'text'),
PRIMARY KEY (trait_category_id)
);
DROP TABLE IF EXISTS trait_categories_traits;
CREATE TABLE trait_categories_traits(
trait_category_id INTEGER NOT NULL CHECK(TYPEOF(trait_category_id) = 'integer'),
trait_id INTEGER NOT NULL CHECK(TYPEOF(trait_id) = 'integer'),
FOREIGN KEY (trait_category_id) REFERENCES trait_categories(trait_category_id),
FOREIGN KEY (trait_id) REFERENCES traits(trait_id)
);
Here is my SELECT which fails:
SELECT trait_categories.name, traits.name
FROM trait_categories JOIN trait_categories_traits ON trait_categories_traits.trait_category_id = trait_categories.trait_category_id
JOIN traits.trait_id ON trait_categories_traits.trait_id = traits.trait_id;
SQLite say:
sqlite> select trait_id from traits limit 1;
663
sqlite> SELECT trait_categories.name, traits.name
...> FROM trait_categories JOIN trait_categories_traits ON trait_categories_traits.trait_category_id = trait_categories.trait_category_id
...> JOIN traits.trait_id ON trait_categories_traits.trait_id = traits.trait_id;
Error: no such table: traits.trait_id
Please help.
JOIN joins two tables, so it wants two table names.
But traits.trait_id is not a table name.
It appears you wanted to join the traits table, so remove the .trait_id. (And when both columns have the same name, using USING is simpler.)
SELECT ...
FROM trait_categories
JOIN trait_categories_traits USING (trait_category_id)
JOIN traits USING (trait_id);

SQLite 3.6.21: "Squeezing" out NULL values with a unique column value

Using SQLite 3.6.21, I would like to update a column in a table.
The goal is to "squeeze out" NULLs from a column if there is only 1 unique real value in that column. If LastName contained "Smith", "Johnson", and a NULL, then do nothing.
For example:
create table foo (FirstName char(20), LastName char(20));
insert into foo values ('Joe', 'Smith');
insert into foo values ('Susan', NULL);
insert into foo values ('Shirley', 'Smith');
insert into foo values ('Kevin', NULL);
Since there is only one last name, I want to replace the NULLs with Smith. I have tried this without success. It ends up replacing the whole column with NULLs.
UPDATE foo
SET LastName =
( CASE
WHEN ((select count(distinct LastName) from foo) = 1) THEN (SELECT distinct LastName from foo)
ELSE LastName
END
);
EDIT:
I'm executing this in Python using the following code:
import sqlite3 as lite
'''
con = lite.connect('test.db')
names = (
('Joe', 'Smith'),
('Susan', None),
('Shirley', 'Smith'),
('Kevin', None),
)
squeezecmd = "UPDATE foo SET LastName = (CASE WHEN ((select count(distinct LastName) from foo) = 1) THEN (SELECT distinct LastName from foo) ELSE LastName END)"
with con:
cur = con.cursor()
cur.execute("CREATE TABLE foo(FirstName TEXT, LastName TEXT)")
cur.executemany("INSERT INTO foo VALUES(?, ?)", names)
cur.execute(squeezecmd)
cur.execute("SELECT * FROM foo")
rows = cur.fetchall()
for row in rows:
print row
Python reorders the "SELECT distinct LastName from foo" so that the NULL is the first value. SQL provides "Smith" as the first value. To ignore the NULL I changed that line to
...THEN (SELECT distinct LastName from foo where LastName is NOT NULL)
EDIT:
Copy from SQL console:
sqlite>
sqlite> SELECT distinct LastName from foo;
Smith
sqlite>
Copy from Python:
with con:
cur = con.cursor()
cur.execute("SELECT distinct LastName from foo")
answer = cur.fetchall()
print answer
Results in
[(None,), (u'Smith',)]

sqlite3: how to select same row twice when there is a match?

Create SOF.SQL
CREATE TABLE "android_metadata" ("locale" TEXT DEFAULT 'en_US');
INSERT INTO "android_metadata" VALUES ('en_US');
CREATE TABLE main.t_def (
_id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
word TEXT(20) not null,
word_def TEXT(20) not null
);
insert into t_def (word, word_def) values ('ball','spherical object');
insert into t_def (word, word_def) values ('cat','feline');
insert into t_def (word, word_def) values ('dog','common housekept');
CREATE TABLE main.t_a (
_id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
corr_answer TEXT(20) not null,
user_answer TEXT(20) not null,
is_correct INTEGER not null
);
insert into t_a (user_answer, corr_answer, is_correct) values ('ball','cat',0);
insert into t_a (user_answer, corr_answer, is_correct) values ('dog','dog',1);
.exit
Then run:
sqlite3 foo.db < SOF.SQL
I want a result set that is:
ball|spherical object|cat|feline|0
This is the closest I have gotten:
select t_def.word, t_def.word_def from t_def, t_a where t_a.is_correct=0 and t_a.corr_answer=t_def.word;
To get values from two rows, you need two instances of the table:
SELECT t_a.user_answer,
user_def.word_def AS user_word_def,
t_a.corr_answer,
corr_def.word_def AS corr_word_def,
t_a.is_correct
FROM t_a
JOIN t_def AS user_def ON t_a.user_answer = user_def.word
JOIN t_def AS corr_def ON t_a.corr_answer = corr_def.word
WHERE NOT t_a.is_correct

How to increment quantity column if record exists, else insert record?

I've got the below sqlite database:
CREATE TABLE `test` (
`idx` INTEGER PRIMARY KEY AUTOINCREMENT,
`qty` INTEGER,
`brand` TEXT,
`type` TEXT
);
insert into test (qty, brand, type) values (1, "Merc", "petrol");
insert into test (qty, brand, type) values (1, "Toyota", "diesel");
I want to insert another record but if it exists then I want to increase the qty field, so:
insert into test (qty, brand, type) values (1, "Merc", "diesel");
so would just increase the qty field by one, and
insert into test (qty, brand, type) values (1, "Merc", "petrol");
would insert a new record.
SQLite is an embedded database, i.e., it is designed to be used together with an application.
The easiest way is to put the logic into the application:
db.execute("UPDATE test SET qty = qty + 1 WHERE brand = ? AND type = ?",
["Merc", "diesel"])
if db.rows_affected == 0:
db.execute("INSERT ...")
As of version 3.24.0, SQLite supports UPSERT.
CREATE TABLE `test` (
`idx` INTEGER PRIMARY KEY AUTOINCREMENT,
`qty` INTEGER DEFAULT 1,
`brand` TEXT,
`type` TEXT
)
UNIQUE (brand, type)
;
INSERT INTO test (qty, brand, type) VALUES ("Merc", "diesel")
ON CONFLICT(brand, type) DO UPDATE SET qty = qty + 1;
INSERT INTO test (qty, brand, type) VALUES ("Merc", "diesel")
ON CONFLICT(brand, type) DO UPDATE SET qty = qty + 1;
SELECT qty, brand, type FROM test;
Output:
2 Merc diesel

Resources