I am trying to run this code but there is no output. But when I run the SQL query from my terminal, it works. Please help.
Statement stmt = conn.createStatement();
ResultSet rset1=stmt.executeQuery("SELECT ShowTime FROM Movie M, screens s WHERE M.MovieID = s.MovieID AND M.MovieID= 01");
while(rset1.next()){
//String tite=(rset1.getTimestamp("title"));
System.out.println(rset1.getString("Showtime"));
//text_39.append((rset1.getString("Showtime"))+"\n");
}
The problem is ResultSet.getString(String) is not case insensitive. Changing the value to System.out.println(rset1.getString("ShowTime")); should solve your problem
if M.MovieID is an numeric data type, the 01 will get truncated to just 1 which will not compare correctly with a string data type of '01' you may need to wrap your '01' in tics so it looks like WHERE M.MovieID = s.MovieID AND M.MovieID= '01'
My thought here is that the Driver and DB engine are doing some implicit casting which is preventing a syntax error but causing you to get no results when run though the driver.
To better answer the question I would need to know what data type MovieID is in Movie table and screens table.
Related
I have read the previous questions but none of them seem to match my problem although they might seem similar at first. :/_
So, I am working on a local database on Java(JDBC). When I press a button I should be getting the result of a "SELECT" query. So far so good, but for some reason which my beginner brain does not understand I keep getting only one row from the query. I have even run the same exact query on "DB Browser for SQLite" and it returns the correct result (1+ rows) .
So this is the method I am using to get the result of the query:
public ResultSet returnBill(int no) throws SQLException{
String sql = "SELECT * FROM billList WHERE no = " + no + " ;";
ResultSet thisSet = stmt.executeQuery(sql); // stmt is a 'Statement' type variable
return thisSet;
}
The method does not crash but it only returns the very first row of a query which should return more than 2 ( while (thisSet.next()) RUNS ONCE). I run other "SELECT" queries on the program which are supposed to return more than one rows and they all work fine so it's not a matter of not being able to start/close the connection etc.
Below is the method being used:
int number = table.getModel().getValueAt(rows, 0);
ResultSet thisSet = db.returnBill(number);
while (thisSet.next()){
String name = thisSet.getString("name");
int quantity = thisSet.getInt("quantity");
// do something with the returned data
}
So I get this magical number from a table (of course I made sure it's not 0, -1 etc.) and I run a query using that number. You could think of the structure of the table consisting of columns :
number | name | quantity |
where 'number' is nonzero.
I understand that probably using this method to run a query on a DB might not be safe or might post security threats but it's not the case right now. I have been working on this project for quite a long time already and I have been through many silly mistakes and I think this is yet one of them. Any help is APPRECIATED ! :D
So yes, it was a silly mistake as I expected.
So I had previously initiated a variable
Database db = new Database();
which opened the database for 2 queries (the SELECT query and an UPDATE query on another table as shown) which would then be closed at the end of the following code.
When I removed this UPDATE query however the loop executed the correct amount of times. So it seems like the SQLite JDBC is somehow prone to running a SELECT and UPDATE query on the same Statement (as far as my super mega* brain perceives it.)
So I created 2 connections at the very beginning and closed them at the end using one of them for the SELECT and the other one for the UPDATE query:
Database db = new Database(); // open database
Database db2 = new Database(); // open another creepy one :/
int number = table.getModel().getValueAt(rows, 0);
ResultSet thisSet = db.returnBill(number);
while (thisSet.next()){
String name = thisSet.getString("name");
int quantity = thisSet.getInt("quantity");
// do something with the returned data
// --------> STUPIDO <----------
//** Now executing an UPDATE query on db2 :
// ex.: UPDATE anotherTable SET amount = (current+ "+ quantity+") WHERE name= '" + name+ "' ;";
}
db.closeConn(); // close db ++
db2.closeConn(); // closes db 2
I don't know if this is the best approach but it solved my problem, so I'm leaving it so probably it could help. Any suggestions though would be welcomed :D
How to make query like this in Java and get the results:
SELECT filedata.num,st_area(ST_Difference(ST_TRANSFORM(filedata.the_geom,70066),filedata_temp.the_geom))
FROM filedata, filedata_temp
Where filedata.num=filedata_temp.num
Or, I think will be better if I create procedure in Postgres from this query.
CREATE OR REPLACE FUNCTION get_geom_difference()
RETURNS void AS
$$
BEGIN
SELECT filedata.num,st_area(ST_Difference(ST_TRANSFORM(filedata.the_geom,70066),filedata_temp.the_geom))
FROM filedata, filedata_temp
Where filedata.num=filedata_temp.num
end;
$$
LANGUAGE 'plpgsql'
and call it
Connection ce_proc= null;
ce_proc = DriverManager.getConnection("jdbc:postgresql://localhost:5432/postgis","postgres","123456");
java.sql.CallableStatement proc = ce_proc.prepareCall("{get_geom_difference()}");
proc.execute();
proc.close();
ce_proc.close();
But how to get results from this procedure in Java?
UPDATE
I tried this SP
DROP FUNCTION get_geom_difference();
CREATE OR REPLACE FUNCTION get_geom_difference()
RETURNS integer AS
$$
DECLARE
tt integer;
BEGIN
SELECT filedata.num INTO tt
FROM filedata
Where filedata.num=1;
RETURN tt;
END;
$$
LANGUAGE 'plpgsql'
and call
Class.forName("org.postgresql.Driver");
Connection connect= null;
connect = DriverManager.getConnection("jdbc:postgresql://localhost:5432/postgis","postgres","123456");
java.sql.CallableStatement proc = connect.prepareCall("{?=call get_geom_difference()}");
proc.registerOutParameter(1, java.sql.Types.INTEGER);
proc.executeQuery();
ResultSet results = (ResultSet) proc.getObject(1);
and got an error:
org.apache.jasper.JasperException: An exception occurred processing
JSP page /commit_changes.jsp at line 25in lineproc.executeQuery();
root cause javax.servlet.ServletException:
org.postgresql.util.PSQLException: No results were returned by the
query
But query
SELECT filedata.num
FROM filedata
Where filedata.num=1;
returns 1.
Where is mistake?
You can largely simplify the function. (Keeping simplistic function for the sake of the question.)
CREATE OR REPLACE FUNCTION get_geom_difference()
RETURNS integer AS
$BODY$
SELECT num
FROM filedata
WHERE num = 1
LIMIT 1; -- needed if there can be more than one rows with num = 1
$BODY$ LANGUAGE SQL;
Though, technically, what you have in the question would work, too - provided the data type matches. Does it? Is the column filedata.num of type integer? That's what I gather from the example. On your other question I was assumingnumeric for lack of information. At least one of them will fail.
If the return type of the function doesn't match the returned value you get an error from the PostgreSQL function. Properly configured, your PostgreSQL log would have detailed error messages in this case.
What do you see, when you create the above function in PostgreSQL and then call:
SELECT get_geom_difference(1);
from psql. (Preferably in the same session to rule out a mixup of databases, ports, servers or users.)
Calling a simple function taking one parameter and returning one scalar value seems pretty straight forward. Chapter 6.1 of the PostgreSQL JDBC manual has a full example which seems to agree perfectly with what you have in your question (My expertise is with Postgres rather than JDBC, though).
There are quite a few different CallableStatement constructors, but only two of them let you get results back.
A ResultSet is returned by CallableStatement.executeQuery(). There's a good complete example in the link above.
I don't know if getting a scalar result back from a CallableStatement is legal. I'd expect PgJDBC to translate it to a rowset of one row, though, so it should work.
Your query example is typical. So what you will need is
Java Database Connectivity (JDBC)
and everything needed to serv it, is in package java.sql
So at this point I recoemnd you to read some tutorial and if you have some particular problem write about it on SO.
You will need JDBC to do that. You should be able to find all JDBC related information here.
Take a look here for a more detailed tutorial on how to connect your Java application to your PostgreSQL.
works 100% java 7 and postgres pgadmin 2016, Use createNativeQuery In your transaction write this
and change myschema.mymethodThatReturnASelect
for the scheme and the name of your function.
#Override
public List<ViewFormulario> listarFormulario(Long idUsuario) {
List<ViewFormulario> list =null;
try {
Query q = em.createNativeQuery("SELECT * FROM myschema.mymethodThatReturnASelect(?);");
q.setParameter(1, idUsuario);
List<Object[]> listObject = (List<Object[]>) q.getResultList();
if (listObject != null && !listObject.isEmpty()) {
list = new ArrayList<>();
for (Object o[] : listObject) {
ViewFormulario c = new ViewFormulario();
c.setIdProyecto(o[0] != null ? Long.valueOf(o[0].toString()) : -1L);
...etc...etc.
I'm having a problem I haven't encountered before: there is a stored function in a database: CC_PROC, which takes two date entries and returns a table. In other words, to call it, you type:
SELECT * FROM (TABLE( CC_PROC( DATE '2012-01-01', DATE '2012-01-15')));
This seems to work perfectly in SQLPlus and NetBeans, and the above line has been apparently been in use for some time.
Anyway, when calling it from java using a prepared statement, I get: "CC_PROC": invalid identifier on the executeQuery call.
This is with:
PreparedStatement preparedStatement =
connection.prepareStatement("SELECT * FROM (TABLE ( CC_PROC( ? , ? )))");
preparedStatement.setDate(1,firstDate);
preparedStatement.setDate(2,secondDate);
resultSet = preparedStatement.executeQuery();
I feel like maybe this is obvious and my limited experience using JDBC directly instead of Hibernate is throwing me. I'd like to not have to re-code the contents of CC_PROC in java business logic. Any ideas?
Thanks!
Aha, found the answer:
The oracle user was SALESOWN, so the fix was:
PreparedStatement preparedStatement = connection.prepareStatement(
"SELECT * FROM (TABLE ( SALESOWN.CC_PROC( ? , ? )))");
Yikes. I don't want to admit the amount of time it took to figure that out.
Apparently SQLPlus and NetBeans do attempt to help out a little...
Thanks for the help guys!
I have been messing with Oracle DB queries that run from my JAVA app. I can successfully get them all to run in SQL Developer. But when I am trying to execute them from my JAVA app I usually get UpdatadbleResultSet Error/Exception on certain queries.
Also, sometimes I receive, ExhaustedResultset. As I mention at the bottom I will re work the question to break it down(When I get a chance). I keep editing and pretty soon it'll be a book.
Why is this? I cannot seem to pinpoint the problem.
Some queries run successfully such as:
SELECT table_name
FROM all_tables
SELECT column_name, data_length
FROM all_tab_columns
WHERE table_name = 'mytable'
But when I try and run something like
SELECT length(<myColumnName>)
FROM mytable
I get the updateableResultSetError
I am running my queries as methods called on button clicks (example below).
static void testQuery() {
String query = "SELECT blah from blah"
String length;
ResultSet rs = db.runQuery(query);
Length = rs.getString("length(myCol)")
System.out.println(length);
}
I have also tried while rs.next()
I can only think that for some reason I am unable to get into each table and I can only pull the "bigger" picture.
EDIT: Explained DB Connection
I am connecting using some other jarfiles that have been added to my project.
private static IDriver driver = null;
private static Database db = null;
I then pass in all my connection credentials in a separate method.
private void connectDB(){
driver = new OracleDriver();
db = new Database(driver)
driver.getPassword;
driver.getetc;
driver.getEtc;
}
EDIT:
When I getstacktrace all I am returning is.
Ljava.lang.StatckTraceElement;(assortment of random characters).
I may not be getting stack traces right so someone can fill me in. After all I am offering a bounty.
Also I will edit this question and break it down again when I have the time.
Your problem is that you're trying to update a query that can't be updated, hence the updateable result error. It seems that whoever is creating your database connection or executing your query is creating an updatable result set.
You can't use certain types of select in an updatable result set: you can't use aggregated functions (such as length, min, max), you can't use select * etc.)
For the full list see Result Set Limitations and Downgrade Rules
Try retrieving the value in your select statement via the columnIndex instead of the column name and see if that makes a difference.
Currently, its hard to tell what your db.runQuery() does since that code is not posted.
String query = "SELECT length(myCol) FROM myTable";
String length;
ResultSet rs = db.runQuery(query);
while (rs.next()) {
length = rs.getString(1);
System.out.println(length);
}
I've got an inkling what may be happening here (which would explain why some queries work, and some don't). Accoring to the jdbc ResultSet javadocs, when using the getString() method of the result set, the column label.
the label for the column specified with the SQL AS clause.
If the SQL AS clause was not specified, then the label is the name of the column
As "length(myCol)" is neither a label nor a column name, it may be that it fell over because of that (but without stacktrace it is difficult to say what your problem actually is).
Try
String query = "SELECT length(myCol) AS myCol_len FROM myTable"
ResultSet rs = db.runQuery(query);
String length = rs.getString("myCol_len");
Though are you sure, you didn't want:
int length = rs.getInt("myCol_len");
Alternatively (as written by Kal), you can use the column index to get the data from the result set, which oblivates the need for a SQL AS label:
String query = "SELECT length(myCol) FROM myTable"
ResultSet rs = db.runQuery(query);
String length = rs.getString(1);
I'm busy on a piece of code to get alle the column names of a table from an Oracle database. The code I came up with looks like this:
DriverManager.registerDriver (new oracle.jdbc.driver.OracleDriver());
Connection conn = DriverManager.getConnection(
"jdbc:oracle:thin:#<server>:1521:<sid>", <username>, <password>);
DatabaseMetaData meta = conn.getMetaData();
ResultSet columns = meta.getColumns(null, null, "EMPLOYEES", null);
int i = 1;
while (columns.next())
{
System.out.printf("%d: %s (%d)\n", i++, columns.getString("COLUMN_NAME"),
columns.getInt("ORDINAL_POSITION"));
}
When I ran this code to my surprise too many columns were returned. A closer look revealed that the ResultSet contained a duplicate set of all the columns, i.e. every column was returned twice. Here's the output I got:
1: ID (1)
2: NAME (2)
3: CITY (3)
4: ID (1)
5: NAME (2)
6: CITY (3)
When I look at the table using Oracle SQL Developer it shows that the table only has three columns (ID, NAME, CITY). I've tried this code against several different tables in my database and some work just fine, while others exhibit this weird behaviour.
Could there be a bug in the Oracle JDBC driver? Or am I doing something wrong here?
Update: Thanks to Kenster I now have an alternative way to retrieve the column names. You can get them from a ResultSet, like this:
DriverManager.registerDriver (new oracle.jdbc.driver.OracleDriver());
Connection conn = DriverManager.getConnection("jdbc:oracle:thin:#<server>:1521:<sid>", <username>, <password>);
Statement st = conn.createStatement();
ResultSet rset = st.executeQuery("SELECT * FROM \"EMPLOYEES\"");
ResultSetMetaData md = rset.getMetaData();
for (int i=1; i<=md.getColumnCount(); i++)
{
System.out.println(md.getColumnLabel(i));
}
This seems to work just fine and no duplicates are returned! And for those who wonder: according to this blog you should use getColumnLabel() instead of getColumnName().
In oracle, Connection.getMetaData() returns meta-data for the entire database, not just the schema you happen to be connected to. So when you supply null as the first two arguments to meta.getColumns(), you're not filtering the results for just your schema.
You need to supply the name of the Oracle schema to one of the first two parameters of meta.getColumns(), probably the second one, e.g.
meta.getColumns(null, "myuser", "EMPLOYEES", null);
It's a bit irritating having to do this, but that's the way the Oracle folks chose to implement their JDBC driver.
This doesn't directly answer your question, but another approach is to execute the query:
select * from tablename where 1 = 0
This will return a ResultSet, even though it doesn't select any rows. The result set metadata will match the table that you selected from. Depending on what you're doing, this can be more convenient. tablename can be anything that you can select on--you don't have to get the case correct or worry about what schema it's in.
In the update to your question I noticed that you missed one key part of Kenster's answer. He specified a 'where' clause of 'where 1 = 0', which you don't have. This is important because if you leave it off, then oracle will try and return the ENTIRE table. And if you don't pull all of the records over, oracle will hold unto them, waiting for you to page through them. Adding that where clause still gives you the metadata, but without any of the overhead.
Also, I personally use 'where rownum < 1', since oracle knows immediately that all rownums are past that, and I'm not sure if it's smart enough to not try and test each record for '1 = 0'.
In addition to skaffman's answer -
use the following query in Oracle:
select sys_context( 'userenv', 'current_schema' ) from dual;
to access your current schema name if you are restricted to do so in Java.
This is the behavior mandated by the JDBC API - passing nulls as first and second parameter to getColumns means that neither catalog name nor schema name are used to narrow the search.
Link to the documentation . It is true that some other JDBC drivers have different behavior by default (e.g MySQL's ConnectorJ by default restricts to the current catalog), but this is not standard, and documented as such