I want to get access to the source code of some stored procedures, which are stored in a Sybase ASE 15.7 database.
At the moment I copy the text manually in a textfile and read it via executed java-code from the disk.
Now it is my goal to improve this process: I will get the sourcecode directly from the database within my executed java-code.
Is that possible?
Sorry, I have no idea.
I have Rapid SQL to work on the database.
you could run an ISQL script that calls the stored procedure sp_helptext to get the code of the stored procedure. Hope this helps.
Vince's hint was to use the stored procedure sp_helptext. This stored procedure produces more than one resultset and caused me difficulties.
RobV's answer was to use the stored procedure sp_showtext. This seems the better solution, cause it returns only one resultset. But I tried it with jdbc and it ever throws in a sql exception ("must return a resultset").
After my fails I find another solution, which need against the other two answers only a execution of a select statement. This works for me! Here is the code:
StringBuffer sbSP = new StringBuffer();
String query = "select c.text "
+"from syscomments c, sysobjects o "
+"where o.id=c.id and o.name='"+spName+"' order by c.colid";
PreparedStatement stmt = connection.prepareStatement(query);
ResultSet rs = stmt.executeQuery();
while (rs.next()) {
//loop over every row of the stored procedure
sbSP.append(rs.getString("text") + "\n");
}
Best use sp_showtext; it gives better formatted results (no broken SQL lines) than sp_helptext
Related
I want to export huge data from oracle to csv file. so i used simple JDBC select statement to get data in memory but and then write it to file, But data is very large of i am getting Out of memory exception. So i thought of using CallableStatement to call Stored Procedure which will return CURSOR with ResultSet as below :-
String getDBTableCursorSql = "{call getDBTableCursor(?,?)}";
callableStatement = dbConnection.prepareCall(getDBTableCursorSql);
callableStatement.setString(1, "test");
callableStatement.registerOutParameter(2, OracleTypes.CURSOR);
// execute getDBTableCursorSqlstore procedure
callableStatement.executeUpdate();
// get cursor and cast it to ResultSet
rs = (ResultSet) callableStatement.getObject(2);
// loop it like normal
while (rs.next()) {
String userid = rs.getString("ID");
String userName = rs.getString("NAME");
..
..
}
Oracle Proc :-
CREATE OR REPLACE PROCEDURE getDBTableCursor(
p_username IN DBUSER.USERNAME%TYPE,
c_dbuser OUT SYS_REFCURSOR)
IS
BEGIN
OPEN c_dbuser FOR
SELECT * FROM CUSTOMER WHERE USERNAME LIKE p_username || '%';
END;
Question 1 :-
does above ResultSet will fetch all the data in single shot ? or it will go to database for each rs.next(),
Question 2:-
is there any other approach which can deal with large data export to file in java using chunks so it wont get Out of memory issue?
I can't use pagination in this condition because of requirement.
Regarding your first question: the Oracle jdbc driver by default fetches 10 rows at a time. This can be verified or set to other value via standard jdbc:
https://docs.oracle.com/cd/E11882_01/java.112/e16548/resltset.htm#JJDBC28621
I have a table named employee, which has his id, name, phone number. I am using MySQL as my database. I am using Java Swing for that. I am searching the employee table with name now using Java (I have used like clause in my Java page).
Now I need to implement that function in stored procedures. Is it possible? And how can we take that resultset in Java code, if it is possible??
Now I have written my stored procedure as follows
BEGIN
SELECT * FROM employee where empName like '%su%'
END
Sample code will be appreciated..
Thanks
First thing is you should write msql procedure that sends parameter for LIKE,
CREATE PROCEDURE simpleproc (param1 CHAR(20))
BEGIN
SELECT * FROM employee where empName like param1;
END
Then from java program you can use this code to use procedure,
CallableStatement cstmt = con.prepareCall("{call simpleproc(?)}");
cstmt.setString(1, "%su%");
ResultSet rs = cstmt.executeQuery();
When executing a stored procedure it may actually return multiple ResultSet objects and/or update counts if it does several statements.
You use CallableStatement to execute the proc and then getResultSet() or getUpdateCount() to get the right result. For multiple results sets/statements you call getMoreResults() to move through the results of the stored proc.
For a simple case like this you should just need to call getResultSet() once and process it.
Yes you can. A stored procedure can even return multiple resultsets.
DELIMITER $$ -- recognized by mysql client but not phpmyadmin
CREATE PROCEDURE prc_test()
BEGIN
SELECT *
FROM employee
WHERE empName LIKE '%su%';
END;
$$
DELIMITER ;
CALL prc_test(); -- to call
String link = "http://hosted.ap.org";
I want to find whether the given url is already existing in the SQL DB under the table name "urls". If the given url is not found in that table i need to insert it in to that table.
As I am a beginner in Java, I cannot really reach the exact code.
Please advise on this regard on how to search the url in the table.
I am done with the SQL Connection using the java code. Please advise me on the searching and inserting part alone as explained above.
PreparedStatement insert = connectin.preparedStateme("insert into urls(url) vlaues(?)");
PreparedStatement search = connectin.preparedStateme("select * from urls where url = ?");
search.setString(1, <your url value to search>);
ResultSet rs = search.executeQuery();
if (!rs.hasNext()) {
insert.setString(1, <your url value to insert>);
insert.executeUpdate();
}
//finally close your statements and connection
...
i assumed that you only have one field your table and field name is url. if you have more fields you need to add them in insert query.
You need to distinguish between two completely separate things: SQL (Structured Query Language) is the language which you use to communicate with the DB. JDBC (Java DataBase Connectivity) is a Java API which enables you to execute SQL language using Java code.
To get data from DB, you usually use the SQL SELECT statement. To insert data in a DB, you usually use the SQL INSERT INTO statement
To prepare a SQL statement in Java, you usually use Connection#prepareStatement(). To execute a SQL SELECT statement in Java, you should use PreparedStatement#executeQuery(). It returns a ResultSet with the query results. To execute a SQL INSERT statement in Java, you should use PreparedStatement#executeUpdate().
See also:
SQL tutorial
JDBC tutorial
I have to improve some code where an Oracle stored procedure is called from a Java program. Currently the code is really really slow: up to about 8 seconds on my development machine. On the same machine, if I directly call an SQL query that does about the same treatment and returns the same data, it takes under 100 ms...
The code creates a CallableStatement, registers one of the output parameters to be an Oracle cursor, and then retrieves the cursor using the getObject method of the statement and parse it to ResultSet:
cstmt = conn.prepareCall("{ call PKG_ESPECEW.P_ListEspece( ?, ?, ?, ?, ?, ? ) }");
cstmt.registerOutParameter(4, oracle.jdbc.OracleTypes.CURSOR);
[...]
cstmt.executeQuery();
rs = (ResultSet)cstmt.getObject(4);
rs.setFetchSize(1000); //supposed to help ?
options = new HashMap<String, String>(1000);
rs.next() //added that to measure exactly the length of the first call
while(rs.next()) {
[...]
}
I put some timestamps in the code to know which part is taking so long. The result: The first call to rs.next() is taking up to various seconds. The result sets are average, from 10 to a couple thousands rows. As I said before, handling similar result sets coming from a regular PreparedStatement takes 10-100 ms depending the size.
Is anything wrong with the code? How do I improve it? I'll do direct SQL where critical if I haven't any other solution, but I'd prefer a solution that allows me to not rewrite all the procedures!
Here is the definition of the stored procedure:
PROCEDURE P_ListEspece(P_CLT_ID IN ESPECE.ESP_CLT_ID%TYPE, -- Langue de l'utilisateur
P_ESP_GROUP_CODE IN ESPECE.ESP_CODE%TYPE,-- Code du groupe ou NULL
P_Filter IN VARCHAR2, -- Filtre de la requĂȘte
P_Cursor OUT L_CURSOR_TYPE, -- Curseur
P_RecordCount OUT NUMBER, -- Nombre d'enregistrement retourne
P_ReturnStatus OUT NUMBER); -- Code d'erreur
"I thought the procedure was executed, then it's result stored in oracle server's memory, and finally transmitted back to the client (the java app) through the cursor and result set and JDBC"
That's incorrect.
What oracle returns as a cursor is basically a pointer to a query (all ready with any bind variables). It has not materialized the result set in memory. It could be a massive result set of millions/billions of rows.
So it could well be a slow query that takes a long time to deliver results.
Apparently the stored procedure is doing some data conversion/massaging forth and back (e.g. int <--> varchar). This is known to take a lot of time in case of large tables. Ensure that you've declared the right datatypes in the SP arguments and are setting the right datatypes in CallableStatement.
How long does it take to execute the procedure outside of Java? Check with a script like this in SQL*Plus:
var ref refcursor
var cnt number
var status number
exec p_listespece (xx, yy, zz, :ref, :cnt, :status);--replace with actual values
print :ref
If it takes more than 10-100 ms, your problem may come from the stored procedure.
I had the same problem, we solved (me and the oracle dedicated guy) by changing the returned parameter from a cursor to a varchar, that was the plain query the stored was executing internally.
this was an huge implementation, I don't know if this is applicable for your scenario.
here's the snippet :
`
String sql = "call MyStored(?,?,?,?)";
CallableStatement st = Conn.prepareCall(sql);
st.setInt(1, 10);
st.setInt(2, 20);
st.setInt(3, 30);
st.registerOutParameter(4, OracleTypes.VARCHAR);
st.execute();
String query = (String) st.getObject(4);
Statement stmt = Conn.createStatement();
rs = stmt.executeQuery(query);
[...]
//work with resultset
[...]
stmt.close();
stmt = null;
`
I have been trying to execute a MS SQL Server stored procedure via JDBC today and have been unsuccessful thus far. The stored procedure has 1 input and 1 output parameter. With every combination I use when setting up the stored procedure call in code I get an error stating that the stored procedure couldn't be found. I have provided the stored procedure I'm executing below (NOTE: this is vendor code, so I cannot change it).
set ANSI_NULLS ON
set QUOTED_IDENTIFIER ON
GO
ALTER PROC [dbo].[spWCoTaskIdGen]
#OutIdentifier int OUTPUT
AS
BEGIN
DECLARE #HoldPolicyId int
DECLARE #PolicyId char(14)
IF NOT EXISTS
(
SELECT *
FROM UniqueIdentifierGen (UPDLOCK)
)
INSERT INTO UniqueIdentifierGen VALUES (0)
UPDATE UniqueIdentifierGen
SET
CurIdentifier = CurIdentifier + 1
SELECT #OutIdentifier =
(SELECT CurIdentifier
FROM UniqueIdentifierGen)
END
The code looks like:
CallableStatement statement = connection
.prepareCall("{call dbo.spWCoTaskIdGen(?)}");
statement.setInt(1, 0);
ResultSet result = statement.executeQuery();
I get the following error: SEVERE: Could not find stored procedure 'dbo.spWCoTaskIdGen'.
I have also tried
CallableStatement statement = connection
.prepareCall("{? = call dbo.spWCoTaskIdGen(?)}");
statement.registerOutParameter(1, java.sql.Types.INTEGER);
statement.registerOutParameter(2, java.sql.Types.INTEGER);
statement.executeQuery();
The above results in: SEVERE: Could not find stored procedure 'dbo.spWCoTaskIdGen'.
I have also tried:
CallableStatement statement = connection
.prepareCall("{? = call spWCoTaskIdGen(?)}");
statement.registerOutParameter(1, java.sql.Types.INTEGER);
statement.registerOutParameter(2, java.sql.Types.INTEGER);
statement.executeQuery();
The code above resulted in the following error: Could not find stored procedure 'spWCoTaskIdGen'.
Finally, I should also point out the following:
I have used the MS SQL Server Management Studio tool and have been able to successfully run the stored procedure. The sql generated to execute the stored procedure is provided below:
GO
DECLARE #return_value int;
DECLARE #OutIdentifier int;
EXEC #return_value = [dbo].[spWCoTaskIdGen] #OutIdentifier = #OutIdentifier OUTPUT;
SELECT
#OutIdentifier [#OutIdentifier],
#return_value [Return Value];
GO
The code being executed runs with the same user id that was used in point #1 above.
In the code that creates the Connection object I log which database I'm connecting to and the code is connecting to the correct database.
Any ideas?
Thank you very much in advance.
Most likely one of...
The credentials uses have no rights to run the code. You'd need a GRANT EXECUTE in the script above
Wrong database. For example, the stored proc was created in master but you are connected to "MyDB"
Since it can't even find the procedure, I would first look to make sure that your user has execute privileges for that procedure. You could try executing the proc with the same user from a tool like Squirrel.
Try it without the dbo. owner designation:
CallableStatement statement = connection.prepareCall("? = spWCoTaskIdGen(?)");
statement.registerOutParameter(1, java.sql.Types.INTEGER);
statement.registerOutParameter(2, java.sql.Types.INTEGER);
statement.executeQuery();
Also, and this is a longshot, are you sure you're in the correct database within the database server?
I had the same problem using SQLServer 2012 Express.
I solved it starting the "SQL Server Browser" service.
Have you tried changing your Java code to use "exec" instead of "call"?
That is:
CallableStatement statement = connection
.prepareCall("{exec dbo.spWCoTaskIdGen(?)}");