3GLs provide mechanisms to prepare statements before executing them. E.g.
SELECT name
FROM people
WHERE age=:AGE
The same query can then be executed for different ages. But can such a statement also be prepared in a "plain" Oracle SQL client? Can the same be done in e.g. SQL Plus or dbForge Studio for Oracle as in Java or C# or any other programming language that supports prepared statements?
In dbForge Studio for Oracle, named parameters can be used, preceded by a colon :
SELECT *
FROM people
WHERE name=:name
The parameters can then be filled in with the "Edit parameters dialog box", available from the SQL toolbar.
I know you didn't ask about PostgreSQL but about Oracle. However, of note, PostgreSQL has this feature right in its SQL language.
The SQL standard includes a PREPARE statement, but it is only for use in embedded SQL. The PostgreSQL version of the PREPARE statement works like this:
PREPARE nameByAge(number) AS
SELECT name
FROM People
WHERE age=$1;
and you use it like this:
EXECUTE nameByAge(18);
EXECUTE nameByAge(50);
So unfortunately for Oracle SQLPlus the answer seems to be no, not bind variables. But SQLPlus has substitution variables, similar to shell scripts. You use them as &1, &2, &3, ... and they get their parameters from the way you call the SQLPlus script.
sqlplus user/password #script.sql 18
sqlplus user/password #script.sql 50
with the script.sql being
SELECT name
FROM People
WHERE age=&1;
this would work, even though it is not bind. But then, do you really care about the slight savings in repeat parse time? In fact Oracle hashes SQL statements and already replaces constants with bind variables to be able to better reuse query plans. So the savings you would get with PREPARE and BIND are really minuscule.
Related
I have the following SQL script (all names replaced with metasyntactic variables):
DELETE FROM FOO
WHERE UPPER(BAR)=? AND UPPER(BAZ)=? AND UPPER(QUX)=? AND UPPER(QUUX)=? AND UPPER(CORGE)=?;
When I run it in SQL Developer, I get the following error, as expected: SQL Error: Missing IN or OUT parameter at index:: 1
Is there a way in SQL Developer to pass test parameters to these values (in this case, BAR, BAZ, QUX, QUUX, and CORGE) or do I have to manually replace the question marks? Thanks!
UPDATE: I've been looking on the internet to try to find the answer with no luck; none of the articles I found deal with the FOO=? syntax. I know that that is the proper syntax to access (and in this case, delete from) the database from a Java program, but I would like to test the SQL script before embedding it in the program.
A query that way is called a prepared statement. It is used as a way to send SQL statements from a program to the database.
First you have to prepare the prepared statement object and later you supply the parameters and finally execute the statement. When setting the parameters, you refer to each question mark in the order they apear in the statement. So in you case, BAR would be parameter 1 and CORGE will be parameter 5.
http://docs.oracle.com/javase/tutorial/jdbc/basics/prepared.html
For testing a query like this is quite useless in my experience. You could change the paramters to variables or even substitution variables if that is more convenient while testing.
http://docs.oracle.com/cd/B19306_01/server.102/b14357/ch5.htm#i1211130
I have an oracle query which has a select statement
select table.columnname = ${sometext_sometext_sometext}
I would like to know what is the purpose of ${}.
Also this throws an error in Oracle SQL developer. Kindly advise what is the work around.
This isn't Oracle syntax, this is a common syntax for interpolating variables into a string found in Perl, Groovy, and a bunch of other languages.
You don't say what the context is here, but what is probably going on is something modifies the file, probably with environment-related properties, before the SQL gets run, the ${} is there to identify to the modifying script what value to substitute here. This is a common thing to do when you have environment-specific properties that need to be injected into a SQL script.
Can you give some background as to where you got this SQL statement? It appears that you are working with a query that requires pre-processing via Java, PHP, a Bash shell script, etc. Standard Oracle SQL or PL/SQL does not know what to do with the "${}" syntax.
I have used this syntax in a standard SQL template that I then process in Java or a bash shell script to generate the final SQL statement.
I've decided to use postgreSQL as database for a game project(C++).
At the moment I'm using Oracle and it's Pro*C precompiler at work and heard that postgreSQL also has something similar called ECPG.
It's also possible to access data from the the postgres database directly by using the SQL in a string.
So the difference between "normal" and using ECPG, is that you can write your SQL statements like code?, or are there any other differences I should be aware of?.
(PS: i know I'm using it at work, but I haven't noticed any other differences)
Looking forward to hearing from you guys.
Yes, ECPG is covered in the documentation.
So the difference between "normal" and using ECPG, is that you can
write your SQL statements like code?
Well, SQL statements are code. A SQL statement just looks like a SQL statement. This is what a CREATE TABLE statement might look like in ECPG.
EXEC SQL CREATE TABLE foo (number integer, ascii char(16));
ECPG allows variable substitution. (Maybe that's what you meant by "write your SQL statements like code".)
EXEC SQL INSERT INTO sometable VALUES (:v1, 'foo', :v2);
All this stuff is in the documentation.
I am doing some research in web security, and the reviser of my article said:
"It should be clear that to avoid SQL Injection, the application should use prepared statements, stored procedures and escape input"
My question is: Is one of these methods isn't enough? Ok, prepared statements or stored procedures are better than a simple escape, but if I use PDO, why i should escape the input or have a stored procedure? Does this make sense?
I would change the reviser's wording to:
It should be clear that to avoid SQL Injection, the application should use prepared statements, escape input, or filter application data before interpolating into an SQL string.
It's not necessary to escape a value if you're going to pass as a parameter. In fact, you should not, because you'll insert literal backslashes into your data.
You need to interpolate strings into your SQL statement when you can't use a query parameter. Examples include:
Table names and column names, which have their own syntax for delimited identifiers. These must be part of the SQL query at prepare time, so the RDBMS can parse and validate them.
SQL keywords, which should be sanitized but cannot be escaped because they are not delimited.
Other syntax or expressions.
Some cases where literal values must be provided at prepare time, e.g. MySQL's fulltext functions do not support parameters for the search pattern.
Stored procedures are not a defense against SQL injection. You can prepare and execute unsafe dynamic SQL statements inside a stored procedure. See http://thedailywtf.com/Articles/For-the-Ease-of-Maintenance.aspx for a great story about that.
I cover all these cases in my presentation SQL Injection Myths and Fallacies. That may be a helpful resource for you.
I also cover SQL injection defense in a chapter of my book, SQL Antipatterns Volume 1: Avoiding the Pitfalls of Database Programming.
If i use PDO, why i should [es]scape the input or have a stored procedure?
As long as you always use PDO, I don't see a reason to bother with input escaping or SPs.
When in doubt, ask yourself: will this piece of plain input data be escaped by some API down the line? Most of the time they will, except when you manually build SQL sentences from input data.
You should not escape if you use PDO. You should not escape if you use JDBC Prepared Statements with parameters. Similarly, most other APIs also take care of this. Stored procedures are not even concerned with escaped data and using them will not magically avoid SQL injection security issues if the input data is not escaped in the SQL that runs the procedure.
Always SQL-Escape data that you put in SQL sentences. Never SQL-Escape data outside SQL sentences.
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