Spring JDBC "IF NOT EXIST INSERT" Primary key constraint violation - java

I have a MSSQL database and a Java Spring application which uses Spring's Transaction Management.
I have a query of "IF NOT EXIT, INSERT .." which is ran from multiple threads.
For some reason I get a primary key constraint violation, even through I check for existence before writing, all happens inside a transaction.
I wanted to know what is the reason for that, and how to prevent it.
The query:
IF NOT EXISTS (SELECT docId FROM documentStatus WHERE docId='abc')
BEGIN INSERT INTO documentStatus
VALUES ('abc',1,0,NULL)
END
ELSE
BEGIN
UPDATE documentStatus SET documentStatus.count=documentStatus.count+1
WHERE docId ='abc'
END;
DDL for documentStatus
CREATE TABLE Dss.dbo.docStatus
(
docId NVARCHAR(256),
count INT NOT NULL DEFAULT 1,
error INT NOT NULL DEFAULT 0,
errorMsg NVARCHAR(1024) DEFAULT NULL,
CONSTRAINT PK_docStatus PRIMARY KEY (docId ASC)
)

DDL -
USE tempdb
GO
IF OBJECT_ID('dbo.docStatus', 'U') IS NOT NULL
DROP TABLE dbo.docStatus
GO
CREATE TABLE dbo.docStatus (
docId NVARCHAR(256) PRIMARY KEY,
[count] INT NOT NULL DEFAULT 1,
error INT NOT NULL DEFAULT 0,
errorMsg NVARCHAR(1024)
)
Your example -
IF NOT EXISTS (
SELECT docId
FROM docStatus
WHERE docId = N'abc'
)
BEGIN
INSERT INTO dbo.docStatus (docId) VALUES (N'abc')
END
ELSE
BEGIN
UPDATE docStatus
SET [count] += 1
WHERE docId = N'abc'
END
MERGE statement -
;WITH cte AS
(
SELECT *
FROM dbo.docStatus
WHERE docId = N'abc'
)
MERGE cte t
USING (
SELECT docId = N'abc'
) s ON s.docId = t.docId
WHEN MATCHED
THEN
UPDATE SET t.[count] += 1
WHEN NOT MATCHED BY TARGET
THEN
INSERT (docId, [count])
VALUES (s.docId, 1);

Related

Get inserted row to Oracle with java

I am building a java program to insert data to my oracle database.
My problem is that I need to insert into two tables, and to reach unique rows I use in TABLE_A triggers for id before insert get next val in a sequence.
But i need the same id for the TABLE_B for connection.
( i cant get getval because what if another user uses the program... )
So I need to reach somehow that when I use executeql(sql) command in return I see what I have submit.
Now I use that I have name and date, so I select the id where name and date is the just inserted.
But its not the best because in one day I can insert more names. So now this will not unique.
like :
insert into table a ( name,date) val ( 'Ryan','2014.01.01')
id here is autoincremented by sequence
than another sql run:
inert into table_b ( id,someval) val ( select id from table_a where
name ='Ryan', date='2014.01.01, 23)
so i need something like:
system.out.println(smtp.executesql(sql).whatIinsertednow())
*than console:* '1 row insered (id,name,date) : ( 1, Ryan, 2014.01.01)
PreparedStatement prepareStatement = connection.prepareStatement("insert...",
new String[] { "your_primary_key_column_name" });
prepareStatement.executeUpdate();
ResultSet generatedKeys = prepareStatement.getGeneratedKeys();
if (null != generatedKeys && generatedKeys.next()) {
Long primaryKey = generatedKeys.getLong(1);
}
I have found the answer this is perfectly works. I can insert from JAVA and its return with the key.
Full version:
CREATE TABLE STUDENTS
(
STUDENT_ID NUMBER NOT NULL PRIMARY KEY,
NAME VARCHAR2 (50 BYTE),
EMAIL VARCHAR2 (50 BYTE),
BIRTH_DATE DATE
);
CREATE SEQUENCE STUDENT_SEQ
START WITH 0
MAXVALUE 9999999999999999999999999999
MINVALUE 0;
And the Java code
String QUERY = "INSERT INTO students "+
" VALUES (student_seq.NEXTVAL,"+
" 'Harry', 'harry#hogwarts.edu', '31-July-1980')";
// load oracle driver
Class.forName("oracle.jdbc.driver.OracleDriver");
// get database connection from connection string
Connection connection = DriverManager.getConnection(
"jdbc:oracle:thin:#localhost:1521:sample", "scott", "tiger");
// prepare statement to execute insert query
// note the 2nd argument passed to prepareStatement() method
// pass name of primary key column, in this case student_id is
// generated from sequence
PreparedStatement ps = connection.prepareStatement(QUERY,
new String[] { "student_id" });
// local variable to hold auto generated student id
Long studentId = null;
// execute the insert statement, if success get the primary key value
if (ps.executeUpdate() > 0) {
// getGeneratedKeys() returns result set of keys that were auto
// generated
// in our case student_id column
ResultSet generatedKeys = ps.getGeneratedKeys();
// if resultset has data, get the primary key value
// of last inserted record
if (null != generatedKeys && generatedKeys.next()) {
// voila! we got student id which was generated from sequence
studentId = generatedKeys.getLong(1);
}
}
source : http://viralpatel.net/blogs/oracle-java-jdbc-get-primary-key-insert-sql/
You can accomplish that by using the RETURNING clause in your INSERT statement:
INSERT INTO table_a ( name,date) val ( 'Ryan','2014.01.01') RETURNING id INTO ?

java.sql.SQLException: Subquery returns more than 1 row

I have a program that when executed it gets lots of words from a file and inserts them into a database, after being inserted if the word is inserted twice it calculates the "IDF" again using a trigger. The problem is that if I do this directly into MySQL it has no problem, but if I do this on Java it returns this error:
Exception in thread "main" java.sql.SQLException: Subquery returns more than 1 row
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1086)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4237)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4169)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2617)
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2778)
at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2828)
at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2777)
at com.mysql.jdbc.StatementImpl.execute(StatementImpl.java:949)
at com.mysql.jdbc.StatementImpl.execute(StatementImpl.java:795)
at model.Consultas.altaBajaCambio(Consultas.java:29)
at model.DatosBD.agregarPalabra(DatosBD.java:23)
at search.Search.main(Search.java:36)
Java Result: 1
I assume the problem has to be with the st.execute(), since it only gives back one int, but I have search on the web for a solution and I cannot find one.
Query:
String query2 = "INSERT IGNORE INTO Search.IndiceInv (DocID, Term, TF) VALUES ("+doc+",'"+term+"',1) ON DUPLICATE KEY UPDATE `TF` = `TF` + 1;";
c.altaBajaCambio(query2);
Execution:
try (Connection con = c.getConnection()) {
if (con == null) {
System.out.println("No hay conexion");
} else {
Statement st = con.createStatement();
st.execute(query);
}
Database:
-- -----------------------------------------------------
-- Table `Search`.`Doc`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `Search`.`Doc` (
`DocID` INT NOT NULL,
PRIMARY KEY (`DocID`))
ENGINE = InnoDB;
-- -----------------------------------------------------
-- Table `Search`.`Term`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `Search`.`Term` (
`Term` VARCHAR(45) NOT NULL,
`IDF` INT NOT NULL,
PRIMARY KEY (`Term`))
ENGINE = InnoDB;
-- -----------------------------------------------------
-- Table `Search`.`IndiceInv`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `Search`.`IndiceInv` (
`DocID` INT NOT NULL,
`Term` VARCHAR(45) NOT NULL,
`TF` INT NOT NULL,
PRIMARY KEY (`DocID`, `Term`),
ENGINE = InnoDB;
Trigger:
delimiter //
create trigger IDF
after update on IndiceInv
for each row
begin
update Term
set IDF = (SELECT LOG((SELECT count(*) FROM Doc)/(SELECT count(DocID) FROM IndiceInv WHERE Term = new.Term)) FROM Doc, IndiceInv)
where Term = new.Term;
end;//
delimiter ;
Try to run manually:
SELECT LOG((SELECT count(*) FROM Doc)/(SELECT count(DocID) FROM IndiceInv WHERE Term = new.Term)) FROM Doc, IndiceInv
(assign the relevant values to new.Term etc)

Transaction count after EXECUTE indicates a mismatching number of BEGIN and COMMIT statements. Previous count

I am getting this exception about commits and rollbacks but am not sure what exactly is wrong with my Stored Procedure. I have read the answers in other such questions and am unable to find where exactly the commit count is getting messed up.
So, this is the Stored Procedure I use:
-- this is a procedure used for the purge utility. This procedure uses the parameters of a date and lets user select
-- if the leads that should be purge must be closed either before, on or since that date.
-- operator: 0-->less 1-->equal 2-->greater
-- #closed: closing date
-- leadscount: returns the count of leads deleted
IF OBJECT_ID ('LEAD_PURGE', 'P') IS NOT NULL
DROP PROCEDURE LEAD_PURGE
go
CREATE PROCEDURE LEAD_PURGE
#purgextns INT,
#leadscount INT OUTPUT
AS
BEGIN
BEGIN TRANSACTION
CREATE TABLE #ASSIGNMENTS_DELETED
(
ID NUMERIC(19, 0)
PRIMARY KEY (ID)
)
CREATE TABLE #MAPRESULTS_DELETED
(
ID NUMERIC(19, 0)
PRIMARY KEY (ID)
)
CREATE TABLE #COMMAND_DELETED
(
ID NUMERIC(19, 0)
PRIMARY KEY (ID)
)
CREATE TABLE #PROGRESS_STATUS_DELETED
(
ID NUMERIC(19, 0)
PRIMARY KEY (ID)
)
CREATE TABLE #DETAILS_DELETED
(
ID NUMERIC(19, 0)
PRIMARY KEY (ID)
)
CREATE TABLE #NEEDS_DELETED
(
ID NUMERIC(19, 0)
PRIMARY KEY (ID)
)
insert into #ASSIGNMENTS_DELETED
select SEQID FROM ASSIGNMENT WHERE LEADSEQ IN (SELECT ID FROM PURGE_LEAD);
SELECT #leadscount = (SELECT COUNT(*) FROM PURGE_LEAD);
INSERT INTO #MAPRESULTS_DELETED
SELECT ID FROM MAPRESULT WHERE ASSIGNMENTSEQ IN (SELECT ID FROM #ASSIGNMENTS_DELETED)
INSERT INTO #COMMAND_DELETED
SELECT ID FROM EXECUTERULECOMMAND WHERE MAPRESULTID IN (SELECT ID FROM #MAPRESULTS_DELETED)
INSERT INTO #PROGRESS_STATUS_DELETED
SELECT PROGRESS_STATUS_ID FROM COMMAND WHERE ID IN (SELECT ID FROM #COMMAND_DELETED)
INSERT INTO #DETAILS_DELETED
SELECT DETAILID FROM LEAD WHERE SEQID IN (SELECT ID FROM PURGE_LEAD)
INSERT INTO #NEEDS_DELETED
SELECT NEEDSID FROM LEAD WHERE SEQID IN (SELECT ID FROM PURGE_LEAD)
DELETE FROM PROGRESS_STATUS WHERE ID IN (SELECT ID FROM #PROGRESS_STATUS_DELETED)
DELETE FROM EXECUTERULECOMMAND WHERE ID IN (SELECT ID FROM #COMMAND_DELETED)
DELETE FROM COMMAND WHERE ID IN (SELECT ID FROM #COMMAND_DELETED)
DELETE FROM SIMPLECONDITIONAL WHERE RESULT IN (SELECT ID FROM #MAPRESULTS_DELETED)
DELETE FROM MAPPREDICATE WHERE ROWBP IN (SELECT ID FROM MAPROW WHERE RESULT IN (SELECT ID FROM #MAPRESULTS_DELETED))
DELETE FROM MAPROW WHERE RESULT IN (SELECT ID FROM #MAPRESULTS_DELETED)
DELETE FROM MAPRESULT WHERE ID IN (SELECT ID FROM #MAPRESULTS_DELETED)
DELETE FROM ASSIGNMENTATTACHMENTS WHERE ASSIGNMENTSEQ IN (SELECT ID FROM #ASSIGNMENTS_DELETED)
DELETE FROM LEADOBSERVER WHERE ASSIGNSEQ IN (SELECT ID FROM #ASSIGNMENTS_DELETED)
DELETE FROM MAPDESTINATIONS WHERE SUGGESTEDASSIGNID IN
(SELECT ID FROM SUGGESTEDASSIGNMENT WHERE ASSIGNMENT_SEQID IN (SELECT ID FROM #ASSIGNMENTS_DELETED))
DELETE FROM SUGGESTEDASSIGNMENT WHERE ASSIGNMENT_SEQID IN (SELECT ID FROM #ASSIGNMENTS_DELETED)
DELETE FROM PRODUCTINTEREST WHERE LEADSEQ IN (SELECT ID FROM PURGE_LEAD)
CREATE TABLE #SALE_DELETED_EX
(
ID NUMERIC(19, 0)
PRIMARY KEY (ID)
)
INSERT into #SALE_DELETED_EX SELECT SALEEXSEQ FROM SALE WHERE SEQID IN (SELECT SALEID FROM LEADSALES WHERE LEADID IN (SELECT ID FROM PURGE_LEAD))
DELETE FROM SALE WHERE SEQID IN (SELECT SALEID FROM LEADSALES WHERE LEADID IN (SELECT ID FROM PURGE_LEAD))
DELETE FROM SALEEXTENSIONS WHERE
SEQID IN (SELECT ID FROM #SALE_DELETED_EX)
DELETE FROM LEADSALES WHERE LEADID IN (SELECT ID FROM PURGE_LEAD)
DELETE FROM NOTES WHERE OBJECTID IN (SELECT ID FROM #NEEDS_DELETED) OR OBJECTID IN (SELECT ID FROM #DETAILS_DELETED)
DELETE FROM HISTORYRECORD WHERE OBJECTID IN (SELECT ID FROM #DETAILS_DELETED)
DELETE FROM DETAIL WHERE SEQID IN (SELECT ID FROM #NEEDS_DELETED UNION SELECT ID FROM #DETAILS_DELETED)
DELETE FROM MESSAGES WHERE PROVIDERID IN (SELECT ID FROM PURGE_LEAD)
DELETE FROM ASSIGNMENT WHERE LEADSEQ IN (SELECT ID FROM PURGE_LEAD)
DELETE FROM LEAD WHERE SEQID IN (SELECT ID FROM PURGE_LEAD)
CREATE TABLE #PURGE_LEAD_E
(
ID NUMERIC(19, 0)
PRIMARY KEY (ID)
)
INSERT into #PURGE_LEAD_E Select SEQID FROM LEADEXTENSIONS WHERE
SEQID NOT IN (SELECT LEADEXSEQ FROM LEAD)
if #purgextns = 1 begin
DELETE FROM LEADEXTENSIONS WHERE
SEQID IN (SELECT ID FROM PURGE_LEAD_E)
end
DELETE FROM PURGE_LEAD;
DROP TABLE #ASSIGNMENTS_DELETED
DROP TABLE #MAPRESULTS_DELETED
DROP TABLE #COMMAND_DELETED
DROP TABLE #PROGRESS_STATUS_DELETED
DROP TABLE #DETAILS_DELETED
DROP TABLE #NEEDS_DELETED
DROP TABLE #PURGE_LEAD_E
DROP TABLE #SALE_DELETED_EX
COMMIT
END
go
now I call this procedure in the following code:
try {
c = new ConnectionHelper().getConnection();
String sql = "";
if (shouldPurgeExtns) {
progressModel.makeProgress("progress.deleting.dependents");
purgeMultiselect(c, LEAD, isMSSQL);
}
sql = "{CALL " + TOPLinkManager.getSchemaPrefix()
+ "LEAD_PURGE (?,?)}";
cs = c.prepareCall(sql);
cs.setInt(1, shouldPurgeExtns ? 0 : 1);
cs.registerOutParameter(2, java.sql.Types.INTEGER);
cs.executeUpdate();
int rowcount = cs.getInt(2);
cs.close();
progressModel.makeProgress("progress.recording.history");
recordHistory(c, isMSSQL, LEAD, DateTypeDecorator.CLOSED, date,
rowcount);
done(progressModel);
c.close();
return true;
} catch (Exception e) {
Logs.main.error("Error Purging Leads", e);
throw new Exception(e.getMessage());
}
And I get an exception on the line which say int rowcount = cs.getInt(2);
The Exception is:
com.microsoft.sqlserver.jdbc.SQLServerException: Transaction count after EXECUTE indicates a mismatching number of BEGIN and COMMIT statements. Previous count = 0, current count = 1.
at com.microsoft.sqlserver.jdbc.SQLServerException.makeFromDatabaseError(SQLServerException.java:196)
at com.microsoft.sqlserver.jdbc.SQLServerStatement.getNextResult(SQLServerStatement.java:1454)
at com.microsoft.sqlserver.jdbc.SQLServerStatement.processResults(SQLServerStatement.java:1083)
at com.microsoft.sqlserver.jdbc.SQLServerCallableStatement.getOutParameter(SQLServerCallableStatement.java:112)
at com.microsoft.sqlserver.jdbc.SQLServerCallableStatement.getterGetParam(SQLServerCallableStatement.java:387)
Please help me out.
at com.microsoft.sqlserver.jdbc.SQLServerCallableStatement.getValue(SQLServerCallableStatement.java:393)
at com.microsoft.sqlserver.jdbc.SQLServerCallableStatement.getInt(SQLServerCallableStatement.java:437)
at marketsoft.tools.purge.PurgeUtils.PurgeLeads(PurgeUtils.java:283)
EDIT:
as I have answered this question myself... I would like to change the question a bit now.
Why was no exception thrown in the execute method???
Your COMMIT is not being hit, probably because of an error. The transaction won't be rolled back automatically
The best way (and best practice) is to add some SQL error handling
CREATE PROCEDURE LEAD_PURGE
#purgextns INT,
#leadscount INT OUTPUT
AS
SET NOCOUNT, XACT_ABORT ON;
BEGIN TRY
BEGIN TRANSACTION
CREATE TABLE #ASSIGNMENTS_DELETED
(
ID NUMERIC(19, 0)
PRIMARY KEY (ID)
)
...
DROP TABLE #SALE_DELETED_EX
COMMIT TRANSACTION
END TRY
BEGIN CATCH
IF XACT_STATE() <> 0
ROLLBACK TRANSACTION
RAISERROR ('it broke', 16, 1)
END CATCH
go
For more details on what is going on here, see my answer here Nested stored procedures containing TRY CATCH ROLLBACK pattern?
Note: you don't need to drop the temp tables as they go out of scope when the stored procedure exits
Try to add in the beginning of procedure
SET XACT_ABORT ON
Or
Wrap your statements with
begin try
BEGIN TRANSACTION
Your TSQL code
COMMIT
end try
begin catch
ROLLBACK
RAISERROR('Gotcha!', 16, 1)
end catch
To check how many uncommitted BEGIN TRAN is opened test the ##TRANCOUNT system variable
This normally happens when the transaction is started and either it is not committed or it is not rollback.
In case the error comes in your stored procedure, this can lock the database tables because transaction is not completed due to some runtime errors in the absence of exception handling
You can use Exception handling like below. SET XACT_ABORT
SET XACT_ABORT ON
SET NoCount ON
Begin Try
BEGIN TRANSACTION
//Insert ,update queries
COMMIT
End Try
Begin Catch
ROLLBACK
End Catch
Sorry Guys! Thanks for all your efforts, In the end, it was a very small mistake on my part in the Stored Procedure:
Look at line:
if #purgextns = 1 begin
DELETE FROM LEADEXTENSIONS WHERE
SEQID IN (SELECT ID FROM PURGE_LEAD_E)
end
It should be #PURGE_LEAD_E
All your answers helped me get a different perspective of store procedure development. Thanks a lot!
How exactly the #leadscount variable contains the count of leads deleted?
This is the only place I see it beeing used:
SELECT #leadscount = (SELECT COUNT(*) FROM PURGE_LEAD);
Anyhow, to test it, why don't you run the above code outside the context of the transaction?
If you really need it to be inside a transaction, try loading the value into a table variable (create a table with only one column). Since they don't participate in transactions you can test if the transaction is your real problem.

Delete Row from Oracle table by passing table name and column name

I have jsp page where user selects table name, column name and column value, with those three condtion I want to delete all matching row from the database. Is there a way to pass table name, column name and column value in oracle to delete certain row from the table? Any example would help me.. Thank you
I'd worry about SQL Injection attacks as you are supplying the table and column names.
You could create an Oracle function to remove the records required and test for certain conditions to be met before removing the row:
CREATE OR REPLACE
FUNCTION delete_record (
p_table IN VARCHAR2,
p_column IN VARCHAR2,
p_value IN VARCHAR2
)
RETURN NUMBER
AS
v_table user_tables.table_name%TYPE;
v_columns user_tab_cols.column_name%TYPE;
BEGIN
-- Check table exists in DB
SELECT table_name
INTO v_table
FROM user_tables
WHERE table_name = UPPER(p_table);
-- Check column exists in DB table
SELECT column_name
INTO v_colums
FROM user_tab_cols
WHERE table_name = UPPER(p_table)
AND column_name = UPPER(p_column);
EXECUTE IMMEDIATE
'DELETE FROM '||DBMS_ASSERT.SIMPLE_SQL_NAME(p_table)||
' WHERE '||DBMS_ASSERT.SIMPLE_SQL_NAME(p_column)||' = :col_value'
USING p_value;
RETURN SQL%ROWCOUNT;
EXCEPTION
WHEN NO_DATA_FOUND
THEN
-- Either return -1 (error) or log an error etc.
RETURN -1;
WHEN others
THEN
<Your exception handling here>
END delete_record;
/
This (or something like this) would check the table and column variables supplied exist in the database before then deleting the records and returning the number of records deleted.
If there is a problem with the number deleted you can issue a rollback statement, if it is OK then you can issue a commit.
Of course, if you want to supply a fully qualified table name (recommended) then you would use the DBMS_ASSERT.QUALIFIED_SQL_NAME function instead of the DBMS_ASSERT.SIMPLE_SQL_NAME function.
Hope it helps...
EDIT: In response to Jack's question about adding date from and date to.
If you add two new conditions that are passed in to the function as:
CREATE OR REPLACE
FUNCTION delete_record (
p_table IN VARCHAR2,
p_column IN VARCHAR2,
p_value IN VARCHAR2,
p_date_from IN DATE,
p_date_to IN DATE
)
Then you'd need to expand the EXECUTE IMMEDIATE with:
EXECUTE IMMEDIATE
'DELETE FROM '||DBMS_ASSERT.SIMPLE_SQL_NAME(p_table)||
' WHERE '||DBMS_ASSERT.SIMPLE_SQL_NAME(p_column)||' = :col_value'||
' AND date BETWEEN :date_from AND :date_to'
USING p_value,
p_date_from,
p_date_to;
N.B. This assumes your date column in the table is called "date".
I don't have a SQL interface in front of me at the moment but this should be close enough to what you need to get it working.
If you are passing the p_date_XXXX parameters in as VARCHAR2 and not DATE types then you's need to "TO_DATE" the values before passing them into the dynamic SQL.
e.g.
EXECUTE IMMEDIATE
'DELETE FROM '||DBMS_ASSERT.SIMPLE_SQL_NAME(p_table)||
' WHERE '||DBMS_ASSERT.SIMPLE_SQL_NAME(p_column)||' = :col_value'||
' AND date BETWEEN :date_from AND :date_to'
USING p_value,
TO_DATE(p_date_from, <date_format>),
TO_DATE(p_date_to, <date_format>);
DELETE FROM table_name WHERE column_name = column_value
The problem is that you can't bind table or column names in PreparedStatement, only column values.
This should work (from memory; not tested):
Statement stmt = null;
try
{
stmt = conn.createStatement("DELETE FROM " + tableName + " WHERE " + columnName + " = '" + condition + "'");
int deleted = stmt.execute();
}
catch (SQLException e)
{
... report error
}
try
{
if (stmt != null)
stmt.close();
}
catch (SQLException ignore)
{
}

Stored Procedure with parameters/variables - how to get result from procedure execution?

Have a question about stored procedure:
How to retrieve the variable's value from stored procedure that is declared as an output variable.
Running procedure as :
EXEC pn_investment_type_eqt {args}
Here is stored procedure:
create proc pn_investment_type_eqt
(
#product_type varchar(10),
#country varchar(10),
#fi_treatment varchar(1)= '',
#investment_type varchar(10) output,
#investment_description varchar(50) output
)
as
set nocount on
if #country <> 'US'
select #country = 'FOREIGN'
if ( #fi_treatment not in ('Y','N') )
select #fi_treatment = 'N'
if not exists(select 1 from d_investment_type_eqt
where product_type = #product_type and isNull(country,'') = isNull(#country,'') and fi_treatment = #fi_treatment and row_status='A' )
begin
select #country = 'ANY'
end
if exists ( select 1 from d_investment_type_eqt
where product_type = #product_type and isNull(country,'') = isNull(#country,'') and fi_treatment = #fi_treatment and row_status='A' )
begin
select #investment_type= investment_type , #investment_description = description
from d_investment_type_eqt
where product_type = #product_type and isNull(country,'') = isNull(#country,'') and fi_treatment = #fi_treatment and row_status='A'
end
else
return (-1)
I need to get values of #investment_type & #investment_description.
I can't change procedure.
I am using a custom implementation of jdbcTemplate of Spring 2.0 (sql, mapper, args)
DB is Sybase
How could I get results from this stored procedure ?
Take a look at this sybase-in-and-out-parameters post, it possibly helps you further.
I decided to use next design :
declare #investment_type_value varchar(10)
declare #investment_description_value varchar(50)
SET #investment_type_value = '3041'
EXEC global..pn_investment_type_eqt 'CVPFDST', 'US', 'N', #investment_type = #investment_type_value output , #investment_description = #investment_description_value OUTPUT
select investment_type = #investment_type_value, investment_description = #investment_description_value
GO
It give me possibility to retrieve variable values.

Categories