I am trying to drop all the functions and procedures in my DB through java.
My current code is like so:
Class.forName(driver);
Connection conn = getConnectionToDB();
String itemName;
ResultSet rs = getResultSetForItem(item);
String upperCaseItem = item.toUpperCase();
while (rs.next()) {
itemName = rs.getString(upperCaseItem + "_NAME");
// Procedure and function names come with a grouping ID, remove it
if (item.equals("procedure") || item.equals("function"))
itemName = itemName.substring(0, itemName.indexOf(";"));
stmt = conn.createStatement();
stmt.executeUpdate(query + " " + itemName);
}
Where item is once "function" and once "procedure". Also, the query variable is set correctly to be "DROP FUNCTION" or "DROP PROCEDURE" respective to the execution.
The method of getResuletSetForItem:
Class.forName(driver);
Connection conn = getConnectionToDB();
DatabaseMetaData md = conn.getMetaData();
switch (item.toLowerCase()){
case "function":
rs = md.getFunctions("LDMS", "dbo", "%");
break;
case "procedure":
rs = md.getProcedures("LDMS", "dbo", "%");
break;
}
return rs;
What happens is, I get the resultset as functions or procedures according to what I am asking for. BUT it returns also the records for the other kind (Meaning, if I asked for a ResultSet of functions, I also get the procedures as well).
This of course causes an exception when I try to, for example, execute "DROP FUNCTION X" where X is actually a stored procedure.
Although you don't explictly say so, it looks like you might be using the MS SQL Server driver for Java.
From the documentation it looks like the getFunctions and getProcedures methods both return a list of functions and procedures. You need to evaluate the FUNCTION_TYPE column to determine which is which.
The type of the function. It can be one of the following values:
SQL_PT_UNKNOWN (0)
SQL_PT_PROCEDURE (1)
SQL_PT_FUNCTION (2)
Related
I have a program that selects from a database given a table and column string.
public void selectAllFrom(String table, String column){
String sql = "SELECT ? FROM ?";
try (Connection conn = this.connect();
PreparedStatement pstmt = conn.prepareStatement(sql)){
pstmt.setString(1, column);
pstmt.setString(2, table);
ResultSet rs = pstmt.executeQuery();
while (rs.next()){
System.out.println(rs.getString(column));
}
} catch (SQLException e){
System.out.println(" select didn't work");
System.out.println(e.getMessage());
}
}
For some reason it is not working and it is going right to catch
Here is the connect() function as well:
private Connection connect(){
Connection conn = null;
// SQLite connection string
String url = "jdbc:sqlite:C:/sqlite/db/chinook.db";
try{
// creates connection to the database
conn = DriverManager.getConnection(url);
System.out.println("Connection to SQLite has been established");
} catch (SQLException e){
System.out.println(e.getMessage());
System.out.println("Connection didn't work");
}
return conn;
}
I know the problem is not with the database because I'm able to run other select queries without parameters. It is the parameters that are giving me the problem. Can anyone tell what the problem is?
A table or column name can't be used as a parameter to PreparedStatement. It must be hard coded.
String sql = "SELECT " + column + " FROM " + table;
You should reconsider the design so as to make these two constant and parameterize the column values.
? is a place holder to indicate a bind variable. When a SQL statement is executed, database first checks syntax, and validates the objects being referenced, columns and access permission for specified objects (i.e metadata about objects) and confirms that all are in place and valid. This stage is called parsing.
Post parsing, it substitutes bind variables to query and then proceeds for actual fetch of results.
Bind variables can be substituted in any place in query to replace an actual hard coded data/strings, but not the query constructs them selves. It means
You can not use bind variables for keywords of sql query (ex: SELECT, UPDATE etc.)
You can not use bind variables for objects or their attributes (i.e table names, column names, functions, procedures etc.)
You can use them only in place of a otherwise hard coded data.
ex: SELECT FIRST_NAME, LAST_NAME, 'N' IS_DELETED FROM USER_DATA WHERE COUNTRY ='CANADA' AND VERIFIED_USER='YES'
In above sample query, 'N','CANADA' and 'YES' are the only strings which can be replaced by a bind variable, not any other word.
Using bind variable is best practice of coding. It improves query performance (when used with large no. of queries in tuned database products like Oracle or MSSQL) and also protects your code against sql injection attacks.
Constructing query by concatenating strings (especially data part of query) is never recommended way. You can still construct a query by concatenation for other parts like table name or column name as long as those strings are not directly taken from input.
Below example is acceptable:
query = "Select transaction_id, transaction_date from ";
if (isHistorical(reportType)
{ query = query + "HISTORY_TRANSACTIONS" ;}
else
{query = query + "PRESENT_TRANSACTIONS" ; }
recommended practice is to use
String query_present = "SELECT transaction_id, transaction_date from PRESENT_TRANSACTIONS";
String query_historical = "SELECT transaction_id, transaction_date from HISTORY_TRANSACTIONS";
if (isHisotrical(reportType))
{
ps.executeQuery(query_historical);
}else{
ps.executeQuery(query_present);
}
I have been searching and trying different stuff for awhile, but have not found an answer. I'm trying to make a connection to sql using JDBC from eclipse. I am having trouble when I need to select a string in the database. If I use:
Select name from data where title = 'mr';
That works with terminal/command line but when I try to use eclipse where I use
statement sp = connection.createstatement();
resultset rs = sp.executequery("select name from data where title = '" + "mr" + "'");
It does not give me anything while the terminal input does. What did I do wrong in the eclipse? Thanks
Heres a part of the code. Sorry, its a bit messy, been trying different things.
private boolean loginChecker(String cid, String password) throws SQLException{
boolean check = false;
PreparedStatement pstatment = null;
Statement stmt = null;
//String query = "SELECT 'cat' FROM customer";
String query = "select '"+cid+"' from customer where password = '"+password+"'";
try {
System.out.println("in try......");
//stmt = con.createStatement();
//ResultSet rs = stmt.executeQuery(query);
PreparedStatement prepStmt = con.prepareStatement(query);
ResultSet rs = prepStmt.executeQuery();
//System.out.print(rs.getString("cid"));
while(rs.next()){
check = true;
System.out.print(rs.getString("cid"));
}
} catch (SQLException e ) {
e.printStackTrace();
} finally {
if (stmt != null) {
//stmt.close();
}
}
return check;
}
Second try on a simpler query:
public List<Object> showTable() {
List<Object> result = new ArrayList<Object>();
String name = "bob";
try
{
PreparedStatement preStatement = con.prepareStatement("select total from test where name = ?");
preStatement.setString(1, name);
ResultSet rs1 = preStatement.executeQuery();
while(rs1.next()){
System.out.println("there");
System.out.println(rs1.getInt("total"));
}
}
catch (SQLException ex)
{
System.out.print("Message: " + ex.getMessage());
}
return result;
}
Remove the quotes around the column name.
String query = "select "+cid+" from customer where password = '"+password+"'";
You've not mentioned which database you're working with but many databases like Oracle change the column case to upper case unless they're quoted. So, you only quote table columns if that's how you had created them. For example, if you had created a table like
CREATE TABLE some_table ( 'DoNotChangeToUpperCase' VARCHAR2 );
Then you would have to select the column with quotes as well
SELECT 'DoNotChangeToUpperCase' FROM some_table
But, if you didn't create the table using quotes you shouldn't be using them with your SELECTs either.
Make sure you are not closing the ResultSet before you are trying to use it. This can happen when you return a ResultSet and try to use it elsewhere. If you want to return the data like this, use CachedRowSet:
CachedRowSet crs = new CachedRowSetImpl();
crs.populate(ResultSet);
CachedRowSet is "special in that it can operate without being connected to its data source, that is, it is a disconnected RowSet object"
Edit: Saw you posted code so I thought I add some thoughts. If that is your ACTUAL code than the reason you are not getting anything is because the query is probably not returning anything.
String query = "select '"+cid+"' from customer where password = '"+password+"'";
This is wrong, for two reasons. 1) If you are using prepared statements you should replace all input with '?' so it should look like the following:
String query = "select name from customer where password = ?";
Then:
PreparedStatement prepStmt = con.prepareStatement(query);
prepStmt.setString(1, password);
ResultSet rs = prepStmt.executeQuery();
2)
System.out.print(rs.getString("cid"));
Here are are trying to get the column named "cid", when it should be the name stored in cid. You should actually never be letting the user decide what columns to get, this should be hardcoded in.
I get a parameter is called 'id' in my function and want to print the cell of the name of this id row.
for example:
this is my table:
id name email
1 alon alon#gmail.com
I send to my function: func(1), so I want it to print 'alon'.
this is what I tried:
static final String url = "jdbc:mysql://localhost:3306/database_alon";
Class.forName("com.mysql.jdbc.Driver");
Connection con = DriverManager.getConnection(url, "root", "Admin");
String query_txt = "SELECT * FROM authors WHERE id = " + id;
Statement ps2 = con.createStatement();
ResultSet my_rs = ps2.executeQuery(query_txt);
System.out.println(my_rs.getString("name"));
con.close;
Everything is fine, but just one problem. You need to move your ResultSet cursor to the first row before fetching any values: -
Use: -
ResultSet my_rs = ps2.executeQuery(query_txt);
while (my_rs.next()) {
System.out.println(my_rs.getString("name"));
}
As a side note, consider using PreparedStatement to avoid getting attacked by SQL Injection.
Here's how you use it: -
PreparedStatement ps2 = con.prepareStatement("SELECT * FROM authors WHERE id = ?");
ps2.setInt(1, id);
ResultSet my_rs = ps2.executeQuery();
while (my_rs.next()) {
System.out.println(my_rs.getString("name"));
}
You need to use ResultSet.next() to navigate into the returned data:
if (my_rs.next()) {
System.out.println(my_rs.getString("name"));
}
Call my_rs.next(), which will move the ResultSet cursor onto the first row (which you are extracting data out of).
If this is a real application, use PreparedStatements instead of generic Statements. This is an extremely important matter of security if you plan on using user input in SQL queries.
I am trying to use a SQL Select statement for a query in Java. I currently have the following:
ResultSet rs = stmt.executeQuery("SELECT *" +
" FROM " + table +
" WHERE " + selection +
" VALUES " + selectionArgs);
where "selection" is a string and "selectionArgs" is a string array.
String selection = "documentFK=?";
String[] selectionArgs = { ... };
Is it possible to use the VALUES command to replace the ? like in with the INSERT command? Either way, what would be the correct syntax?
Thanks for the help.
I believe what you're looking for is the IN statement. Your query should look like this:
SELECT *
FROM table
WHERE documentFK IN ('doc1', 'doc2', 'doc3')
AND userFK IN ('user1', 'user2', 'user3')
This is (obviously) going to make your code a bit more ugly. You'll have to ensure that the WHERE keyword is used for the first clause, but the AND keyword is used for every other clause. Also, each list will have to be comma-delimited.
no, that is not the way it's done. first you create the statement from the query, using the question marks as place holders for the real values you want to put there. then you bind these values to the statement.
//the query
String sql = "SELECT " + "*" +
" FROM " + table +
" WHERE documetFK = ?";
//create the statement
PreparedStatement stmt = connection.prepareStatement(sql);
//bind the value
stmt.setInt(1, 4); //1 is "the first question mark", 4 is some fk
//execute the query and get the result set back
ResultSet rs = stmt.executeQuery();
now, if you want this thing with selection string and some args, then you're going to have a loop in your java code. not sure what your array looks like (you're not giving me that much to go on), but if it's made up from strings, it would be something like this:
//the query
String sql = "SELECT " + "*" +
" FROM " + table +
" WHERE " + selection;
//create the statement
PreparedStatement stmt = connection.prepareStatement(sql);
//bind the values
for(int i = 0; i < selectionArgs.length; i++) {
stmt.setString(i, selectionArgs[i]); //i is "the nth question mark"
}
//execute the query and get the result set back
ResultSet rs = stmt.executeQuery();
Can you use a PreparedStatement?
First of all SELECT .. WHERE .. VALUES is incorrect SQL syntax. Lose the VALUES part.
Then you're looking for prepared statements.
In your example it's going to look something like this:
String sql = "SELECT * FROM myTable WHERE documentFK=?";
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setString(1, "myDocumentFK"); // parameters start from 1, not 0. also we're assuming the parameter type is String;
ResultSet rs = pstmt.executeQuery();
Or with multiple parameters:
String sql = "SELECT * FROM myTable WHERE documentFK=? AND indexTerm=?";
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setString(1, "myDocumentFK"); // parameters start from 1, not 0. also we're assuming the parameter type is String;
pstsm.setInt(2, 100); // assume indexTerm can be 100 and is an integer
ResultSet rs = pstmt.executeQuery();
However, all of this doesn't worth your while since you can simply do the same by concatenating the value into the statement. But be aware of the SQL injections, so don't forget to escape the parameters that you're passing into the database.
PS: I was typing this way too long. You already have the answers :-)
As a side note, you may want to take a look at this to prevent SQL injections:
https://www.owasp.org/index.php/Preventing_SQL_Injection_in_Java
Sormula can select using "IN" operator from a java.util.Collection of arbitrary size. You write no SQL. It builds the SQL SELECT query with correct number of "?" parameters. See example 4.
I am working with a Java prepared statement that gets data from an Oracle database. Due to some performance problems, the query uses a "virtual column" as an index.
The query looks like this:
String status = "processed";
String customerId = 123;
String query = "SELECT DISTINCT trans_id FROM trans WHERE status = " + status + " AND FN_GET_CUST_ID(trans.trans_id) = " + customerId;
Connection conn = getConnection();
PreparedStatement ps = null;
ResultSet rs = null;
try {
ps = conn.prepareStatement(query);
ps.execute();
...
} catch (...)
This does not work. Having the function as part of the where clause causes a SQLException. I am aware of CallableStatement, and know I could use that first and then concatenate the results. However, this table uses FN_GET_CUST_ID(trans_id) as part of it's index. Is there a way to use a prepared statement with a database function as a query parameter?
Never concatenate arguments for the SQL into the String. Always use placeholders (?) and setXxx(column, value);.
You'll get the same error if you'd run the SQL in a your favorite DB tool. The problem is that Oracle can't use the function for some reason. What error code do you get?
If Customer ID is numeric keep in int not in String. Then try doing the following:
String query = "SELECT DISTINCT trans_id FROM trans WHERE status = ? AND FN_GET_CUST_ID(trans.trans_id) = ?";
ps = conn.prepareStatement(query);
ps.setString(1, status);
ps.setInt(2, customerId);
ps.execute();
Besides other benefits of prepared statement you won't have to remember about string quotations (this causes your error most likely) and escaping of the special characters.
At the first glance, the query seems to be incorrect. You are missing an apostrophe before and after the usage of status variable (assuming that status is a varchar column).
String query = "SELECT DISTINCT trans_id FROM trans
WHERE status = '" + status + "' AND FN_GET_CUST_ID(trans.trans_id) = " + customerId;
EDIT: I am not from java background. However, as #Aron has said, it is better to use placeholders & then use some method to set values for parameters to avoid SQL Injection.