Result set in postgresql stored procedure llike java - java

hi is there any way to do the following java code in postgresql stored procedure
String sqlQuery = "SELECT uid, name, duration from EVENTS";
ResultSet rs = stmt.executeQuery(sqlQuery);
while (rs.next()) {
String name = rs.getString(2);
}
i need the same in the postgresql stored procedure?

Per the PL/PgSQL documentation you use a LOOP over a query for that.
DO
$$
DECLARE
myresult record;
BEGIN
FOR myresult IN SELECT uid, name, duration FROM events
LOOP
RAISE NOTICE 'Name is %',myresult.name;
END LOOP;
END;
$$ LANGUAGE plpgsql;
However, use of loops is very often a sign you're just not using SQL properly. It's highly likely that proper use of WITH queries (common table expressions) and a bit of thought will get you a pure SQL solution that'll generally perform a LOT better.
In future, please give your PostgreSQL version and explain a little about what you're actually trying to accomplish. The code you show is completely useless, it does nothing. So it's obviously not what you really want to do, but you've told us nothing about that. Quite often the solution you think you need (looping, say) isn't the solution you really need.

Related

Using Variable as a column in sql query

Here is my code. I am trying to use a variable instead of a column name in here
But I get below exception. How can I resolve this error?
You can't bind table/column names in a prepared statement, nor would you normally want to allow this. Here is a working version of your code:
String query = "UPDATE report SET itemno = ?";
pst = (PreparedStatement) con.prepareStatement(query);
pst.setInt(1, dqty);
pst.executeUpdate();
Notes:
You almost certainly want to add a WHERE clause to your update, without which it would affect every record in the table. With prepared statements, you don't need to worry about escaping your literal data. Just let Java handle this for you.
If you really need the ability to update other table/column combinations, then just create other statements for that. One size fits all works at 7-Eleven, but not JDBC, since you might SQL injected.

Calling stored procedure

Good Night in my timezone.
I am using Sybase ase 15, and I have a stored procedure with two input parameters both VARCHAR, basically inside the stored procedure I use dynamic SQL, something like this:
#cmd = 'select * from TABLE where COL IN'+#PARAM1+'AND COL2=#PARAM2
EXEC(#cmd)
I call this procedure using JDBC like this way:
CallableStatement stmt = conn.prepareCall("{call MyStoredProcedure(?,?)}");
stmt.setString(1, "'''0'',''1'''");
stmt.setString(2, '''fr''');
stmt.executeQuery();
It throws me an error informing that the call is malformed.
But if I run the call directly in the IDE like this :
EXEC MyStoredProcedure'''0'',''1'',''2'',''3'',''4'',''5'',''6'',''7''','''fr'''
It runs without any problem, so i guess that there is some problem with the character escaping i guess.
Anyone had experience this problem ?
With the best regards
Thanks in advance
You don't specify IN and OUT parameters:
http://docs.oracle.com/javase/tutorial/jdbc/basics/storedprocedures.html
See if following the tutorial helps.
I would also comment that you only have two parameters, but your query passes in strings that appear to be more. It's ugly, misleading, and appears to break first normal form.

What does "=?" represent when used in an SQL query

I'm fairly new to SQL and I'm currently reworking a java program that another
programmer has developed. When I print one of his query select statements the script contains sql syntax:
SELECT * from database WHERE id = ?
I just want know what =? is supposed to do? I've been googling around and I can't find any relevant answer.
It's not a SQL notation, but a JDBC (Java Database Connectivity) notation. The ? gets replaced with a parameter that is specified separately. Using this approach, instead of trying to substitute the parameter yourself into the string, helps prevent the risk of SQL injection.
The ? is a place holder, a parameter, so that you can pass it in dynamically and return different results for different parameters.
Somewhere in the code you should see that he adds the parameter to the Statement object and execute it.
Most likely you are using a tool that will replace the "?" with an actual value. I've seen this in other tools before such as SQL DTS (Data Transformation Services)... but that's showing how old I am :)
The ? is not part of the SQL language.
The ? is a place holder used in SQL queries when used with JDBC Prepared statement. Using a prepared statement has advantages over the normal statement specially when you use it repeatedly (say in a loop).
Here is an example :
PreparedStatement ps =
connection.prepareStatement("select name from users where user_name = ?");
ps.setString(1, "user1");
the "?" gets replace by "user1" when the query is run and the first name of the user with user name "user1" is returned.

How do I declare a String array in a Java SQL declareParameter call?

Simplified for illustrative purposes:
String[] filter = {"foo", "bar"};
String sql = "SELECT * FROM table WHERE column IN ?";
declareParameter(new SqlParameter(Types.ARRAY));
This doesn't work when I execute it (I get a java.sql.SQLException: [Microsoft][SQLServer 2000 Driver for JDBC]Invalid parameter binding(s). exception.
JDBC doesn't support this kind of query officially and SQL Server doesn't either as far as I know. This topic has been discussed on SO many times and several workarounds have been proposed:
What is the best approach using JDBC for parameterizing an IN clause?
PreparedStatement IN clause alternatives?
pass variable from java to SQL IN clause
Trouble with PreparedStatement that uses union of selects query and IN CLAUSE
You can probably find many more as it is indeed a very relevant yet still open topic.
I am not sure about MS SQL Server. But such a code wouldn't work on oracle DB. In oracle, we cannot pass a java array to an IN clause. The way to work around that limitation is to construct a PL/SQL function that converts a list of strings into a table, something like stringToTable. Then pass a concatenated string as a parameter.
Again, this answer is applicable for Oracle DB; It might not work on MS SQL server.

Doing Java String replacement efficiently

We have the following code :
String templateQuery = "select * from my_table where col1=$1 or col2 like '%$2.$1'";
String tmp = templateQuery;
for(int i=1;i<=maxCols;i++) {
tmp = tmp.replaceAll("\\$"+i, data[i-1]);
}
This code works fine as maxCols never exceeds 10. But my colleague disagree with me stating that this code consumes too much memory. Can you help us ?
EDIT:
I have change the initial templateQuery with a much realistic one. Secondly, templateQuery can potentially be a big string.
EDIT 2:
Thanks for those who have pointed out the SQLInjection problem.
Don't do this.
Not for performance reasons (which will be miniscule compared with the cost of the database query), but to avoid SQL injection attacks. What happens if data[0] is actually the string
' OR 'x' = 'x
?
Then you'll end up with a SQL statement of:
SELECT * FROM my_table WHERE col1='' OR 'x' = 'x'
which I think we can agree isn't what you wanted.
Use a parameterized SQL statement instead (PreparedStatement) and get the database driver to send the parameter values separately.
EDIT: In other comments, the OP has specified that the template string can be quite long, and some parameters may actually involve multiple initial values combined together. I still say that the cost of replacement is likely to be insignificant in the grand scheme of things, and I still say that PreparedStatement is the way to go. You should perform whatever combining operations you need to on the input before setting them as the values for the PreparedStatement - so the template may need the SQL with SQL placeholders, and then "subtemplates" to work out how to get from your input to the parameters for the PreparedStatement. Whatever you do, putting the values directly into the SQL is the wrong approach.
Why aren't you just using a PreparedStatement with replacement parameters?
String templateQuery = "SELECT * FROM my_table WHERE col1 = ?";
PreparedStatement ps = con.prepareStatement(templateQuery);
for (int i = 0; i < data.length; i++) {
ps.setString(i + 1, data[i]);
}
ResultSet rs = ps.executeQuery();
You're otherwise vulnerable to SQL injection if you use string replacement like you have.
He is correct, because you create maxCols tmp Strings.
I realized that it is for Sql commands, if is it, why you do not use PreparedStatement (http://download.oracle.com/javase/1.4.2/docs/api/java/sql/PreparedStatement.html) for this task?
Also, for formatting strings, rather than use substitute, use Formatter, it is much more elegant: http://download.oracle.com/javase/1.5.0/docs/api/java/util/Formatter.html
Whether this consumes too much memory is open to debate (what's "too much"?)
Nonetheless, for this kind of stuff you should use PreparedStatement. It allows you to do pretty much exactly what you're trying to achieve, but in a much cleaner fashion.
Your colleague is right in that every string replacement creates a new copy of the string. (However, the cost of these is probably negligible with less than 10 parameters.) Moreover, for every execution of this query the SQL engine needs to parse it afresh, which consumes far more additional resources each time.
The potential bigger problem though is that the code is suscept to SQL injection. If the input data is coming from an external source, a hacker can pass in a parameter such as "col1; drop table my_table;", effectively deleting your whole table.
All of these can be solved by using a PreparedStatement instead.

Categories