How to implement INSERT where not exists for ORACLE in Mule4 - sql-insert

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

Related

age control 2 for pl/sql

i am trying to find out at what age an employee started working.
if he started under 16 he should report this 'Error when entering the date of birth' mistake. so my trigger is created but my trigger is not working
I get ever this error: ORA-01422: Exact retrieval returns more than the requested number of lines
i can't find the problem
Here is the code:
SET SERVEROUTPUT ON
ACCEPT Birthday PROMPT ' Pleas give you Date of birth: '
CREATE OR REPLACE TRIGGER T_Controll
before INSERT ON meine_Firma -- Table
FOR EACH ROW
DECLARE
V_Berufstart meine_Firma.Hiredate%TYPE; --Job begin
V_Geburtsdatum DATE; -- Date of birth
V_Alter number:=0; -- AGE
SELECT HIREDATE INTO V_Berufstart FROM meine_Firma;
BEGIN
V_Geburtsdatum:=('&Birthday');
V_Alter:= Round(MONTHS_BETWEEN(V_Berufstart,V_Geburtsdatum)-2)/12;
IF 16 > V_Alter THEN
RAISE_APPLICATION_ERROR(-20201,'Error when entering the date of birth');
END IF;
END;
/
SET SERVEROUTPUT OFF
If he under 16 then he may not work
sorry my english is not good (=
You have a much bigger issue in this script than the error you are getting. Even after correcting as #ShaunPeterson suggested it will still fail
, it WILL NOT generate an error it will just not run as you expect. The issue is you failed to understand substitution variables - the use of &name (Specifically here &Birthday.) I'll actually use &Birthday in the following but the discussion applies to ANY/ALL substitution variables.
people fail to understand why they can't use the "&" substitution
variables in their PL/SQL procedures and functions to prompt for input
at run time. This article will hopefully help clarify in your mind
what the differences are so that you can understand where and when to
use these.
Substitution Variables The clue here is in the name... "substitution". It relates to values being substituted into the code
before it is submitted to the database. These substitutions are
carried out by the interface being used
The effect of this substitution is the the line containing the substitution variable is physically rewritten by the interface replacing %Birthday. In this case if you don't enter a value or the date 2000-05-19 the statement before and after substitution is
BEFORE: V_Geburtsdatum:=('&Birthday');
AFTER: V_Geburtsdatum:=(''); OR V_Geburtsdatum:=('2000-05-19');
Either way the after is what the compiler sees; it does NOT see %Birthday at all. Moreover when run the trigger will not prompt for a value. As far as the compiler is concerned it is a hard coded value that will never change. Beyond that a trigger, or any other PLSQL script (stored or anonymous) never prompts for values, they are actually incapable of doing so as it is not part of the language. Any prompt is via your interface software not plsql.
I'm going to suggest a way to avoid the trigger altogether. Getting on soap box: Triggers are BAD, they have some usefulness for assigning auto incrementing keys (before 12c),logging, very limited auditing, etc. However, for business rules they should be the option of last resort. Ok Get off soap box.
The first thing is to make the columns meine_Firma.Hiredate and meine_Firma.Geburtsdatum NOT null (if not already). If either are NULL you cannot calculate anything with them, the result would be NULL.
Second create a new column age_at_hire (or whatever) as a virtual column then put a check constraint on it. And voila trigger no longer needed. See fiddle for demo.
So the proposed change (YES you will probably have to clean up the bad data first):
alter table meine_Firma modify
( hiredate not null
, Geburtsdatum not null
) ;
alter table meine_Firma add
( age_at_hire integer generated always as (trunc(months_between(hiredate,Geburtsdatum))) virtual
, constraint check_age_at_hire check (age_at_hire >= 16*12)
);
Anyway, I hope you get an understanding of substitution variables for the future. And learn to avoid triggers. Good luck.
The reason you are getting that specific error is that the below select will select ALL rows from meine_Firma as there is no where clause
SELECT HIREDATE INTO V_Berufstart FROM meine_Firma;
However because you are in a trigger you do not need to select anything you use the :NEW bind variable. So you can just use
V_Berufstart := :NEW.HIREDATE;
If this was an update trigger there would be both a :NEW and :OLD bind variable declared so that you can access the OLD and NEW values. As this is an Insert trigger the :OLD will just be null as there is no old values.

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.

UPDATE statement not working in sqlite

I'm using the following command to update a field in my database:
UPDATE Movies SET 'From'=2 WHERE 'Name'="foo";
I'm using sqlite3.exe in windows (command prompt). Although no error message is produced, nothing changes in the table. I examined the database with a couple of gui tools and I'm sure UPDATE does nothing.
'From' is of type integer and 'Name' is text.
The problem you've got is that you're getting your quoting wrong. SQLite follows the SQL standard here, and that specifies what quote characters to use: '…' is for strings, and "…" is for tokens (like special names used as column or table names). Sometimes it manages to guess what you mean anyway and compensate for getting it wrong, but it can't with the WHERE clause because that is syntactically correct (if decidedly unhelpful):
Swapping the quoting appears to work:
UPDATE Movies SET "From"=2 WHERE "Name"='foo';
Those aren't good column names. Both are keywords, best avoided, and not self-explanatory at all.
Do a SELECT to see how many rows match the WHERE clause in the UPDATE. If none come back, you have your answer.
Did you commit the UPDATE? Is auto commit turned on?

MS Access CREATE PROCEDURE Or use Access Macro in .NET

I need to be able to run a query such as
SELECT * FROM atable WHERE MyFunc(afield) = "some text"
I've written MyFunc in a VB module but the query results in "Undefined function 'MyFunc' in expression." when executed from .NET
From what I've read so far, functions in Access VB modules aren't available in .NET due to security concerns. There isn't much information on the subject but this avenue seems like a daed end.
The other possibility is through the CREATE PROCEDURE statement which also has precious little documentation: http://msdn.microsoft.com/en-us/library/bb177892%28v=office.12%29.aspx
The following code does work and creates a query in Access:
CREATE PROCEDURE test AS SELECT * FROM atable
However I need more than just a simple select statement - I need several lines of VB code.
While experimenting with the CREATE PROCEDURE statement, I executed the following code:
CREATE PROCEDURE test AS
Which produced the error "Invalid SQL statement; expected 'DELETE', 'INSERT', 'PROCEDURE', 'SELECT', or 'UPDATE'."
This seems to indicate that there's a SQL 'PROCEDURE' statement, so then I tried
CREATE PROCEDURE TEST AS PROCEDURE
Which resulted in "Syntax error in PROCEDURE clause."
I can't find any information on the SQL 'PROCEDURE' statement - maybe I'm just reading the error message incorrectly and there's no such beast. I've spent some time experimenting with the statement but I can't get any further.
In response to the suggestions to add a field to store the value, I'll expand on my requirements:
I have two scenarios where I need this functionality.
In the first scenario, I needed to enable the user to search on the soundex of a field and since there's no soundex SQL function in Access I added a field to store the soundex value for every field in every table where the user wants to be able to search for a record that "soundes like" an entered value. I update the soundex value whenever the parent field value changes. It's a fair bit of overhead but I considered it necessary in this instance.
For the second scenario, I want to normalize the spacing of a space-concatenation of field values and optionally strip out user-defined characters. I can come very close to acheiving the desired value with a combination of TRIM and REPLACE functions. The value would only differ if three or more spaces appeared between words in the value of one of the fields (an unlikely scenario). It's hard to justify the overhead of an extra field on every field in every table where this functionality is needed. Unless I get specific feedback from users about the issue of extra spaces, I'll stick with the TRIM & REPLACE value.
My application is database agnostic (or just not very religious... I support 7). I wrote a UDF for each of the other 6 databases that does the space normalization and character stripping much more efficiently than the built-in database functions. It really annoys me that I can write the UDF in Access as a VB macro and use that macro within Access but I can't use it from .NET.
I do need to be able to index on the value, so pulling the entire column(s) into .NET and then performing my calculation won't work.
I think you are running into the ceiling of what Access can do (and trying to go beyond). Access really doesn't have the power to do really complex TSQL statements like you are attempting. However, there are a couple ways to accomplish what you are looking for.
First, if the results of MyFunc don't change often, you could create a function in a module that loops through each record in atable and runs your MyFunc against it. You could either store that data in the table itself (in a new column) or you could build an in-memory dataset that you use for whatever purposes you want.
The second way of doing this is to do the manipulation in .NET since it seems you have the ability to do so. Do the SELECT statement and pull out the data you want from Access (without trying to run MyFunc against it). Then run whatever logic you want against the data and either use it from there or put it back into the Access database.
Why don't you want to create an additional field in your atable, which is atable.afieldX = MyFunc(atable.afield)? All what you need - to run UPDATE command once.
You should try to write a SQL Server function MyFunc. This way you will be able to run the same query in SQLserver and in Access.
A few usefull links for you so you can get started:
MSDN article about user defined functions: http://msdn.microsoft.com/en-us/magazine/cc164062.aspx
SQLServer user defined functions: http://www.sqlteam.com/article/intro-to-user-defined-functions-updated
SQLServer string functions: http://msdn.microsoft.com/en-us/library/ms181984.aspx
What version of JET (now called Ace) are you using?
I mean, it should come as no surprise that if you going to use some Access VBA code, then you need the VBA library and a copy of MS Access loaded and running.
However, in Access 2010, we now have table triggers and store procedures. These store procedures do NOT require VBA and in fact run at the engine level. I have a table trigger and soundex routine here that shows how this works:
http://www.kallal.ca/searchw/WebSoundex.htm
The above means if Access, or VB.net, or even FoxPro via odbc modifies a row, the table trigger code will fire and run and save the soundex value in a column for you. And this feature also works if you use the new web publishing feature in access 2010. So, while the above article is written from the point of view of using Access Web services (available in office 365 and SharePoint), the above soundex table trigger will also work in a stand a alone Access and JET (ACE) only application.

Verifying sqlite FTS (Full Text Search) syntax, and how to do a single term NOT search

Is there a way to determine if a MATCH query sent to an fts3 table in sqlite is valid? Currently, I don't find out if the expression is invalid until I try to run it, which makes it a little tricky. I'd like to report to the user that the syntax is invalid before even trying to run it.
I'm using sqlite with the C api.
Additionally, doing a search with the expression "NOT " will fail with a "SQLlite logic/database error". Googling seems to indicate that such a query is invalid. Is there a correct syntax to do the operation? I'm essentially trying to find entries that do NOT contain that term. Or do I have to drop back down to using LIKE and do a sequential scan and not use FTS?
Looks like the simplest way right now is to create a separate FTS table with no rows, and execute the query against it. It will be immediate since there's no data in the table, and will report and error if the query syntax is incorrect.

Resources