I'm trying to perform this transaction on MariaDB 10.1.25 on Fedora 25 and DBeaver as sql editor.
Each query alone works fine, but when wrap them on the transaction block always fails.
BEGIN;
INSERT INTO quality.tb_account (email, password, registration_date, active, screen_name)
VALUES ('user11#email.com', 'password', CURRENT_DATE(), TRUE, 'user11');
INSERT INTO quality.tb_account_roles (account_id, role_id)
VALUES (LAST_INSERT_ID(), 1);
COMMIT;
The error is the next one:
SQL Error [1064] [42000]: (conn:2) You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'INSERT INTO quality.tb_account (email, password, registration_date, active, scre' at line 2
Query is : BEGIN;
INSERT INTO quality.tb_account (email, password, registration_date, active, screen_name) VALUES ('user11#email.com', 'password', CURRENT_DATE(), TRUE, 'user11');
INSERT INTO quality.tb_account_roles (account_id, role_id) VALUES (LAST_INSERT_ID(), 1);
COMMIT
(conn:2) You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'INSERT INTO quality.tb_account (email, password, registration_date, active, scre' at line 2
Query is : BEGIN;
INSERT INTO quality.tb_account (email, password, registration_date, active, screen_name) VALUES ('user11#email.com', 'password', CURRENT_DATE(), TRUE, 'user11');
INSERT INTO quality.tb_account_roles (account_id, role_id) VALUES (LAST_INSERT_ID(), 1);
COMMIT
org.mariadb.jdbc.internal.util.dao.QueryException: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'INSERT INTO quality.tb_account (email, password, registration_date, active, scre' at line 2
Query is : BEGIN;
INSERT INTO quality.tb_account (email, password, registration_date, active, screen_name) VALUES ('user11#email.com', 'password', CURRENT_DATE(), TRUE, 'user11');
INSERT INTO quality.tb_account_roles (account_id, role_id) VALUES (LAST_INSERT_ID(), 1);
COMMIT
What am I doing wrong?? Why each query works alone but not together??
You must issue each SQL statement by itself -- do not try to concatenate them together.
Notice that it said "...near 'INSERT..." meaning that it got to the ";" but did not like finding stuff after that.
Related
New to SQLite and trying to understand the upsert functionality.
I have a table with the following DDL:
CREATE TABLE contacts (
contact_id INTEGER PRIMARY KEY,
first_name TEXT NOT NULL,
last_name TEXT NOT NULL,
email TEXT NOT NULL UNIQUE,
phone TEXT NOT NULL UNIQUE
);
Let's say I insert a record:
INSERT INTO contacts (contact_id, first_name, last_name, email, phone)
VALUES (1, 'John', 'Jones', 'jjones#gmail.com', '888-867-5309');
How can I do an upsert that takes into account both the UNIQUE constraint (email) and the PK constraint ( contact_id) so that it handles either case since I don't know which constraint will fail.
I tried doing this:
INSERT INTO contacts (contact_id, first_name, last_name, email, phone)
VALUES (1, 'John', 'Jones', 'john.jones#gmail.com', '888-867-5309')
ON CONFLICT (contact_id, email) DO UPDATE
SET first_name='John', last_name='Jones', email='john.jones#gmail.com', phone='888-867-5309'
WHERE contact_id=1;
But I get the error:
sqlite3.OperationalError: ON CONFLICT clause does not match any PRIMARY KEY or UNIQUE constraint
Doing them individually works just fine.
INSERT INTO contacts (contact_id, first_name, last_name, email, phone)
VALUES (1, 'John', 'Jones', 'john.jones#gmail.com', '888-867-5309')
ON CONFLICT (contact_id) DO UPDATE
SET first_name='John', last_name='Jones', email='john.jones#gmail.com', phone='888-867-5309'
WHERE contact_id=1;
INSERT INTO contacts (contact_id, first_name, last_name, email, phone)
VALUES (1, 'John', 'Jones', 'john.jones#gmail.com', '888-867-5309')
ON CONFLICT (email) DO UPDATE
SET first_name='John', last_name='Jones', email='john.jones#gmail.com', phone='888-867-5309'
WHERE email='john.jones#gmail.com';
I understand I get the error because the combination of columns doesn't meet a single constraint, it encompasses two. But how would I take both into account?
Since you defined:
contact_id INTEGER PRIMARY KEY
contact_id is AUTOINCREMENT and you must not set explicitly a value for this column when you insert a new row (although SQLite would not complain if you do if there is no conflict).
So all you need is:
INSERT INTO contacts (first_name, last_name, email, phone)
VALUES ('John', 'Jones', 'john.jones#gmail.com', '888-867-5309')
ON CONFLICT (email) DO UPDATE
SET first_name='John', last_name='Jones', email='john.jones#gmail.com', phone='888-867-5309';
But, you defined also:
phone TEXT NOT NULL UNIQUE
so there are 2 UNIQUE constraints in your table.
For this case if you want SQLite to deal with conflicts from both columns you can use (INSERT OR) REPLACE:
REPLACE INTO contacts (first_name, last_name, email, phone)
VALUES('Johny', 'Jones', 'john.jones#gmail.com', '888-867-5309')
You must know that REPLACE inserts the new row if there is no conflict (for the columns email and phone in your case), but if there is a conflict then deletes the conflicting row or rows (because there would be 2 conflicting rows one for email and the other for phone) and inserts the new row.
What is wrong with the code to produce this error
mysql.connector.errors.ProgrammingError: 1064 (42000): You have an error in
your SQL syntax; check the manual that corresponds to your MariaDB server
version for the right syntax to use near '%s)' at line 1
I am using XAMPP Localhost Database and mysql.connector Package in Python. My Code for Inserting:
cursor = db.cursor()
username = input()
sql = "INSERT INTO `employee` (`id`, `username`) VALUES (NULL, %s)"
cursor.execute(sql, username)
db.commit()
print("success")
Instead of this line
cursor.execute(sql, username)
try this
cursor.execute(sql, [username])
execute expects a list/(list of tuples) as the second parameter. You can have a look at the documentation if you need more details.
I'm writing a lua program and created a variable for the value the user inputted into a text field. I want to place this variable into a .db database through sqlite 3. How do I show a variable in the insert query?
function addToDatabase()
-- Inserting Rows into Database
local insertQuery = [[INSERT INTO test VALUES
(NULL, ?, 'endOdomReading', ?, 'business', 'Middle Park', 'Logan', '32', '26.56');, (startOdomReading, date)]]
db:exec(insertQuery)
end
I'm not sure which library you use for SQLite3 access (I don't know Corona).
Here's an example using lsqlite3 (which I have renamed to sqlite3 -- no leading l):
function AddToDb(a,b) --insert rows into database using prepared statement
stmt:reset()
stmt:bind(1,a)
stmt:bind(2,b)
assert(stmt:step() == sqlite3.DONE)
end
db = sqlite3.open ':memory:'
db:exec 'create table xxx(value1,value2)'
stmt = db:prepare 'insert into xxx values(?,?)'
AddToDb('hello','world')
AddToDb('bye','now')
for rowid,a,b in db:urows 'select rowid,value1,value2 from xxx' do
print(rowid,a,b)
end
db:close()
Here's my tables:
CREATE TABLE IF NOT EXISTS message_threads (
thread_id integer primary key autoincrement NOT NULL,
user_id integer NOT NULL,
last_checked timestamp NOT NULL DEFAULT '0',
last_updated timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
)
CREATE TABLE IF NOT EXISTS messages (
message_id integer primary key autoincrement NOT NULL,
thread_id integer NOT NULL,message_type integer NOT NULL DEFAULT '0',
message_content varchar(500) NOT NULL,
message_date timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
sent integer NOT NULL DEFAULT '0'
);
Here's the error I'm getting:
Could not prepare statement (1 no such column: m.message_date)
Here's the query that I'm using (This query works in MySQL, as I tested it in PHPMyAdmin with a dummy table)
SELECT * FROM messages m, message_threads t
WHERE m.thread_id = t.thread_id
ORDER BY t.last_updated, t.thread_id, m.message_date;
I'm using WebSQL (which I think is SQLite)
FULL WebSQL CODE
$rootScope.database = openDatabase('application.db', '1.0', 'Application database', 1024 * 1024);
$rootScope.database.transaction(function(tx) {
tx.executeSql("CREATE TABLE IF NOT EXISTS message_threads (thread_id integer primary key autoincrement NOT NULL, user_id integer NOT NULL, last_checked timestamp NOT NULL DEFAULT '0', last_updated timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP);");
tx.executeSql("CREATE TABLE IF NOT EXISTS messages (message_id integer primary key autoincrement NOT NULL,thread_id integer NOT NULL,message_type integer NOT NULL DEFAULT '0',message_content varchar(500) NOT NULL, message_date timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, sent integer NOT NULL DEFAULT '0');");
});
// Empty messages/threads for testing purposes
$rootScope.database.transaction(function(tx) {
tx.executeSql("DELETE FROM messages;");
tx.executeSql("DELETE FROM message_threads;");
});
$rootScope.database.transaction(function(tx) {
tx.executeSql("INSERT INTO message_threads (user_id) VALUES (?);", [0]);
tx.executeSql("INSERT INTO messages (thread_id, message_content, sent) VALUES (?, ?, ?);", [1, "How are you doing?", 1]);
tx.executeSql("INSERT INTO messages (thread_id, message_content) VALUES (?, ?);", [1, "Good you?"]);
});
$rootScope.database.transaction(function(tx) {
tx.executeSql("SELECT * FROM messages m, message_threads t WHERE m.thread_id = t.thread_id ORDER BY t.last_updated, t.thread_id, m.message_date", [], function(tx, rs) {
console.log(JSON.stringify(rs));
}, function(tx, err) {
alert("Error: " + err.message);
});
});
I should add that the query works fine using DBBrowser for SQLite.
Chances are that your database has an older version of the table without the column.
CREATE TABLE IF NOT EXISTS only creates a new table with the given specification if a table by the same name does not exist. It does nothing to make sure the columns are there.
To fix it, either remove your database file, or use DROP TABLE to get rid of your old tables before recreating them.
I have created a fresh new sqlite database and tested both of your create queries using the plain command line sqlite.exe version 3.8.0.2 on windows 7. There were no errors.
Then I have used SQLiteStudio Version 3.0.6 and entered some dummy data and executed your select query. Again no issues.
The tools that I have used can only deal with sqlite. Therefore, it seems to me that there are some configuration issues with your tools.
I'm using SQLite. I have two tables:
Log:
pid INTEGER PRIMARY KEY AUTOINCREMENT
action INTEGER NOT NULL
.... ect.
ErrorExtras:
pid INTEGER REFERENCES log(pid)
msg TEXT,
request TEXT
Now when an error occurs, I want to insert into both. Inserting into Log is easy, as it generates the PID, however, inserting into ErrorExtras is harder since I don't know the PID without doing a query. If I insert into Log, query for the PID and then insert into ErrorExtras, that seems quie messy. Is there some kind of shortcut for these kinds of inserts?
In my case, this is possible because the other info in log uniquely identifies the pid (so there's a combined key), but what if this weren't the case?
You needn't query for the insert_id, just use the last_insert_id in the select statement in ErrorExtras and Bob's your uncle.
If you have control of your SQL commands, you can use the last_insert_rowid SQL function like this:
INSERT INTO Log(action) VALUES(42);
INSERT INTO ErrorExtras(pid, msg) VALUES(last_insert_rowid(), 'x');
(But this works only for the very next INSERT command, because afterwards, last_insert_rowid() returns the rowid of the ErrorExtras record.)
If you are using the C API, you can use the sqlite3_last_insert_rowid function:
sqlite3_prepare_v2(db, "INSERT INTO Log(action) VALUES(42)", -1, &stmt, NULL);
sqlite3_step(stmt);
sqlite3_finalize(stmt);
sqlite3_prepare_v2(db, "INSERT INTO ErrorExtras(pid,msg) VALUES(?,?)", -1, &stmt, NULL);
sqlite3_bind_int64(stmt, 1, sqlite3_last_insert_rowid(db));
sqlite3_bind_text(stmt, 2, "x", -1, SQLITE_TRANSIENT);
sqlite3_step(stmt);
sqlite3_finalize(stmt);
The APIs of other languages typically also have some mechanism to get the last inserted rowid.
For example, in Android, the insert function returns it:
ContentValues cv = new ContentValues();
cv.put("action", 42);
long log_rowid = db.insert("Log", null, cv);
ContentValues cv = new ContentValues();
cv.put("pid", log_rowid);
cv.put("msg", "x");
db.insert("ErrorExtras", null, cv);