Problem with automated SQLite query via Node Red - sqlite

Warning, I am a complete noob with SQLite and Node-Red.
I am working on a project to scan and read car license plates. I now have the hardware up and running, it is passing plate information to a very basic SQLite 3 table of two records through Node-Red on a Raspberry Pi 3.
I can run instant queries, where a module sends over an exact query to run, ie
SELECT "License_Plate" FROM QuickDirtyDB WHERE "License_Plate" LIKE "%RAF66%"
This will come back with my plate RAF660, as below
topic: "SELECT "License_Plate" FROM QuickDirtyDB WHERE "License_Plate" LIKE "%RAF66%""
payload: array[1]
0: object
License_Plate: "RAF660"
When I automate and run this query it will not work, have been playing with this for three days now.
I am even unable to get a very basic automated query to work like
'var readlpr = msg.payload;
msg.topic = 'SELECT "License_Plate" FROM QuickDirtyDB WHERE "License_Plate" = ' + readlpr + ''
return msg;'
that's two single quotes at the end of the query line.
This is sent through to the query as below, it is the output from the debug node, exactly what is going into the query.
"SELECT "License_Plate" FROM QuickDirtyDB WHERE "License_Plate" = RAF660 "
and the error that comes out is,
"Error: SQLITE_ERROR: no such column: RAF660"
After this is working, I need to work out how I can allow a mismatch of two characters in case the OCR software either misread two characters or even drops two characters entirely. Is this something that a query can handle, or will I have to pass many plate details to a program to work out if I have a match?
I thought I would have had to run a query to create some kind of a view and then requery my read plate vs that view to see which plate in the database is the closest match, not sure if I have the terminology correct, view, join, union etc.
Thank you for looking and any suggestions you may have.
I will probably be going home in about an hour, so may not be able to check back in till Monday

RAF660 is a string and needs to be quoted "RAF660"
License_Plate is a column and should not be quoted.
The way you have it reads as fetch the rows where the RAF660 column is set to the value "License_Plate".

Related

How to implement INSERT where not exists for ORACLE in Mule4

I am trying to implement a use-case in Mule4 where a tour needs to be assigned to a user if it has not already been assigned.
I was hoping that I could implement it using Mule db:insert component and using INSERT WHERE NOT EXISTS SQL script as below.
INSERT INTO TL_MAPPING_TOUR(TOURNO,TLID,SYSTEM) select :tourno,:tlid,:system from DUAL
where not exists(select * from TL_MAPPING_TOUR where (TOURNO=:tourno and TLID=:tlid and SYSTEM=:system))
However, this is resulting in Mule Exception
Message : ORA-01722: invalid number
Error type : DB:BAD_SQL_SYNTAX
TL_MAPPING_TOUR table has an id column (Primary Key), but that is auto-generated by a sequence.
The same script, modified for running directly in SQL developer, as shown below, is working fine.
INSERT into TL_MAPPING_TOUR(TOURNO,TLID,SYSTEM)
select 'CLLO001474','123456789','AS400'
from DUAL
where not exists(select * from TL_MAPPING_TOUR where (TOURNO='CLLO001474' and TLID='123456789' and SYSTEM='AS400'));
Clearly Mule db:insert component doesn't like the syntax, but it's not very clear to me what is wrong here. I can't find any INSERT WHERE NOT EXISTS example implementation for the Mule4 Database component either.
stackoverflow page https://stackoverflow.com/questions/54910330/insert-record-into-sql-server-when-it-does-not-already-exist-using-mule directs to page not found.
Any idea what is wrong here and how to implement this in Mule4 without using another Mule4 db:select component before db:insert?
I don't know "mule4", but this:
Message : ORA-01722: invalid number
doesn't mean that syntax is wrong (as you already tested it - the same statement works OK in another tool).
Cause: You executed a SQL statement that tried to convert a string to a number, but it was unsuccessful.
Resolution:
The option(s) to resolve this Oracle error are:
Option #1: Only numeric fields or character fields that contain numeric values can be used in arithmetic operations. Make sure that all expressions evaluate to numbers.
Option #2: If you are adding or subtracting from dates, make sure that you added/substracted a numeric value from the date.
In other words, it seems that one of columns is declared as NUMBER, while you passed something that is a string. Oracle performed implicit conversion when you tested the statement in SQL Developer, but it seems that mule4 didn't and hence the error.
The most obvious cause (based on what you posted) is putting '123456789' into TLID as other values are obviously strings. Therefore, pass 123456789 (a number, no single quotes around it) and see what happens. Should work.
SQL Developer is too forgiving. It will convert string to numbers and vise versa automatically when it can. And it can a lot.
Mulesoft DB connector tries the same but it is not as succefule as native tools. Pretty often it fails to convert, especially on dates but this is not your case.
In short - do not trust too much data sense of Mulesoft. If it works - great! Otherwise try to eliminate any intelligence from it and do all conversions in the query and better from the string. Usually number works fine but if doesn't - use to_number function to mark properly that this is the number.
More about this is here https://simpleflatservice.com/mule4/AvoidCoversionsOrMakeThemNative.html

Error with SQLite query, What am I missing?

I've been attempting to increase my knowledge and trying out some challenges. I've been going at this for a solid two weeks now finished most of the challenge but this one part remains. The error is shown below, what am i not understanding?
Error in sqlite query: update users set last_browser= 'mozilla' + select sql from sqlite_master'', last_time= '13-04-2019' where id = '14'
edited for clarity:
I'm trying a CTF challenge and I'm completely new to this kind of thing so I'm learning as I go. There is a login page with test credentials we can use for obtaining many of the flags. I have obtained most of the flags and this is the last one that remains.
After I login on the webapp with the provided test credentials, the following messages appear: this link
The question for the flag is "What value is hidden in the database table secret?"
So from the previous image, I have attempted to use sql injection to obtain value. This is done by using burp suite and attempting to inject through the user-agent.
I have gone through trying to use many variants of the injection attempt shown above. Im struggling to find out where I am going wrong, especially since the second single-quote is added automatically in the query. I've gone through the sqlite documentation and examples of sql injection, but I cannot sem to understand what I am doing wrong or how to get that to work.
A subquery such as select sql from sqlite_master should be enclosed in brackets.
So you'd want
update user set last_browser= 'mozilla' + (select sql from sqlite_master''), last_time= '13-04-2019' where id = '14';
Although I don't think that will achieve what you want, which isn't clear. A simple test results in :-
You may want a concatenation of the strings, so instead of + use ||. e.g.
update user set last_browser= 'mozilla' || (select sql from sqlite_master''), last_time= '13-04-2019' where id = '14';
In which case you'd get something like :-
Thanks for everyone's input, I've worked this out.
The sql query was set up like this:
update users set last_browser= '$user-agent', last_time= '$current_date' where id = '$id_of_user'
edited user-agent with burp suite to be:
Mozilla', last_browser=(select sql from sqlite_master where type='table' limit 0,1), last_time='13-04-2019
Iterated with that found all tables and columns and flags. Rather time consuming but could not find a way to optimise.

How to put a part of a code as a string in table to use it in a procedure?

I'm trying to resolve below issue:
I need to prepare table that consists 3 columns:
user_id,
month
value.
Each from over 200 users has got different values of parameters that determine expected value which are: LOB, CHANNEL, SUBSIDIARY. So I decided to store it in table ASYSTENT_GOALS_SET. But I wanted to avoid multiplying rows and thought it would be nice to put all conditions as a part of the code that I would use in "where" clause further in procedure.
So, as an example - instead of multiple rows:
I created such entry:
So far I created testing table ASYSTENT_TEST (where I collect month and value for certain user). I wrote a piece of procedure where I used BULK COLLECT.
declare
type test_row is record
(
month NUMBER,
value NUMBER
);
type test_tab is table of test_row;
BULK_COLLECTOR test_tab;
p_lob varchar2(10) :='GOSP';
p_sub varchar2(14);
p_ch varchar2(10) :='BR';
begin
select subsidiary into p_sub from ASYSTENT_GOALS_SET where user_id='40001001';
execute immediate 'select mc, sum(ppln_wartosc) plan from prod_nonlife.mis_report_plans
where report_id = (select to_number(value) from prod_nonlife.view_parameters where view_name=''MIS'' and parameter_name=''MAX_REPORT_ID'')
and year=2017
and month between 7 and 9
and ppln_jsta_symbol in (:subsidiary)
and dcs_group in (:lob)
and kanal in (:channel)
group by month order by month' bulk collect into BULK_COLLECTOR
using p_sub,p_lob,p_ch;
forall x in BULK_COLLECTOR.first..BULK_COLLECTOR.last insert into ASYSTENT_TEST values BULK_COLLECTOR(x);
end;
So now when in table ASYSTENT_GOALS_SET column SUBSIDIARY (varchar) consists string 12_00_00 (which is code of one of subsidiary) everything works fine. But the problem is when user works in two subsidiaries, let say 12_00_00 and 13_00_00. I have no clue how to write it down. Should SUBSIDIARY column consist:
'12_00_00','13_00_00'
or
"12_00_00","13_00_00"
or maybe
12_00_00','13_00_00
I have tried a lot of options after digging on topics like "Deling with single/escaping/double qoutes".
Maybe I should change something in execute immediate as well?
Or maybe my approach to that issue is completely wrong from the very beginning (hopefully not :) ).
I would be grateful for support.
I didn't create the table function described here but that article inspired me to go back to try regexp_substr function again.
I changed: ppln_jsta_symbol in (:subsidiary) to
ppln_jsta_symbol in (select regexp_substr((select subsidiary from ASYSTENT_GOALS_SET where user_id=''fake_num''),''[^,]+'', 1, level) from dual
connect by regexp_substr((select subsidiary from ASYSTENT_GOALS_SET where user_id=''fake_num''), ''[^,]+'', 1, level) is not null) Now it works like a charm! Thank you #Dessma very much for your time and suggestion!
"I wanted to avoid multiplying rows and thought it would be nice to put all conditions as a part of the code that I would use in 'where' clause further in procedure"
This seems a misguided requirement. You shouldn't worry about number of rows: databases are optimized for storing and retrieving rows.
What they are not good at is dealing with "multi-value" columns. As your own solution proves, it is not nice, it is very far from nice, in fact it is a total pain in the neck. From now on, every time anybody needs to work with subsidiary they will have to invoke a function. Adding, changing or removing a user's subsidiary is much harder than it ought to be. Also there is no chance of enforcing data integrity i.e. validating that a subsidiary is valid against a reference table.
Maybe none of this matters to you. But there are very good reasons why Codd mandated "no repeating groups" as a criterion of First Normal Form, the foundation step of building a sound data model.
The correct solution, industry best practice for almost forty years, would be to recognise that SUBSIDIARY exists at a different granularity to CHANNEL and so should be stored in a separate table.

SQL Code for Running Total does not recognise table name

I have a question on creating running totals in MS Access 2010 similar to the one here:
Access 2010 - query showing running total for multiple records, dropping old record and adding new record on each line
However when I input the equivalent code from that thread I get an error saying that the database cannot be found (Access seems to think the table I have specified is the database name)
Here is the code from the original thread:-
SELECT hbep1.EmployeeID, hbep1.PayPeriodID,
(
SELECT Sum(hbep2.HoursUsed)
FROM Hours_by_Empl_PP hbep2
WHERE hbep2.EmployeeID=hbep1.EmployeeID
AND (hbep2.PayPeriodID Between hbep1.[PayPeriodID]-3
And hbep1.[PayPeriodID])
) AS Sum_of_Hours_last_4_PPs
FROM Hours_by_Empl_PP hbep1;
Here is the code I inputted into my query:-
SELECT
V4_Try.ID_NIS_INV_HDR,
V4_Try.ID_ITM,
V4_Try.RunTot3,
V4_Try.BomVsActQty,
DMin("RunTot3","V4_Try","[ID_Itm]=" & [ID_ITM]) AS IDItmMin,
DMax("RunTot3","V4_Try","[ID_Itm]=" & [ID_ITM]) AS IDItmMax,
(
SELECT Sum([V4_Try].[BomVsActQty])
FROM [V4_Try].[BomVsActQty]
WHERE [V4_Try].[ID_ITM]=[V4_Try].[ID_ITM]
AND (IDItmMax < IDItmMin)
) AS RunTot6
FROM V4_Try
ORDER BY V4_Try.ID_ITM, V4_Try.RunTot3;
One thing I notice is that the main query uses DMax() and DMin() to create some aliased columns
...
DMin("RunTot3","V4_Try","[ID_Itm]=" & [ID_ITM]) AS IDItmMin,
DMax("RunTot3","V4_Try","[ID_Itm]=" & [ID_ITM]) AS IDItmMax,
...
and then the subquery tries to use those aliases in its WHERE clause
(
SELECT ...
WHERE...
AND (IDItmMax < IDItmMin)
) AS RunTot6
I'm pretty sure that the subquery will have no knowledge of the column aliases in the "parent" query, so they may be the items that are unrecognized.
Start by running this query:
SELECT * FROM V4_Try;
Then develop for complexity. Build the nested query before anything else. When you know that runs, try adding your aliases, then the DMax() function, and so on. Isolate the point at which you have an error popping up.
This is the process to fix a query.
Oh, and please specify the precise error that is raised by Access. Also, if this is being run from VBA, please let us know because that affects your trouble-shooting.

ASP.NET / SQL drop-down list sort order

I am trying to correct the sort order of my ASP.NET drop down list.
The problem I have is that I need to select a distinct Serial number and have these numbers organised by DateTime Desc.
However I cannot ORDER BY DateTime if using DISTINCT without selecting the DateTime field in my query.
However if I select DateTime this selects every data value associated with a single Serial number and results in duplications.
The purpose of my page is to display data for ALL Serials, or data associated to one serial. When a new cycle begins (because it is a new production run) the Serial reverts to 1. So I cannot simply organise by serial number either.
When I use the following SQL statement the list box is in the order I require but after a period of time (usually a few hours) the order changes and appears to have no organised structure.
alt text http://img7.imageshack.us/i/captureky.jpg/
I'm fairly new to ASP.NET / SQL, does anyone know of a solution to my problem.
If you have multiple date times for each serial number, then which do you want to use for ordering? If the most recent, try this:
SELECT SerialNumber,
MAX(DateTimeField)
FROM Table
GROUP BY SerialNumber
ORDER BY 2 DESC
I don´t know if everybody agrees with that, but when I see a DISTINCT in a query the first thought that goes trough my mind is "This is wrong". Generally, DISTINCT is not necessary and it´s used when the person writing the query doesnt know very well what he is doing and this might be the case since you said you are new with Sql.
Without complete knowledge of your model is difficult to assist you a hundred percente, but I would say that you should use a GROUP BY clause instead of DISTINCT, then you can order it correctly.

Resources