SQLITE with special character in the json path - sqlite

I have a column in sqlite which stores a column with json files and the the key of the json can contain any unicode characters. I have a query to calculate the cardinality of the specific key.
SELECT COUNT(DISTINCT JSON_UNQUOTE(JSON_EXTRACT(dimensions, '$.*abc')))from `definition`
the name is *abc which contains a special character * and used in the json path to the value of the json. the query returns nothing.
In order to read special characters like *, the json path is double-quoted and the above query becomes
SELECT COUNT(DISTINCT JSON_UNQUOTE(JSON_EXTRACT(dimensions, '$."*abc"')))from `definition`
Now I am able to read json path with * but unable to read json path containing a double quote, for example
SELECT COUNT(DISTINCT JSON_UNQUOTE(JSON_EXTRACT(dimensions, '$."a"bc"')))from `definition`
I tried to escape the double quotes in the json path with backslash or one additional double quote but it's not working. Any suggestion would be appreciated.

You usually don't need quotes around the object key name. The double quote in the name of that second one one will need to be escaped, though:
sqlite> CREATE TABLE test(data TEXT);
sqlite> INSERT INTO test VALUES ('{"*abc":1,"foo\"bar":2}');
sqlite> SELECT json_extract(data, '$.*abc') FROM test;
json_extract(data, '$.*abc')
----------------------------
1
sqlite> SELECT json_extract(data, '$.foo\"bar') FROM test;
json_extract(data, '$.foo\"bar')
--------------------------------
2
It's not in the documentation, but after looking at the source code, the path string parsing behavior for object keys is:
When encountering a ., if the next character is a double quote, read up to the next double quote and use the enclosed text as the name. Otherwise, read up to the next . or [ (Or end of string) and use that as the name. There's no parsing of any JSON string escape sequences or anything else fancy in it.
So the only time you really need the quotes is if the key has a . or [ in it. '$."$.abc"' for example. It's harmless to use them unless the name has a double quote, though.

Related

Where condition in mysql with array value

I have a table with like this:
id
values
user_id
1
["8","7","6"]
5
Now I'm running a query with WHERE condition on values column:
SELECT * from table_name WHERE values = ["8","7","6"]
But MySQL returns this error:
Error Code : 1064
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '["8","7","6"]'
If you want to compare for strict equality, you want to do the comparison as JSON objects. You can do this by using JSON_EXTRACT to parse the data as JSON instead of text:
SELECT * from table_name WHERE
JSON_EXTRACT(`values`, '$') = JSON_EXTRACT('["8","7","6"]', '$');
You should be able to use this for any type of JSON as long as you want strict equality. If you want to return all rows that match the given JSON object, use JSON_CONTAINS.
For example to find all values with the string "8" in it, you'd use the following:
SELECT * from table_name WHERE JSON_CONTAINS(`values`, '"8"');
Note that this matching is not as simple as you'd expect and matches any value in the document. If your data consists of JSON arrays, this should still be adequate.
The information about your column datatype, especially values are crucial. Since the column stores a mix of numbers and non-numbers characters, we can assume that it might be stored in VARCHAR() or TEXT datatype. But since the data format looks like a JSON array, it's also a possibility that the column datatype is JSON. Now both of these datatypes have a very different query structure.
First, let's address some issues:
Whenever the cell values include other characters than numerical, it will be considered as string. Hence, using plain .. WHERE values = ["8","7","6"] without wrapping it in quotes ('), you'll get that Error Code : 1064.
VALUES is a reserved word in MySQL so if you want to stick to it as your table column names, you always need to wrap it in backticks. If not, this will also return Error Code : 1064:
.. WHERE `values` = ..
Now let's try this:
If the column datatype for values is VARCHAR() or TEXT, you just have to simply wrap the search value in single quote like:
SELECT * from table_name WHERE `values` = '["8","7","6"]';
Refer this fiddle
updated for MariaDB
If the column datatype for values is JSON, it's something like this:
SELECT * from table_name where JSON_UNQUOTE(`values`)= '["8","7","6"]'
Refer this fiddle for JSON
The JSON method I've referred to this MariaDB documentation.
P/S: According to this documentation JSON is an alias for LONGTEXT introduced for compatibility reasons with MySQL's JSON data type. In other words, when creating a table with JSON datatype in MariaDB, it will be shown as LONGTEXT but with extra definition than just plain LONGTEXT datatype. See this fiddle for more detail.

SQLlite comma escape in match query

I have a match query for example:
select * from items where itemdesc MATCH (',')
The data that it returns its complete non sense - something that contains semicolons, dots etc.
The like query returns a correct dataset however.
select * from items where itemdesc like ('%,%')
How do correctly return the data in the MATCH query when I have the comma - the same issue persists with apostrophes, not sure if there are more characters that the match query does not like.
SQlite fts4 virtual tables don't handle punctuations and they just get replaced with the space instead...
https://www.sqlite.org/fts3.html#tokenizer
so what i did was just declare the tokenchars:
"tokenize=unicode61" + " \"" +"tokenchars=.,/?!:;\\"
Your actual search string you have to wrap with quotes as well - MATCH '",*"'
it doesn't handle quotes though....

Getting a table from a schema from sql with a backslash

So I have to get a table which is in a schema in a database. The schema name contains a backslash, e.g david\b.
I have my connection con so I use dbplyr
tabel <- dplyr::tbl(con, in_schema("david\\b", "some_tabel"))
But this does not work.
Every database I know would only possibly allow a backslash in a quoted identifier. So I think you need to include the double quotes as well as the (escaped) backslash:
in_schema('"david\\b"', "some_tabel")
If you click on the links in my comment, they all pretty much say identifiers (like table and schema names) can only include letters, numbers, _ and (sometimes) $ and #. Unless the identifier is quoted.

How to perform SQLite LIKE queries with wildcards not read as wildcards

I'm running into a problem in SQLite when querying on text fields that happen to have the _ or % wildcard characters.
I have a table with a 'Name' field I want to query on. Two of my records have the value 'test' and 'te_t' in the 'Name' field I want to query on. If I run a query like below
"SELECT ALL * from Table WHERE Name LIKE 'te_t'"
This will return both the 'te_t' and 'test' records, because of '_' being read as a wildcard. How do I make it so that I only get the 'te_t' record from the above query?
I've done some research on this and read that I should be able to throw a backslash '\' character in front of the wildcard to get it to be read as a normal _ character instead of a wildcard. But when I try the query
"SELECT ALL * from Table WHERE Name LIKE 'te\_t'"
my query returns zero matches.
What am I doing wrong? Is this just not possible in SQLite?
In SQL, you can escape special characters in the LIKE pattern if you declare some escape character with ESCAPE:
SELECT * FROM MyTable WHERE Name LIKE 'te\_t' ESCAPE '\'
(see the documentation)

Strange sqlite3 behavior

I'm working on a small SQLite database using the Unix command line sqlite3 command tool. My schema is:
sqlite> .schema
CREATE TABLE status (id text, date integer, status text, mode text);
Now I want to set the column 'mode' to the string "Status" for all entries. However, if I type this:
sqlite> UPDATE status SET mode="Status";
Instead of setting column 'mode' to the string "Status", it sets every entry to the value that is currently in the column 'status'. Instead, if I type the following it does the expected behavior:
sqlite> UPDATE status SET mode='Status';
Is this normal behavior?
This is also a FAQ :-
My WHERE clause expression column1="column1" does not work. It causes every row of the table to be returned, not just the rows where column1 has the value "column1".
Use single-quotes, not double-quotes, around string literals in SQL. This is what the SQL standard requires. Your WHERE clause expression should read: column1='column2'
SQL uses double-quotes around identifiers (column or table names) that contains special characters or which are keywords. So double-quotes are a way of escaping identifier names. Hence, when you say column1="column1" that is equivalent to column1=column1 which is obviously always true.
http://www.sqlite.org/faq.html#q24
Yes, that's normal in SQL.
Single quotes are used for string values; double quotes are used for identifiers (like table or column names).
(See the documentation.)

Resources