while inserting i can insert danish character in proper format in sqlite Db but while retrieving my query returns no result - sqlite

while inserting i can insert danish character in proper format in sqlite Db but while retrieving my query returns no result
String searchQuery= "SELECT * FROM article,product where article.ItemNo=product.ItemNo ";
if(searchText.length()>0)
{
searchQuery += " AND (article.itemNo like '"+ searchText +"%' OR product.Description like '"+ searchText +"%')";
}
in debug mode query is
`SELECT * FROM article,product where article.ItemNo=product.ItemNo AND (article.itemNo like '%ø%' OR product.Description like '%ø%')..`
No result returns
Proper query will be
SELECT * FROM article,product where article.ItemNo=product.ItemNo AND (article.itemNo like '%Ø%' OR product.Description like '%Ø%');
the desired description field value in Db is MØNTPUNG.
I am wondering is there any issue of case sensitivty?I am using UTF8 encoding for my raw file that will insert data to DB.

The documentation says:
SQLite only understands upper/lower case for ASCII characters by default. The LIKE operator is case sensitive by default for unicode characters that are beyond the ASCII range. For example, the expression 'a' LIKE 'A' is TRUE but 'æ' LIKE 'Æ' is FALSE.
To handle non-ASCII characters correctly, store an uppercase version of your string(s) in a separate column, and search in that with an uppercase search pattern.

Related

How do safely I add a raw string to a query?

My SQLite query :
let data = db.getAllRows(sql"""
SELECT name, source, uploaded_at, canonical_url, size
FROM table
WHERE name like ?
ORDER BY ? DESC
LIMIT ?
OFFSET ?
""", &"%{query}%", order, limit, offset)
Nim adds single quotes to any string replacing ?. I can manually build the SQL string and then use sql(string), but the input then isn't escaped. Is there some other token apart from ? that does not add '?
To answer your title question: "How to safely add a raw string to a query", you can use dbQuote:
import db_sqlite
let
a = "unes'caped %' string"
b = "my prefix ->"
c = "<- my suffix"
d = b & dbQuote(a) & c
echo d
This will print my prefix ->'unes''caped %'' string'<- my suffix, adding quotes before/after and escaping any ones inside. This string is presumably safe to pass as an sql statement. You should get the same result as if you had used ? with extra parameters.

How to *always* display blob value using x'abc' binary string literal syntax?

Very similar to How to display blob value using x'abc' binary string literal syntax?:
How can I have the sqlite3 shell display always display blob columns using the hex notation, as per e.g. quote(blob_column_name), without explicitly using quote, and in select * queries (and other contexts where blob_column_name isn't mentioned explicitly)?
(I suspect the answer is "you can't", but I'm hoping to be pleasantly surprised.)
There are two output modes that use SQL syntax (not only for blobs but for all values):
sqlite> .mode quote
sqlite> SELECT 1, x'123ABC', 'hello', null;
1,X'123abc','hello',NULL
sqlite> .mode insert
sqlite> SELECT 1, x'123ABC', 'hello', null;
INSERT INTO "table" VALUES(1,X'123abc','hello',NULL);

SQllite Query with Lower and Special Characters

I have a Sqllite query
SELECT * FROM m_table WHERE LOWER(fName) = LOWER('yui!"'':;/?') AND account = '100' ORDER BY fName COLLATE NOCASE ASC ;
Above returns 0 rows; But when I use the same as below , it Works
update m_table set fName = 'yui!"'':;/? renamed' where fname='yui!"'':;/?' AND account = '100';
Any clues ?
PS: I am using LOWER to ignore case sensitive. I am using this via an android client. Hence
I am also doing StringEscapeUtils.escapeSql("folderName")
This is most likely related to the fact, that your input string contains characters in a non-ASCII-charset. from the documentation of SQLlite:
lower(X) -- The lower(X) function returns a copy of string X with all
ASCII characters converted to lower case. The default built-in lower()
function works for ASCII characters only. To do case conversions on
non-ASCII characters, load the ICU extension.
http://www.sqlite.org/lang_corefunc.html
Try to run the following statement and see what it returns.
SELECT LOWER(fName) FROM m_table WHERE fname='yui!"'':;/?' AND account = '100';

Strange SQLite behavior: Not returning results on simple queries

Ok, so I have a basic table called "ledger", it contains fields of various types, integers, varchar, etc.
In my program, I used to use a query with no "from" predicate to collect all of the rows, which of course works fine. But... I changed my code to allow selecting one row at a time using "where acctno = x" (where X is the account number I want to select at the time).
I thought this must be a bug in the client library for my programming language, so I tested it in the SQLite command-line client - and it still doesn't work!
I am relatively new to SQLite, but I have been using Oracle, MS SQL Server, etc. for years and never seen this type of issue before.
Other things I can tell you:
* Queries using other integer fields also don't work
* Queries on char fields work
* Querying it as a string (with the account number on quotes) still doesn't work. (I thought maybe the numbers were stored as a string inadvertently).
* Accessing rows by rowid works fine - which is why I can edit the database with GUI tools with no noticeable problem.
Examples:
Query with no WHERE (works fine):
1|0|0|JPY|8|Paid-In Capital|C|X|0|X|0|0||||0|0|0|
0|0|0|JPY|11|Root Account|P|X|0|X|0|0|SYSTEM|20121209|150000|0|0|0|
3|0|0|JPY|13|Mitsubishi Bank Futsuu|A|X|0|X|0|0|SYSTEM|20121209|150000|0|0|0|
4|0|0|JPY|14|Japan Post Bank|A|X|0|X|0|0|SYSTEM|20121209|150000|0|0|0|
...
Query with WHERE clause: (no results)
sqlite> select * from ledger where acctno=1;
sqlite>
putting quotes around the 1 above changes nothing.
Interestingly enough, "select * from ledger where acctno > 1" returns results! However since it returns ALL results, it's not terrible useful.
I'm sure someone will ask about the table structure, so here goes:
sqlite> .schema ledger
CREATE TABLE "LEDGER" (
"ACCTNO" integer(10,0) NOT NULL,
"drbal" integer(20,0) NOT NULL,
"crbal" integer(20,0) NOT NULL,
"CURRKEY" char(3,0) NOT NULL,
"TEXTKEY" integer(10,0),
"TEXT" VARCHAR(64,0),
"ACCTYPECD" CHAR(1,0) NOT NULL,
"ACCSTCD" CHAR(1,0),
"PACCTNO" number(10,0) NOT NULL,
"CATCD" number(10,0),
"TRANSNO" number(10,0) NOT NULL,
"extrefno" number(10,0),
"UPDATEUSER" VARCHAR(32,0),
"UPDATEDATE" text(8,0),
"UPDATETIME" TEXT(6,0),
"PAYEECD" number(10,0) NOT NULL,
"drbal2" number(10,0) NOT NULL,
"crbal2" number(10,0) NOT NULL,
"delind" boolean,
PRIMARY KEY("ACCTNO"),
CONSTRAINT "fk_curr" FOREIGN KEY ("CURRKEY") REFERENCES "CURRENCY" ("CUR
RKEY") ON DELETE RESTRICT ON UPDATE CASCADE
);
The strangest thing is that I have other similar tables where this works fine!
sqlite> select * from journalhdr where transno=13;
13|Test transaction ATM Withdrawel 20130213|20130223||20130223||
TransNo in that table is also integer (10,0) NOT NULL - this is what makes me thing it is something to do with the values.
Another clue is that the sort order seems to be based on ascii, not numeric:
sqlite> select * from ledger order by acctno;
0|0|0|JPY|11|Root Account|P|X|0|X|0|0|SYSTEM|20121209|150000|0|0|0|
1|0|0|JPY|8|Paid-In Capital|C|X|0|X|0|0||||0|0|0|
10|0|0|USD|20|Sallie Mae|L|X|0|X|0|0|SYSTEM|20121209|153900|0|0|0|
21|0|0|USD|21|Skrill|A|X|0|X|0|0|SYSTEM|20121209|154000|0|0|0|
22|0|0|USD|22|AES|L|X|0|X|0|0|SYSTEM|20121209|154200|0|0|0|
23|0|0|JPY|23|Marui|L|X|0|X|0|0|SYSTEM|20121209|154400|0|0|0|
24|0|0|JPY|24|Amex JP|L|X|0|X|0|0|SYSTEM|20121209|154500|0|0|0|
3|0|0|JPY|13|Mitsubishi Bank Futsuu|A|X|0|X|0|0|SYSTEM|20121209|150000|0|0|0|
Of course the sort order on journalhdr (where the select works properly) is numeric.
Solved! (sort-of)
The data can be fixed like this:
sqlite> update ledger set acctno = 23 where rowid = 13;
sqlite> select * from ledger where acctno = 25;
25|0|0|JPY|0|Test|L|X|0|X|0|0|SYSTEM|20130224|132500|0|0|0|
Still, if it was stored as strings, then that leave a few questions:
1. Why couldn't I select it as a string using the quotes?
2. How did it get stored as a string since it is a valid integer?
3. How would you go about detecting this problem normally besides noticing bizzarre symptoms?
Although the data would normally be entered by my program, some of it was created by hand using Navicat, so I assume the problem must lie there.
You are victim of SQLite dynamic typing.
Even though SQLite defines system of type affinity, which sets some rules on how input strings or numbers will be converted to actual internal values, but it does NOT prevent software that is using prepared statements to explicitly set any type (and data value) for the column (and this can be different per row!).
This can be shown by this simple example:
CREATE TABLE ledger (acctno INTEGER, name VARCHAR(16));
INSERT INTO ledger VALUES(1, 'John'); -- INTEGER '1'
INSERT INTO ledger VALUES(2 || X'00', 'Zack'); -- BLOB '2\0'
I have inserted second row not as INTEGER, but as binary string containing embedded zero byte. This reproduces your issue exactly, see this SQLFiddle, step by step. You can also execute these commands in sqlite3, you will get the same result.
Below is Perl script that also reproduces this issue
This script creates just 2 rows with acctno having values of integer 1 for first, and "2\0" for second row. "2\0" means string consisting of 2 bytes: first is digit 2, and second is 0 (zero) byte.
Of course, it is very difficult to visually tell "2\0" from just "2", but this is what script below demonstrates:
#!/usr/bin/perl -w
use strict;
use warnings;
use DBI qw(:sql_types);
my $dbh = DBI->connect("dbi:SQLite:test.db") or die DBI::errstr();
$dbh->do("DROP TABLE IF EXISTS ledger");
$dbh->do("CREATE TABLE ledger (acctno INTEGER, name VARCHAR(16))");
my $sth = $dbh->prepare(
"INSERT INTO ledger (acctno, name) VALUES (?, ?)");
$sth->bind_param(1, "1", SQL_INTEGER);
$sth->bind_param(2, "John");
$sth->execute();
$sth->bind_param(1, "2\0", SQL_BLOB);
$sth->bind_param(2, "Zack");
$sth->execute();
$sth = $dbh->prepare(
"SELECT count(*) FROM ledger WHERE acctno = ?");
$sth->bind_param(1, "1");
$sth->execute();
my ($num1) = $sth->fetchrow_array();
print "Number of rows matching id '1' is $num1\n";
$sth->bind_param(1, "2");
$sth->execute();
my ($num2) = $sth->fetchrow_array();
print "Number of rows matching id '2' is $num2\n";
$sth->bind_param(1, "2\0", SQL_BLOB);
$sth->execute();
my ($num3) = $sth->fetchrow_array();
print "Number of rows matching id '2<0>' is $num3\n";
Output of this script is:
Number of rows matching id '1' is 1
Number of rows matching id '2' is 0
Number of rows matching id '2<0>' is 1
If you were to look at resultant table using any SQLite tool (including sqlite3), it will print 2 for second row - they all get confused by trailing 0 inside a BLOB when it gets coerced to string or number.
Note that I had to use custom param binding to coerce type to BLOB and permit null bytes stored:
$sth->bind_param(1, "2\0", SQL_BLOB);
Long story short, it is either some of your client programs, or some of client tools like Navicat which screwed it up.

Escape single quote character for use in an SQLite query

I wrote the database schema (only one table so far), and the INSERT statements for that table in one file. Then I created the database as follows:
$ sqlite3 newdatabase.db
SQLite version 3.4.0
Enter ".help" for instructions
sqlite> .read ./schema.sql
SQL error near line 16: near "s": syntax error
Line 16 of my file looks something like this:
INSERT INTO table_name (field1, field2) VALUES (123, 'Hello there\'s');
The problem is the escape character for a single quote. I also tried double escaping the single quote (using \\\' instead of \'), but that didn't work either. What am I doing wrong?
Try doubling up the single quotes (many databases expect it that way), so it would be :
INSERT INTO table_name (field1, field2) VALUES (123, 'Hello there''s');
Relevant quote from the documentation:
A string constant is formed by enclosing the string in single quotes ('). A single quote within the string can be encoded by putting two single quotes in a row - as in Pascal. C-style escapes using the backslash character are not supported because they are not standard SQL. BLOB literals are string literals containing hexadecimal data and preceded by a single "x" or "X" character. ... A literal value can also be the token "NULL".
I believe you'd want to escape by doubling the single quote:
INSERT INTO table_name (field1, field2) VALUES (123, 'Hello there''s');
for replace all (') in your string, use
.replace(/\'/g,"''")
example:
sample = "St. Mary's and St. John's";
escapedSample = sample.replace(/\'/g,"''")
Just in case if you have a loop or a json string that need to insert in the database. Try to replace the string with a single quote . here is my solution. example if you have a string that contain's a single quote.
String mystring = "Sample's";
String myfinalstring = mystring.replace("'","''");
String query = "INSERT INTO "+table name+" ("+field1+") values ('"+myfinalstring+"')";
this works for me in c# and java
In C# you can use the following to replace the single quote with a double quote:
string sample = "St. Mary's";
string escapedSample = sample.Replace("'", "''");
And the output will be:
"St. Mary''s"
And, if you are working with Sqlite directly; you can work with object instead of string and catch special things like DBNull:
private static string MySqlEscape(Object usString)
{
if (usString is DBNull)
{
return "";
}
string sample = Convert.ToString(usString);
return sample.Replace("'", "''");
}
In bash scripts, I found that escaping double quotes around the value was necessary for values that could be null or contained characters that require escaping (like hyphens).
In this example, columnA's value could be null or contain hyphens.:
sqlite3 $db_name "insert into foo values (\"$columnA\", $columnB)";
Demonstration of single quoted string behavior where complexity or double quotes are not desired.
Test:
SELECT replace('SAMY''S','''''','''');
Output:
SAMY'S
SQLite version:
SELECT sqlite_version();
Output:
3.36.0

Resources