I already downloaded the latest SQLite.dll from SQLite Download Page and try to load it using TFDPhysDriverLink.VendorLib
But when I run the app, which contains the following code:
procedure TForm1.FormCreate(Sender: TObject);
begin
FDConnection1.Close;
FDPhysSQLiteDriverLink1.Release;
FDPhysSQLiteDriverLink1.VendorLib:= 'Path\SQLite3.dll';
FDQuery1.Open('SELECT *, ROW_NUMBER() OVER() Col FROM TableName');
end;
It throws:
[FireDAC][Phys][SQLite] ERROR: near "(": syntax error
Which means that the window function ROW_NUMBER() is not recognized.
What I'm doing wrong?
How can I force FireDAC to use the latest SQLite.dll?
SQLite do not support ROW_NUMBER.
Look at the answers for this question, you'll probably find something to replace ROW_NUMBER.
If you get this error, then the SQlite3.dll was loaded just fine.
Just use the RowID field, which is always existing for any standard SQLite3 table - unless you explicitly created them with CREATE TABLE WITHOUT ROWID statement.
So I would just write:
FDQuery1.Open('SELECT *, RowID FROM TableName');
Note that if there is an explicit INTEGER PRIMARY KEY column in your table, it will in fact map the internal RowID column. Check the SQLite3 documentation for how this works.
Related
let's suppose to have the table
create table mytable
(val1 number(5),
val2 varchar2(10));
insert into mytable values (1,'XXX');
and asked to generate the following XML
<ns1:head>
<ns1:val1>1</val1>
<ns1:val2>XXX</val2>
</ns1:head>
It's quite simple by running
select xmlelement("head",
xmlelement("val1",val1).extract('/*'),
xmlelement("val2",val2).extract('/*')
).extract('/*')
from mytable;
and to get
<head>
<val1>1</val1>
<val2>XXX</val2>
</head>
The problem is that if I try to do that way but for getting each node with "ns1:" in front of every tag
select xmlelement("ns1:head",
xmlelement("ns1:val1",val1).extract('/*'),
xmlelement("ns1:val2",val2).extract('/*')
).extract('/*')
from mytable;
I get an ORA-31011: XML parsing failed
Maybe I dont' konw how exactly the .extract('/*') works and in my case the "ns1:" could fails
Oracle version 10g
Thanks in advance!
Mark
What is the purpose of using extract('/*')?
Also a namespace prefix must be defined. You can add its declaration in the root element with xmlattributes.
select xmlelement("ns1:head", xmlattributes('http://www.example.com/ns1' as "xmlns:ns1"),
xmlelement("ns1:val1",val1),
xmlelement("ns1:val2",val2)
)
from mytable;
result:
<ns1:head xmlns:ns1="http://www.example.com/ns1"><ns1:val1>1</ns1:val1><ns1:val2>XXX</ns1:val2></ns1:head>
Update:
XMLELEMENT returns and XML object. If you want to get it as a formatted text, you can use XMLSERIALIZE.
select XMLSERIALIZE(document xmlelement("ns1:head", xmlattributes('http://www.example.com/ns1' as "xmlns:ns1"),
xmlelement("ns1:val1",val1),
xmlelement("ns1:val2",val2)
) indent)
from mytable;
result:
<ns1:head xmlns:ns1="http://www.example.com/ns1">
<ns1:val1>1</ns1:val1>
<ns1:val2>XXX</ns1:val2>
</ns1:head>
Update 2:
as I found out, indent instruction does not exist in Oracle 10g. So, if extract('/*') worked without namespaces, then adding xmlattributes to your original query with namespaces might work. I don't have Oracle 10g to test this.
select xmlelement("ns1:head", xmlattributes('http://www.example.com/ns1' as "xmlns:ns1"),
xmlelement("ns1:val1",val1).extract('/*'),
xmlelement("ns1:val2",val2).extract('/*')
).extract('/*')
from mytable;
Update 3:
Using extract('/*') for indenting lines looks like an undocumented feature. On Oracle 12c it doesn't work this way. So, updating Oracle version might break this undocumented behavior.
select sqlite_version();
INSERT INTO users (uuid, test_field) VALUES ('uuid1', '1.0);
INSERT INTO users (uuid) VALUES ('uuid1') ON CONFLICT(uuid) DO UPDATE SET test_field = '1.1';
The above results in:
3.8.11.1
OK
ERROR: near "ON": syntax error
Why is it failing to recognize the ON word of ON CONFLICT
The us of ON CONFLICT is what is termed as an UPSERT and was only introduced in SQLite 3.24.0.
as per :-
UPSERT is a special syntax addition to INSERT that causes the INSERT
to behave as an UPDATE or a no-op if the INSERT would violate a
uniqueness constraint. UPSERT is not standard SQL. UPSERT in SQLite
follows the syntax established by PostgreSQL. UPSERT syntax was added
to SQLite with version 3.24.0 (2018-06-04).
SQL As Understood By SQLite - upsert
As such it cannot be used in SQLite 3.8.11.1 and thus the SYNTAX error near ON as it's not a recognised keyword in that context.
update table set column_name limit 3 offset 2;
The above query is not working.
Throws error
sql error: syntax error near 'limit'.
An UPDATE statement expects a new value after the column_name, like this:
update thetable set column_name = 'some new value'
Furthermore, the documentation mentions that you need to have compiled SQLite with the SQLITE_ENABLE_UPDATE_DELETE_LIMIT option, which is not enabled by default.
Sqlite does not allow the use of LIMIT and OFFSET statements like in MYSQL. You will have to use a nested query to workaround it . Or use two queries.
delete N.* from Tbl_Nodes N, Data_Tree DT WHERE N.Part = DT.Part
for this command I am getting following error.
System.Data.SQLite.SQLiteException: SQLite error near "N": syntax error
Above command works fine for MSAccess.
Is there any alternative to use table shortcut in Sqlite?
The DELETE statement operates on a single table and does not use a table alias. Therefore, your FROM clause must read FROM Tbl_Nodes.
You're probably looking for:
delete from Tbl_Nodes WHERE Part IN (SELECT Part FROM Data_Tree)
Note that this will remove all nodes from Tbl_Nodes that have a corresponding Part value in Data_Tree but does not remove any records from Data_Tree itself.
While SQL varies somewhat among vendors, as a general principle it's a mistake to learn SQL from MS Access and try to apply it to other products. MS Access features some very non-standard constructions.
Using an alias for the table?
FROM table AS t1
You're missing a bit of your SQL statement there I guess but does it not work if you just say:
delete N from Tbl_Nodes N, Data_tree DT WHERE...(rest of statement)
I've just removed the .*
Here's a strange one:
I can filter on NOT NULLS from SQLite, but not NULLS:
This works:
SELECT * FROM project WHERE parent_id NOT NULL;
These don't:
SELECT * FROM project WHERE parent_id IS NULL;
SELECT * FROM project WHERE parent_id ISNULL;
SELECT * FROM project WHERE parent_id NULL;
All return:
There is a problem with the syntax of your query (Query was not
executed) ...
UPDATE:
I am doing this with PHP- through my code with ezSQl and using the PHPLiteAdmin interface
Using the PHPLiteAdmin demo, this expression works- so now I'm suspecting a version issue with my PHP's SQLite? Could that be? Wasn't this expression always valid?
UPDATE 2:
When I run the code from PHP using ezSQL, the PHP warning is:
PHP Warning: SQL logic error or missing database
Is there a way to get more information out of PHP? This is maddeningly opaque and weird, especially because the same statement in the CLI works fine...
UPDATE 3
The only other possible clue I have is that the databases that I create with PHP cannot be read by the CLI, and vice versa. I get:
Error: file is encrypted or is not a database
So there's definitly two SQlite flavors butting heads here. (See this) Still, why the invalid statment??
UPDATE 4
OK I think I've traced the problem to the culprit, if not the reason- The DB I created with PHP ezSQL is the one where the IS NULL statement fails. If I create the DB using PHP's SQLite3 class, the statement works fine, and moreover, I can access the DB from the CLI, whereas ezSQL created DB gave the file is encrypted error.
So I did a little digging into ezSQL code- Off the bat I see it uses PDO methods, not the newer SQLite3 class. Maybe that's something- I'm not gonna waste further time on it...
In any case, I've found my solution, which is to steer clear of ezSQL, and just use PHPs SQLite3 class.
a IS b and a IS NOT b is the general form where a and b are expressions.
This is generally only seen in a IS NULL and a IS NOT NULL cases. There are also ISNULL and NOTNULL (also NOT NULL) operators which are short-hands for the previous expressions, respectively (they only take in a single operand).
The SQL understood in SQLite expressions is covered in SQLite Query Language: Expressions.
Make sure that (previous) statements have been terminated with a ; first if using the CLI.
These are all valid to negate a "null match":
expr NOT NULL
expr NOTNULL
expr IS NOT NULL
These are all valid to "match null":
expr ISNULL
expr IS NULL
Since all of the above constructs are themselves expressions the negations are also valid (e.g. NOT (expr NOT NULL) is equivalent to expr IS NULL).
Happy coding.
The proof in the pudding:
SQLite version 3.7.7.1 2011-06-28 17:39:05
Enter ".help" for instructions
Enter SQL statements terminated with a ";"
sqlite> create table x (y int null);
sqlite> select * from x where y isnull;
sqlite> select * from x where y notnull;
sqlite> select * from x where y not null;
sqlite> select * from x where y is null;
sqlite> select * from x where y is not null;
sqlite>
The problem could stem from how SQLite handles empty columns. For instance just because a column is empty does not mean it is NULL. Have you tested against ""?
SELECT * FROM project WHERE parent_id = ""
That query might return results.
In Android SQLite, field IS NULL doesn't work either.
field = 'null' does. Give it a try in your environment
This works on SQLite in SQLite Manager for Firefox:
select * from foo where not baz is not null
The query above returns rows where column [baz] is null. :-) Yarin, maybe it will work for you?
(The 'not' before the column name is not a typo).
This query too finds rows where baz is null:
select * from foo where [baz] is null
If you are testing perhaps the PK column (?) and the column is being treated as synonym for rowid, then no rows will have a rowid that's null.
try where your_col_name ISNULL
wheres ISNULL contains no space