MariaDB: delete row by using table alias doesn´t work - mariadb

having a statement like this:
DELETE FROM ek_stockvalue lw WHERE lw.id_stockvalue = 6
seems to run in an error in MariaDB. If i remove the "lw"-tablealias, it works:
DELETE FROM ek_stockvalue WHERE id_stockvalue = 6

In MariaDB's documentation nothing is mentioned, see DELETE, however, in MySQL's documentation the following is indicated, see 13.2.2 DELETE Syntax:
Note
If you declare an alias for a table, you must use the alias when
referring to the table:
DELETE t1 FROM test AS t1, test2 WHERE ...
Try:
DELETE `lw` FROM `ek_stockvalue` `lw`
WHERE `lw`.`id_stockvalue` = 6;
See dbfiddle.

Nest a select statement into your delete statement like this (where I assume that your table has an identifying column named 'id'). Then you can use alias within the select statement:
DELETE FROM ek_stockvalue WHERE id in (
SELECT id FROM ek_stockvalue lw WHERE lw.id_stockvalue = 6
)

Related

Get the last inserted row ID (HFSQL)

I need to get the Id(Auto Incremented) created for an inserted Row
How i can do that the documentation mentioned LAST_INSERT_ID but i don't know how to use it ,
i tried this but it does not work :
Insert into tab1 (tab1.Name) values('foo')
SELECT LAST_INSERT_ID ()
Try this :
Insert into tab1 (tab1.Name) values('foo')
SELECT LAST_INSERT_ID() FROM tab1 LIMIT 1
Try this:
You can use:
SELECT IDENT_CURRENT('tablename')
to access the latest identity for a particular table.
For Example:
INSERT INTO YourTable(columns....) VALUES(..........)
SELECT IDENT_CURRENT('YourTable')

Aggregation Queries

Is it possible to do the following query in SQLite.Swift without resorting to arbitrary SQL (which I do have working but would prefer to avoid)?
select table1.id, sum(table1.col1*table2.col2)
from table1, table2
where table1.id=table2.id
group by table1.id
I've attempted the following: the SQL (through asSQL()) appears to be correct, but I can't find a way to reference the aggregate column from the returned row.
let query = table1.select(id, (table1[column1]*table2[column2]).sum
.join(table2, on: table1[id] == table2[id])
.group(id)
Can you alias columns somehow?
OK, I've found the solution, and it only took me 2 days!
The way to alias a column in SQLite.swift is to use an expression.
The name of the expression becomes the column alias.
So instead of
let query = table1.select(id, (table1[column1]*table2[column2]).sum)
.join(table2, on: table1[id] == table2[id])
.group(id)
Use:
let aggrColumn = (table1[column1]*table2[column2]).sum
let query = table1.select(id, aggrColumn)
.join(table2, on: table1[id] == table2[id])
.group(id)
let results = try db.prepare(query)
for row in results {
myAggrColumn = try row.get(aggrColumn)
}
Using
select id, sum(table1.col1*table2.col2)
from table1, table2
were table1.id=table2.id
group by id
Will result (see below for corrections) in 2 columns, namely id and sum(table1,col*table2.col2)
However both uses of id would be ambiguous as coded as there are two such source columns.
As such the query should be changed (see following code whihc assumes you want the id from table1 (shouldn't matter if table2 were used due to the join))
Additionally were is not a keyword, it should be WHERE
An alias would likely make things easier you make an alias using the AS keyword. The folloiwng also includes AS mysumcolumn thus the resultant columns will be id and mysumcolumn
select table1.id, sum(table1.col1*table2.col2) AS mysumcolumn
from table1, table2
where table1.id=table2.id
group by table1.id
Running this with no data results in :-

Why do I get the error "Error: no such column: main.<tablename>.<columname>" although it exists?

This works:
sqlite> .databases
seq name file
--- --------------- ----------------------------------------------------------
0 main /path/to/db
2 uni /path/to/db
also this:
sqlite> pragma main.table_info(tsv_storage);
0|id|int|0||0
1|seqid|text|0||0
...
and this:
sqlite> select count(*) from main.tsv_storage;
198159
and also the attached database works:
sqlite> select * from uni.fasta_storage where uni.fasta_storage.id = 1;
1 MASNTVSAQ... Q197F8.1 002R_IIV3 Uncharacterized protein 002R Q197F8
but this not:
sqlite> select main.tsv_storage.seqid where main.tsv_storage.id=8;
Error: no such column: main.tsv_storage.seqid
EDIT:
and I have also problems with this, do I have to join the tables?
insert into main.tsv_storage(seqlength) select length(fasta) from
uni.fasta_storage where uni.fasta_storage.title = main.tsv_storage.seqid;
Error: no such column: main.tsv_storage.seqid
It happens for all columns, not only seqid. I think I did everything that is explained here: http://sqlite.awardspace.info/syntax/sqlitepg12.htm
What am I missing?
sqlite> select * from main.tsv_storage.seqid where main.tsv_storage.id=8;
You have not defined where to look for the selection. You need to tell the query what fields to search within the table, then define which table you are searching. The select * portion tells the query to look in all fields within the table. The from portion of the query tells the processes what table to look in. And lastly the where portion tells the query what to match when looking.
When using INSERT ... SELECT ..., the SELECT part must be valid query.
You cannot access a column like main.tsv_storage without having the table in the FROM clause:
INSERT INTO main.tsv_storage(seqlength)
SELECT length(fasta)
FROM uni.fasta_storage, main.tsv_storage
WHERE uni.fasta_storage.title = main.tsv_storage.seqid;
And the entire commands looks suspicious.
Are you sure you don't want to update the values in the seqlength column for existing records?
In that case, you would use something like this:
UPDATE main.tsv_storage
SET seqlength = (SELECT length(fasta)
FROM uni.fasta_storage
WHERE uni.fasta_storage.title = main.tsv_storage.seqid);

I am getting an error when I execute a delete query

I am executing the following query
DELETE FROM List,Tree WHERE List.CatID = Tree.CatID AND List.ID = '1' AND Tree.Cat = '332'
but I run into following error
near ",": syntax error
Correct syntax for delete statement is this
DELETE FROM table_name WHERE somecolumn=somevalue
So you cannot use 2 tables in a single delete query by separating them with a comma..
You need to do something like
DELETE something FROM table_name INNER JOIN...
You can delete only from one table at a time, and you have to rewrite the join as a subquery:
DELETE FROM List
WHERE ID = '1'
AND CatID IN (SELECT CatID
FROM Tree
WHERE Cat = '332')

How to handle a missing feature of SQLite : disable triggers?

How to handle a missing feature of SQLite: disable triggers?
I don't have it stored the name of triggers for a specific table.
For example how can I drop all triggers?
What would you do?
So here it is 2015 and there still is no 'disable triggers' in SQLite. For a mobile Application this can be problematic--especially if it's a corporate App requiring offline functionality and local data.
An initial data load can be slowed to crawl by trigger execution even when you don't wrap each insert in an individual transaction.
I solved this issue using SQLite SQL fairly simply. I have a settings table that doesn't participate in the init load. It holds 'list' of key/value pairs. I have one key called 'fireTrigger' with a bit value of 0 or 1. Every trigger I have has an expression that selects value and if it equals 1 it fires the trigger, otherwise it doesn't.
This expression is in addition to any expressions evaluated on the data relating to the trigger. e.g.:
AND 1 = (SELECT val FROM MTSSettings WHERE key = 'fireTrigger')
In simple clean effect this allows me to disable/enable the trigger with a simple UPDATE to the settings table
I wrote a very simple extension function to set a boolean value to true or false.
And a function to retrieve this value (GetAllTriggersOn()).
With this function I can define all my triggers like:
CREATE TRIGGER tr_table1_update AFTER UPDATE ON TABLE1 WHEN GetAllTriggersOn()
BEGIN
-- ...
END
SQLite stores schema (meta) information in the built-in sqlite_master table.
To get a list of available triggers use the below query:
SELECT name FROM sqlite_master
WHERE type = 'trigger' -- AND tbl_name = 'a_table_name'
Set a flag in your database and use it in the triggers WHEN condition.
Say you want to create a trigger on the "clients" table after an insert. You have created a table "trigger_settings" with a TINYINT "triggers_on" field - this is your flag. Then you can set the field to 0 if you want to turn off the filters and to 1 when you want to turn them back on.
Then you create your filter with a WHEN condition that checks the "triggers_on" field.
For example:
CREATE TRIGGER IF NOT EXISTS log_client_data_after_insert
AFTER INSERT
ON [clients]
WHEN (SELECT triggers_on FROM trigger_settings)=1
BEGIN
your_statement
END;
Maybe you can make a stored procedures for droping and creating them. Is that good for you ?
Expanding on Nick Dandoulakis's answer, you could drop all relevant triggers and then reinstate them before the transaction's completion:
BEGIN;
SELECT name, sql FROM sqlite_master WHERE type = 'trigger' AND tbl_name = 'mytable';
-- store all results
-- for each name: DROP TRIGGER $name;
-- do normal work
-- for each sql: execute the SQL verbatim
COMMIT;
Expanding other answers this is how i'm doing it. Take into account that this is disabling all triggers for all tables in the database except some of then used by spatialite
SQLITE_FILE=/tmp/my.sqlite
# Define output sql files as variables
CREATE_TRIGGER_SQL=/tmp/create_triggers.sql
DROP_TRIGGER_SQL=/tmp/drop_triggers.sql
## Dump CREATE TRIGGER statements to a file ##
# To wrap statements in a transaction
echo -e "BEGIN;\n\n" > "${CREATE_TRIGGER_SQL}"
# `SELECT sql` does not output semicolons, so we must concatenate them
sqlite3 -bail "${SQLITE_FILE}" "SELECT sql || ';' FROM sqlite_master WHERE type = 'trigger' AND (name NOT LIKE 'gid_%' AND name NOT LIKE 'ggi_%' AND name NOT LIKE 'ggu_%' AND name NOT LIKE 'gii_%' AND name NOT LIKE 'giu_%' AND name NOT LIKE 'vwgcau_%' AND name NOT LIKE 'vtgcau_%' AND name NOT LIKE 'gcau_%' AND name NOT LIKE 'geometry_columns_%' AND name NOT LIKE 'gcfi_%' AND name NOT LIKE 'gctm_%' AND name NOT LIKE 'vtgcfi_%' AND name NOT LIKE 'vwgcfi_%' AND name NOT LIKE 'vtgcs_%' AND name NOT LIKE 'vwgc_%' AND name NOT LIKE 'vtgc_%' AND name NOT LIKE 'gcs_%');" >> "${CREATE_TRIGGER_SQL}"
echo -e "\n\nCOMMIT;" >> "${CREATE_TRIGGER_SQL}"
## Dump DROP TRIGGER statements to a file ##
echo -e "BEGIN;\n\n" > "${DROP_TRIGGER_SQL}"
sqlite3 -bail "${SQLITE_FILE}" "SELECT 'DROP TRIGGER ' || name || ';' FROM sqlite_master WHERE type = 'trigger' AND (name NOT LIKE 'gid_%' AND name NOT LIKE 'ggi_%' AND name NOT LIKE 'ggu_%' AND name NOT LIKE 'gii_%' AND name NOT LIKE 'giu_%' AND name NOT LIKE 'vwgcau_%' AND name NOT LIKE 'vtgcau_%' AND name NOT LIKE 'gcau_%' AND name NOT LIKE 'geometry_columns_%' AND name NOT LIKE 'gcfi_%' AND name NOT LIKE 'gctm_%' AND name NOT LIKE 'vtgcfi_%' AND name NOT LIKE 'vwgcfi_%' AND name NOT LIKE 'vtgcs_%' AND name NOT LIKE 'vwgc_%' AND name NOT LIKE 'vtgc_%' AND name NOT LIKE 'gcs_%');" >> "${DROP_TRIGGER_SQL}"
echo -e "\n\nCOMMIT;" >> "${DROP_TRIGGER_SQL}"
## Execute like ##
sqlite3 -bail /"${SQLITE_FILE}" < "${DROP_TRIGGER_SQL}"
# do things
sqlite3 -bail /"${SQLITE_FILE}" < "${CREATE_TRIGGER_SQL}"

Resources