combing DELETE and LIKE in a sqlite statement - sqlite

I am trying to combine the two into a single statment, I would even settle for two seperate statements..... I know it must be possible, but how?
this is what I have tried:
DELETE FROM myTable WHERE myValue LIKE 'findme%';
and:
DELETE FROM myTable WHERE EXISTS (SELECT * FROM myTable WHERE myValue LIKE 'findme%');
I get an error for the second statement saying something like, you can only have a single result for a LIKE statement with another statement...

If this statement returns any rows
select * from mytable where myvalue like 'findme%';
then replacing "select *" with "delete" should delete them.
delete from mytable where myvalue like 'findme%';
That should work with any SQL database, as long as you have sufficient permissions.

Your first statement should work. Try without the final semicolon maybe?
The second one is not logical. Your subquery is not correlated to the first one and you cannot scan a table which is being modified. Actually what I would expect from this query, if it would ever run, is that all rows are deleted if there is a single row where your column matches…
If you wonder why the solutions with the IN clause work and not the EXISTS, it is because the EXISTS condition is evaluated for each row, whereas the IN set is evaluated once.

This works to me:
DELETE FROM myTable WHERE id IN (SELECT id FROM myTable WHERE myValue LIKE 'findme%');

Have you tried this?
DELETE FROM myTable WHERE myValue IN (SELECT myValue FROM myTable WHERE myValue LIKE 'findme%');

DELETE FROM `table_name` WHERE `column_name` LIKE 'value%'

Related

SQLite Insert or Ignore/Replace with lastInsertID in one statement

I feel like this should be easy...
I have a table like this:
CREATE TABLE table_name (
id INTEGER PRIMARY KEY,
name TEXT NOT NULL,
UNIQUE (name COLLATE NOCASE)
)
No two names are the same, case insensitive. Right now I have users adding names and it does this:
INSERT INTO table_name (name) VALUES ("my name");
And I need to get the id of the row, which is easy with PHP PDO's lastInsertID(). But I also want, if the user is adding a name that's already in the database, for nothing to be added to the database, but still get that id without having to do another database call. I was hoping for something like
INSERT OR REPLACE INTO table_name (name) VALUES ("my name");
And have it just overwrite the same data into the cell and return the lastInsertID (even though it wasn't inserted?). But that doesn't work. What are my other options? Will I have to do a separate database query to see if the name field already exists?
With the OR REPLACE clause, the statement always deletes any old row.
Just use two statements. (There is no technical reason for doing this in a single statement.)

How to DELETE a row with a GUID Value in SQLite

I have a column in SQLite of GUID type, I have tried a query like this, and it returns no error, but the row is not deleted
DELETE FROM MyTable WHERE Id='4ffbd580-b17d-4731-b162-ede8d698e026';
In SQLite Browser the Id values look like binary values, they have strange characters.
I also have tried this, but still does not work
DELETE FROM MyTable WHERE Id='{4ffbd580-b17d-4731-b162-ede8d698e026}';
I know I'm late for this, but it might just be useful for someone with the same problem.
I have a uniqueidentifier type of column in one of my tables and when I execute a select query without any conditions, it returns the result guid column values in this format -
{000B6A69-04D6-C557-7EA3-08CF8C8AD84B}
(Yes, with the braces)
I found out using typeof() function that my guid column values had been stored as text. So, I just tried out four different statements and luckily, the 4th one worked -
1. select myGuidColumn, typeof(myGuidColumn) from MyTable WHERE [myGuidColumn] = '000B6A69-04D6-C557-7EA3-08CF8C8AD84B' --didn't work
2. select myGuidColumn, typeof(myGuidColumn) from MyTable WHERE [myGuidColumn] = '{000B6A69-04D6-C557-7EA3-08CF8C8AD84B}' --didn't work
3. select myGuidColumn, typeof(myGuidColumn) from MyTable WHERE [myGuidColumn] LIKE '{000B6A69-04D6-C557-7EA3-08CF8C8AD84B}' --didn't work
4. select myGuidColumn, typeof(myGuidColumn) from MyTable WHERE [myGuidColumn] LIKE '000B6A69-04D6-C557-7EA3-08CF8C8AD84B' --it works!
Try this command. Id is a probably a binary blob field
DELETE FROM MyTable WHERE Id= X'4ffbd580b17d4731b162ede8d698e026';

SQLITE - INSERT or UPDATE without changing ROWID value

I need to update a table row IF EXISTS, otherwise INSERT a new row.
I tried:
INSERT OR REPLACE INTO table VALUES ...
but if the row row exist this statement changes the row's ROWID, and that's what I'm trying to avoid (I need the rowid :D)
I also tried to find a way to get some sort of return value from the update, in the case where an update has taken place, but I still don't understand how... If I could get the return value from the update statement, I could choose wether to proceed with an insert or not.
Do you have any suggestion or solution to this problem? Or do I need to make a copy of the ROWID and use that instead of the "pure" table ROWID?
Thanks in advance, best regards
ps: I was looking HERE and I was wondering if sqlite has the OUTPUT special word too, but google didn't help me..
---- EDIT after reading comments:
table schema example
CREATE TABLE test (
table_id TEXT NOT NULL,
some_field TEXT NOT NULL,
PRIMARY KEY(table_id)
)
INSERT or REPLACE INTO test (table_id, some_field) VALUES ("foo","bar")
I tested Chris suggestion but the rowid still gets changed. I think the best alternative is to do a SELECT to see if a row with that key already exist. If so, UPDATE, otherwise, INSERT... good old fashion but guaranteed to work.
Combine it with select, like this
INSERT or REPLACE INTO test (ROWID, table_id, some_field)
VALUES ((SELECT ROWID from test WHERE table_id = 'foo' UNION SELECT max(ROWID) + 1 from test limit 1), 'foo','bar')
You need to specify that your table_id is unique in addition to being the primary key:
sqlite> CREATE TABLE test (
table_id TEXT NOT NULL,
some_field TEXT NOT NULL,
PRIMARY KEY(table_id),
UNIQUE(table_id)
);
sqlite> insert or replace into test values("xyz", "other");
sqlite> select * FROM test;
xyz|other
sqlite> insert or replace into test values("abc", "something");
sqlite> insert or replace into test values("xyz", "whatever");
sqlite> select * FROM test;
abc|something
xyz|whatever
From version 3.24.0 (2018-06-04), SQLite now supports an UPSERT clause that will do exactly what the OP needed: https://www.sqlite.org/lang_UPSERT.html
The insert would now look like this:
INSERT INTO test (table_id, some_field) VALUES ("foo","baz")
ON CONFLICT(table_id) DO UPDATE SET some_field=excluded.some_field;

Keep first and remove dupliciate rows only using sqlite

Maybe i should do this in C# but i have more then one row with linkId X. I would like to remove it but i am unsure how. In code i could just use a foreach from 0 to n and remove any found rows with a greater (or !=) id but thats in code. Is there a less difficult way of doing it using sqlite?
Assuming the table's name is tableName and there is a primary key field named id, the following sql would do it. I think the following SQL query is general enough and should be able to be executed under any database engine.
delete from tableName
where id not in (
select min(id) from tableName
group by linkId
)

How to get the number of rows of the selected result from sqlite3?

I want to get the number of selected rows as well as the selected data. At the present I have to use two sql statements:
one is
select * from XXX where XXX;
the other is
select count(*) from XXX where XXX;
Can it be realised with a single sql string?
I've checked the source code of sqlite3, and I found the function of sqlite3_changes(). But the function is only useful when the database is changed (after insert, delete or update).
Can anyone help me with this problem? Thank you very much!
SQL can't mix single-row (counting) and multi-row results (selecting data from your tables). This is a common problem with returning huge amounts of data. Here are some tips how to handle this:
Read the first N rows and tell the user "more than N rows available". Not very precise but often good enough. If you keep the cursor open, you can fetch more data when the user hits the bottom of the view (Google Reader does this)
Instead of selecting the data directly, first copy it into a temporary table. The INSERT statement will return the number of rows copied. Later, you can use the data in the temporary table to display the data. You can add a "row number" to this temporary table to make paging more simple.
Fetch the data in a background thread. This allows the user to use your application while the data grid or table fills with more data.
try this way
select (select count() from XXX) as count, *
from XXX;
select (select COUNT(0)
from xxx t1
where t1.b <= t2.b
) as 'Row Number', b from xxx t2 ORDER BY b;
just try this.
You could combine them into a single statement:
select count(*), * from XXX where XXX
or
select count(*) as MYCOUNT, * from XXX where XXX
To get the number of unique titles, you need to pass the DISTINCT clause to the COUNT function as the following statement:
SELECT
COUNT(DISTINCT column_name)
FROM
'table_name';
Source: http://www.sqlitetutorial.net/sqlite-count-function/
For those who are still looking for another method, the more elegant one I found to get the total of row was to use a CTE.
this ensure that the count is only calculated once :
WITH cnt(total) as (SELECT COUNT(*) from xxx) select * from xxx,cnt
the only drawback is if a WHERE clause is needed, it should be applied in both main query and CTE query.
In the first comment, Alttag said that there is no issue to run 2 queries. I don't agree with that unless both are part of a unique transaction. If not, the source table can be altered between the 2 queries by any INSERT or DELETE from another thread/process. In such case, the count value might be wrong.
Once you already have the select * from XXX results, you can just find the array length in your program right?
If you use sqlite3_get_table instead of prepare/step/finalize you will get all the results at once in an array ("result table"), including the numbers and names of columns, and the number of rows. Then you should free the result with sqlite3_free_table
int rows_count = 0;
while (sqlite3_step(stmt) == SQLITE_ROW)
{
rows_count++;
}
// The rows_count is available for use
sqlite3_reset(stmt); // reset the stmt for use it again
while (sqlite3_step(stmt) == SQLITE_ROW)
{
// your code in the query result
}

Resources