sqlite why select like works and equals does not? - database

I have a problem with sqlite3 database, I execute the following queries
sqlite> select * from property where link like
"http://www.domain.com/huur/den-bosch/appartement-48118689-meester-spoermekerlaan-88/";
I get two rows
17|2014-11-03|Meester Spoermekerlaan
88|http://www.domain.com/huur/den-bosch/appartement-48118689-meester-spoermekerlaan-88/|5237
JZ|Den Bosch|€ 789|3|1
32|2014-11-03|Meester Spoermekerlaan
88|http://www.domain.com/huur/den-bosch/appartement-48118689-meester-spoermekerlaan-88/|5237
JZ|Den Bosch|€ 789|3|1
Then I execute the same query, but using the equality operator, like so
sqlite> select * from property where
link="http://www.domain.com/huur/den-bosch/appartement-48118689-meester-spoermekerlaan-88/";
sqlite> (<---- no results??)
I already found a similar answer to mine, however the issue is not the same, my fields are of datatype "text", as you can see here: https://stackoverflow.com/a/14823565/279147
sqlite> .schema property
CREATE TABLE property (id integer PRIMARY KEY AUTOINCREMENT UNIQUE,"date" text,address text,link text,postcode text,city text,price text,rooms text,page integer);
So does anybody have any idea why this would happen? here is my version information
root#s1:/# sqlite3 application.sqlite3
SQLite version 3.7.3

I had the same problem. This work around worked for me.
SELECT * from foo WHERE CAST(name AS BLOB) = CAST('bla' AS BLOB);

SQLite uses dynamic typing; it does not matter if the link column is declared as text or blob or fluffy bunnies.
LIKE automatically converts its parameters into strings, but the = operator does not.
Fix the program that writes the entries to the database to use the correct data type.

I had similar issue, in my case the point was, the like is not case sensitive, but the = operator is case sensitive.

This is because = is a literal string comparison so it would have to be exactly the same.
The like operator is looking for a matching pattern within the string and finds it.

Related

How can I parse JSON arrays in postgresql?

I am using PostgreSQL 9.5.14, and have a column in a table that contains JSON arrays that I need to parse for their contents.
Using a select I can see that the structure of the JSON is of this kind:
SELECT rule_results from table limit 5;
Result:
[{"rule_key":"applicant_not_lived_outside_eu"},{"rule_key":"family_assets_exceed_limit"},{"rule_key":"owned_a_deed"}]
[]
[]
[{"rule_key":"family_category","details":"apply_with_parents_under_25"}]
[]
I have been unable to create an SQL command to give me the values of the rule_key keys.
I've attempted to use the documentation for json-functions in postgresql to find a solution from
https://www.postgresql.org/docs/9.5/functions-json.html
SELECT rule_results::json->'rule_key' as results from table;
This gives me null values only.
SELECT jsonb_object_keys(rule_results::jsonb) from table;
This results in the error msg "cannot call jsonb_object_keys on a scalar", which seems to mean that the query is limited to a single row.
This looks simple enough, an array with key:value pairs, but somehow the answer eludes me. I would appreciate any help.
demo: db<>fiddle
Different solutions are possible. It depends on what you are expecting finally. But all solutions would use the function json_array_elements(). This expands every element into one row. With that you can do whatever you want.
This results in one row per value:
SELECT
value -> 'rule_key'
FROM
data,
json_array_elements(rule_results)

Use String parameter for RegEx in query

In my query (the database is a sql server) I use a RegEx for a select command like this:
SELECT * FROM test WHERE id LIKE '1[2,3]'
(This query is tested and returns the data I want)
I want to use a paramter for this RegEx. For that I definded the Paramter in iReport $P{id} as a string and the value is "1[2,3]".
In my query I use now this parameter like this:
SELECT * FROM test WHERE id LIKE $P{id}
As result I get a blank page. I think the problem is that the value of the parameter is defined with " ". But with ' ' I get a compiler error that the paramter isn't a string.
I hope someone can help me.
LIKE applies to text values, not to numeric values. Since id is numeric use something like this:
SELECT * FROM test WHERE id IN (12, 13)
with the parameter
SELECT * FROM test WHERE id IN ($P!{id_list})
and supply a comma separated list of ids for the parameter. The bang (!) makes sure that the parameter will be inserted as-is, without string delimiters.
Btw: LIKE (Transact-SQL) uses wildcards, not regex.
You can still use LIKE since there exists an implicit conversion from numeric types to text in T-SQL, but this will result in a (table or index) scan, where as the IN clause can take advantage of indexes.
The accepted answer works but it is using String replacement, read more about sql-injection, to understand why this is not good practice.
The correct way to execute this IN query in jasper report (using prepared statement) is:
SELECT * FROM test WHERE $X{IN, id, id_list}
For more information as the use of NOTIN, BETWEEN ecc. see JasperReports sample reference for query

Postgresql Concat String

I want to create select Query in Postgresql. my code is
select * into concat('production.',layer_name) from concat('staging.',layer_name);
but there is a problem
ERROR: "concat" is not a known variable
LINE 20: select * into concat('production.'layer_name) from concat('...
I can not understand why .
Can anybody help me?
There is a concat() function in Postgres (since v.9.1). Useful for string concatenation possibly involving NULL values. But your syntax is just gibberish to the Postgres parser. It is generally not possible to use values (or return values from a function) as identifiers in plain SQL. You would need dynamic SQL in a plpgsql function for that.
But your example doesn't seem to need either. Do you want to copy rows from one table to another one? If so:
INSERT INTO production.layer_name
SELECT * FROM staging.layer_name

Postgresql PQgetvalue: array return

I've a table created like:
CREATE TABLE tbl_test
(
id bigserial PRIMARY KEY,
interest int ARRAY[2]
);
I got PGresult* res using PQexec(conn, "SELECT * FROM tbl_test");
Now, how can I get int[] from PQgetvalue(res, 0, 1).
I don't want to depend on structs defined in array.h as they might change.
I could not find any API in Postgresql docs which can do things.
Please advise.
Regards,
Mayank
PQgetvalue() returns the string representation of the field value unless you specify a binary cursor. In either case (string or binary cursor) you'll need to supply the code to manipulate the result into the form you want.
You might find some ideas in the PostgreSQL source code.
src/backend/utils/adt/arrayfuncs.c
src/include/utils/array.h.
And there's some code in contrib/intarray.
At http://doxygen.postgresql.org/, click "Files", then search for "array".
At the string level, which is what PQgetvalue() returns, it's probably easy to Google up some code that extracts integers from an comma-delimited string.

Is there any C SQLite API for quoting/escaping the name of a table?

It's impossible to sqlite3_bind_text a table name because sqlite3_prepare_v2 fails to prepare a statement such as:
SELECT * FROM ? ;
I presume the table name is needed to parse the statement, so the quoting needs to have happened before sqlite3_prepare_v2.
Is there something like a sqlite3_quote_tablename? Maybe it already exists under a name I can't recognize, but I can't find anything in the functions list.
SQLite will escape identifiers for you with the %w format in the https://www.sqlite.org/printf.html family of functions.
your proposed sqlite3_quote_tablename function could sanitize the input to prevent sql injection attacks. To do this it could parse the input to make sure it is a string literal. http://sqlite.org/lang_expr.html#litvalue
If a table name has invalid characters in it you can enclose the table name in double quotes, like this.
sqlite> create table "test table" (id);
sqlite> insert into "test table" values (1);
sqlite> select * from "test table";
id
----------
1
Of course you should avoid using invalid characters whenever possible. It complicates development and is almost always unnecessary (IMO the only time it is necessary is when you inherit a project that is already done this way and it's too big to change).
When using SQLite prepared statements with parameters the parameter: "specifies a placeholder in the expression for a literal value that is filled in at runtime"
Before executing any SQL statement, SQLite "compiles" the SQL string into a series of opcodes that are executed by an internal Virtual Machine. The table names and column names upon which the SQL statement operates are a necessary part of the compilation process.
You can use parameters to bind "values" to prepared statements like this:
SELECT * FROM FOO WHERE name=?;
And then call sqlite3_bind_text() to bind the string gavinbeatty to the already compiled statement. However, this architecture means that you cannot use parameters like this:
SELECT * FROM ? WHERE name=?; // Can't bind table name as a parameter
SELECT * FROM FOO WHERE ?=10; // Can't bind column name as a parameter
If SQLite doesn't accept table names as parameters, I don't think there is a solution for your problem...
Take into account that:
Parameters that are not assigned values using sqlite3_bind() are treated as NULL.
so in the case of your query, the table name would be NULL which of course is invalid.
I was looking for something like this too and couldn't find it either. In my case, the expected table names were always among a fixed set of tables (so those were easy to validate). The field names on the other hand weren't so I ended up filtering the string, pretty much removing everything that was not a letter, number, or underscore (I knew my fields would fit this parameters). That did the trick.

Resources