Declaring variables for Oracle SQL in dbVisualizer - sql

Using an Oracle database (currently 18g) through dbVisualizer, I have SQL that has parameters peppered throughout. Some of the parameters are in multiple places. The query I'm working with right now has 13 distinct parameter names with 56 total references in the code. I have some standard values I use for testing. I don't want to use the interface dbVisualizer presents for entering them manually. I want to use a text editor to enter my test values and put them all at the beginning of my code so I don't risk fat-fingering my SQL logic and so I can delete or comment out that section when I'm done testing.
I've done this for decades in SQL Server...
declare #varname varchar(50)
set #varname = 'asdf'
select #varname
...but I don't see a way to do this in Oracle. I have read many posts regarding how to do this using PL/SQL or SQL*Plus (like https://dba.stackexchange.com/questions/3652/how-do-i-declare-and-use-variables-in-oracle) that don't work for my environment. I have also seen posts with accepted answers that just don't work (like Declare a variable in Oracle SQL to use in a query).
How can I declare variables in Oracle SQL through dbVisualizer as easily as I can in SQL Server using SSMS?

I have needed this functionality for about 3 years now. Since I finally found enough information to figure it out, and since I've never found this info on StackExchange, I'm asking and answering my own question in the hopes that others don't suffer needlessly as long as I have.
I found a post (https://support.dbvis.com/support/discussions/topics/1000076719) describing how to do this, but it looks like some of the post got lost in a forum upgrade. Fiddling around a bit I found that this will work:
#echo ${ MY_VARCHAR1 ||My Value|| String }$
#echo ${ MY_VARCHAR2 || My Other Value || String }$
#echo ${ MY_INTEGER || 13467 || Integer }$
#echo ${ MY_DATE || 1983-08-25 || Date }$
;
SELECT ${MY_VARCHAR1}$ "VarcharVal"
, REPLACE(${MY_VARCHAR2}$, ' ', '[SPACE]') "VarcharValWithLeadingAndTrailingSpaces"
, ${MY_INTEGER}$ "IntegerVal"
, ${MY_DATE}$ "DateVal"
FROM DUAL
;
Notice the results for MY_VARCHAR2. While integers and dates are handled cleanly, you want to be sure to not have spaces around the value for string data.
Update: Adjusted code per dbVisualizer docs. Same result, though.

Related

Pulling a SQL Server date to be used in Oracle query within SSIS environment is ignored in the Oracle query

I am having trouble in my Oracle query that uses a variable stored in SSIS which has a date that is pulled from sql server.
I am using an execute sql task that simply gets a max date from a sql server table and stores it in a variable. E.g.
SELECT MAX(t.Date) FROM table t;
I then want to use that variable in my Oracle query which is an ADO.NET source connection. I noticed you can't parameterize in those connections and found the work around where you use the sql expression with your user variable in it. So now my Oracle source query looks something like this:
"SELECT DISTINCT t.* FROM table t WHERE TO_CHAR(t.LastUpdateDate, 'YYYY-MM-DD') > " + "'#[User::LastUpdateDate]'"
The query syntax itself is fine, but when I run it, it is pulling all rows and seems to be completely ignoring the where clause of the date.
I've tried removing the TO_CHAR from LastUpdateDate.
I've tried adding a TO_CHAR to my user variable #[User::LastUpdateDate].
I've tried using the CONVERSION() function from sql server on #[User::LastUpdateDate].
Nothing seems to work and the query just runs and pulls in all data as if I don't have the WHERE clause on the query.
Does anyone know how to rectify this issue or point out what I might be doing wrong?
Thank you for any and all help!
**EDIT:
My date being pulled from SQL Server is in this format: 2022-09-01 20:17:58.0000000
This is not an answer, just troubleshooting advice
You do not say what data type #[User::LastUpdateDate] is, I'll assume it's a datetime
Ideally all datetime data should be kept in datetime data types, then format becomes completely irrelevant. However since it's difficult to parameterise Oracle queries in SSIS, you have to concoct a string to be submitted. Now date format does become important.
On to something a little different, it is a very good habit performancewise, to not put functions around columns that you are searching on. This is called sargability - look it up.
Given these things, I suggest that you concoct your required SQL query bit by bit and troubleshoot.
First, format your date parameter as an Oracle date literal. Remember this is normally a bad and unecessary thing. We are only doing it because we have to concoct a SQL string.
So create another SSIS variable called strLastUpdateDate and put this hideous expression in it:
RIGHT("0" + (DT_STR,2,1252)DATEPART( "dd" , #[User::LastUpdateDate] ), 2) + '-' +
(DT_STR,3,1252)DATEPART( "mmm" , #[User::LastUpdateDate] ) + '-' +
(DT_STR,4,1252)DATEPART("yyyy" , #[User::LastUpdateDate] )
Yes this is ludicrously long code but it will turn your date variable into a Oracle string literal. You could simplify this by putting it into your original max query but lets not go there. Use whatever debugging technique you have to confirm that it works as expected.
Now you should be able to use this:
"SELECT t.*, '"+#[User::LastUpdateDate]+"' As MyStrDate FROM table t WHERE
t.LastUpdateDate > '" #[User::strLastUpdateDate] + "'"
You can try running that and see if it makes any difference. Make sure you use this https://dba.stackexchange.com/questions/8828/how-do-you-show-sql-executing-on-an-oracle-database to monitor what is actually being submitted to Oracle.
This is all from memory and googling - I haven't done SSIS for many years now
I suspect after all this you may still have the same problem because I recall from many years having the same mysterious issue.

How to use variables in SQL queries on DataGrip (Exasol dialect)?

Database: EXASOL
IDE: IntelliJ DataGrip
I am trying to declare variables in SQL and call them throughout the query.
This is the equivalent in Microsoft SQL Server:
DECLARE #var AS INT = 3
SELECT #var AS var
-- Use case example:
SELECT * FROM table1 WHERE column_value = #var
Is this possible in DataGrip and Exasol? I searched the documentation (General Script Language, Database Interaction) of Exasol where they describe the following:
a = 3
SELECT :a
However, this opens a console where I am asked to type the value of a. I don't want to type the values of variables every time I execute the code. I want to set a variable and use it on different parts of the query, just like any other high-level programming language.
I found two similar questions on JetBrains' forum (1, 2) but they are unanswered. Another one found on StackOverflow (url) just stated that the dialect is not supported on DataGrips.
Does anyone know how to solve this? Is it simply not supported? It would really increase productivity for me and my team.
Thank you in advance!
After spending some time, I found out that this is not possible. Instead Exasol allows LUA scripts that can run such calculations. Below you will find an example:
CREATE LUA SCRIPT "TEST" (p_country) RETURNS TABLE AS
local param_c = p_country
exit(
query(
[[
SELECT * FROM SCHEMA_NAME.TABLE_NAME
WHERE SK_COUNTRY = :local_c;
]]
,{local_c=param_c}
)
);
/
EXECUTE SCRIPT SCHEMA_NAME.TEST('DE');
In this example the keyword RETURNS TABLE outputs the table results from this query. The keyword exit() is similar to a print() method. And lastly, I don't know why but the function parameter needs to be assigned to a local variable, which then needs to be assigned to another variable in the query. This makes no sense to me, but I could not get it to work otherwise.
In my example I have the script parameter p_country which is assigned to the local parameter param_c which is then assigned to the query parameter local_c.
You can find the documentation under:
https://docs.exasol.com/database_concepts/scripting/general_script_language.htm?Highlight=for%20loop
https://docs.exasol.com/database_concepts/scripting/db_interaction.htm

Will it avoid SQL Injections by not allowing sql keywords in params?

I know that sanitizing parameters (removing quotes for example) is not a perfect solution against SQL injection when you can't use setParameters().
But is it safe to sanitize parameters by checking if they (parameters) don't contain strings with an empty space after it as you see below???
'DELETE ', 'ALTER ', 'DROP ', 'SELECT ', 'TABLE '
For example, email parameter was passed to server but it contains DROP keyword:
String param = "john#mail'DROP myTable"
SELECT * from Users where email = 'john#mail'DROP mytable'
So, my table is dropped;
Notice the space I left after each keyword. This way if a data in db contain the listed keywords but without space, then it will be allowed to use, otherwise it should be a hacker trying to harm my data (ALTER TABLE mydb).
Please feel free to add as example any SQL engine: SQL, Oracle, HANA, MySQL
Thanks
No this is not sufficient.
Please follow the industry standards for preventing SQL Injection that are laid out by OWASP.
One obvious example of SQL injection for the query you posted would be if someone provided the following input for user:
john#mail' OR '1' = '1
Which would produce the query:
SELECT * from Users where email = 'john#mail' OR '1' = '1'
They could also inject a UNION to start selecting data from other tables. There are probably even more devastating examples.
The bottom line is never try to "roll your own" SQL Injection protection. Much smarter people than you and I have tried to solve this problem and the currently accepted standard of using parameterized queries is simply the best solution we currently have available.

Can you explain this SQL injection?

The website i worked was recently attempted to be hacked by the following SQL injection script
boys' and 3=8 union
select 1,
concat(0x232425,ifnull(`table_name`,0x30),char(9),ifnull(`table_rows`,0x30), char(9),0x252423),
3,4,5,6,7,8,9
from `information_schema`.`tables`
where table_schema=0x62646B3032 limit 44,1 -- And '8'='8
This injection returned the mysql table name. This was reported by the error reporting system on that website and we managed to fix that part however I am not able to understand what does the above injection mean?
Anyone can explain this?
Penuel
They're using a select from the Information Schema views in mysql server :
http://dev.mysql.com/doc/refman/5.0/en/information-schema.html
They use some clever hacks to rout out simple sql injection prevention techniques.
According to this the MySQL concat()
Returns the string that results from
concatenating the arguments. May have
one or more arguments. If all
arguments are nonbinary strings, the
result is a nonbinary string. If the
arguments include any binary strings,
the result is a binary string. A
numeric argument is converted to its
equivalent binary string form
So 0x232425 is converted to #$% which is simply added to the begining and end of the table_name field. Maybe just to make it easier for them to pull out the Table names later using Regex.
Later on the char(9) is equivalent to a tab as you can see here and is just there to format the output nicer.
The 3,4,5,6,7,8,9 is just there so that the columns match the boys table that they are performing the Union on.
This injection returned the mysql table name.
Do you mean that your website displayed the table name when you gave it this input, or that the query returns that when run from the mysql client? If it showed on your website, then the attacker has the ability to inject much more harmful queries. Check your data.

How do I deal with quotes ' in SQL [duplicate]

This question already has answers here:
How to anticipate and escape single quote ' in oracle
(2 answers)
Closed 7 years ago.
I have a database with names in it such as John Doe etc. Unfortunately some of these names contain quotes like Keiran O'Keefe. Now when I try and search for such names as follows:
SELECT * FROM PEOPLE WHERE SURNAME='O'Keefe'
I (understandably) get an error.
How do I prevent this error from occurring. I am using Oracle and PLSQL.
The escape character is ', so you would need to replace the quote with two quotes.
For example,
SELECT * FROM PEOPLE WHERE SURNAME='O'Keefe'
becomes
SELECT * FROM PEOPLE WHERE SURNAME='O''Keefe'
That said, it's probably incorrect to do this yourself. Your language may have a function to escape strings for use in SQL, but an even better option is to use parameters. Usually this works as follows.
Your SQL command would be :
SELECT * FROM PEOPLE WHERE SURNAME=?
Then, when you execute it, you pass in "O'Keefe" as a parameter.
Because the SQL is parsed before the parameter value is set, there's no way for the parameter value to alter the structure of the SQL (and it's even a little faster if you want to run the same statement several times with different parameters).
I should also point out that, while your example just causes an error, you open youself up to a lot of other problems by not escaping strings appropriately. See http://en.wikipedia.org/wiki/SQL_injection for a good starting point or the following classic xkcd comic.
Oracle 10 solution is
SELECT * FROM PEOPLE WHERE SURNAME=q'{O'Keefe}'
Parameterized queries are your friend, as suggested by Matt.
Command = SELECT * FROM PEOPLE WHERE SURNAME=?
They will protect you from headaches involved with
Strings with quotes
Querying using dates
SQL Injection
Use of parameterized SQL has other benefits, it reduces CPU overhead (as well as other resources) in Oracle by reducing the amount of work Oracle requires in order to parse the statement. If you do not use parameters (we call them bind variables in Oracle) then "select * from foo where bar='cat'" and "select * from foo where bar='dog'" are treated as separate statements, where as "select * from foo where bar=:b1" is the same statement, meaning things like syntax, validity of objects that are referenced etc...do not need to be checked again. There are occasional problems that arise when using bind variables which usually manifests itself in not getting the most efficient SQL execution plan but there are workarounds for this and these problems really depend on the predicates you are using, indexing and data skew.
Input filtering is usually done on the language level rather than database layers.
php and .NET both have their respective libraries for escaping sql statements. Check your language, see waht's available.
If your data are trustable, then you can just do a string replace to add another ' infront of the ' to escape it. Usually that is enough if there isn't any risks that the input is malicious.
I suppose a good question is what language are you using?
In PHP you would do: SELECT * FROM PEOPLE WHERE SURNAME='mysql_escape_string(O'Keefe)'
But since you didn't specify the language I will suggest that you look into a escape string function mysql or otherwise in your language.
To deal quotes if you're using Zend Framework here is the code
$db = Zend_Db_Table_Abstract::getDefaultAdapter();
$db->quoteInto('your_query_here = ?','your_value_here');
for example ;
//SELECT * FROM PEOPLE WHERE SURNAME='O'Keefe' will become
SELECT * FROM PEOPLE WHERE SURNAME='\'O\'Keefe\''
Found in under 30s on Google...
Oracle SQL FAQ