I am trying to use an Oracle stored procedure to update a database table. I am calling the procedure from a Java program. I want my procedure to accept dates in the format '01-01-2015' but for some reason my procedure will only accept a date if it is formatted as '01-JAN-2015'.
My stored procedure:
DELIMITER //
CREATE OR REPLACE PROCEDURE updateAward
(
p_award_id IN awards.award_id%TYPE,
p_award_date IN awards.award_date%TYPE,
p_total_amount IN awards.total_amount%TYPE,
p_number_sales IN awards.number_sales%TYPE,
p_emp_id IN awards.emp_id%TYPE
)
AS
BEGIN
UPDATE awards
SET award_date = to_date(p_award_date, 'DD-MM-YYYY'),
total_amount = p_total_amount,
number_sales = p_number_sales,
emp_id = p_emp_id
WHERE award_id = p_award_id;
COMMIT;
END;
/
The java code that calls it:
public boolean updateByID(Connection conn, String strVar, int[] intVar, double doubleVar)
{
System.out.println(strVar);
System.out.println(doubleVar);
System.out.println(intVar[0]);
System.out.println(intVar[1]);
System.out.println(intVar[2]);
try
{
String query = "{call updateAward(?,?,?,?,?)}";
CallableStatement stmt = conn.prepareCall(query);
stmt.setInt(1,intVar[0]);
stmt.setString(2, strVar);
stmt.setDouble(3, doubleVar);
stmt.setInt(4, intVar[1]);
stmt.setInt(5, intVar[2]);
stmt.executeUpdate();
return true;
}
catch(SQLException e)
{
System.out.println(e.getMessage());
}
return false;
}
The console print out of the variables being passed:
12-12-2012
65165.2
21
22
3
The error itself:
KORA-01843: not a valid month
ORA-06512: at line 1
Every solution that I have found has been to put the date format in the procedure. I believe I have done it with
award_date = to_date(p_award_date, 'DD-MM-YYYY'),
Have I written it incorrectly? Can someone please help?
Currently you are passing a String:
stmt.setString(2, strVar);
And you are parsing a String:
award_date = to_date(p_award_date, 'DD-MM-YYYY')
But you are expecting a Date in your custom type, and that is where the conversion fails. Change that to VARCHAR (or VARCHAR2) and it will work.
You're passing a string to a procedure that's expecting an Oracle date argument, via setString(). That means Oracle has to do an implicit conversion of the string to a date as part of the call, using the session/locale NLS_DATE_FORMAT, before you reach your to_date() call.
You could change your procedure argument type from awards.award_date%TYPE to varchar2, and still do the explicit conversion inside the procedure. Or you can leave the procedure signature as it is and pass the correct data type by converting it on the Java side, e.g.:
SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy");
cStmt.setDate(2, new java.sql.Date(sdf.parse(strVar).getTime()));
And as p_date is already a date, you should not call to_date() on that, as it will do an implicit conversion back to a string (using NLS_DATE_FORMAT again) and then try to explicitly convert that back to a date using the format model you supplied, which is also likely to give a similar error. Simplify that to just:
SET award_date = p_award_date,
Related
I am calling postgreSQL function from Java using SimpleJdbcCall and extracting the output in ResultSet, while the function returns data when run in postgre but in Java it is giving null result.
Here is my postgre function that I am calling:
CREATE OR REPLACE FUNCTION package.getdemojob(create_user_id character varying)
RETURNS TABLE(batch_id bigint, content_id character varying, start_date timestamp without time zone,
end_date timestamp without time zone)
LANGUAGE plpgsql
AS $function$
BEGIN
RETURN query
SELECT MY_TABLE.BATCH_ID, MY_TABLE.CONTENT_ID, MY_TABLE.START_DATE, MY_TABLE.END_DATE
FROM MY_TABLE
WHERE MY_TABLE.CREATE_USER = create_user_id
ORDER BY BATCH_ID;
END;
$function$
;
Java code that I am using to call this function is:
this.demoGetJob = new SimpleJdbcCall(jdbcTemplate)
.withCatalogName("package")
.withProcedureName("getdemojob")
.withoutProcedureColumnMetaDataAccess()
.useInParameterNames("create_user_id")
.declareParameters(
new SqlParameter("create_user_id", Types.VARCHAR)
);
SqlParameterSource in = new MapSqlParameterSource().addValue("create_user_id", userId);
ResultSet rs = demoGetJob.executeFunction(ResultSet.class, in);
while(rs.next()){
System.out.println(rs.getInt("batch_id"));
}
On line rs.next() I am getting nullPointerException though there is data present in MY_TABLE with the given create_user_id
What wrong am I doing?
Thanks in advance.
I am in the process of converting an application from Jython to compiled Java. The application uses a host of SQL Server stored procedures to do CRUD operations. All of the procedures are defined with a return value that indicates status, and some output parameters used to provide feedback to the application. Most of the procedures also return a result set. I'm struggling with how to retrieve the return value and the result set and the output parameters.
I normally work with C# so the nuances of JDBC are new to me. I've been testing with one of the procedures that does an insert to the database and then does a select on the inserted object.
Here's a simplified example procedure just to use for the purpose of illustration. The actual procedures are more complex than this.
CREATE PROCEDURE [dbo].[sp_Thing_Add]
(
#Name NVARCHAR(50),
#Description NVARCHAR(100),
#ResultMessage NVARCHAR(200) = N'' OUTPUT
)
AS
BEGIN
SET NOCOUNT ON
DECLARE #Result INT = -1
DECLARE #ResultMessage = 'Procedure incomplete'
BEGIN TRY
INSERT INTO Things (Name, Description) VALUES (#Name, #Description)
SELECT * FROM Things WHERE ThingID = SCOPE_IDENTITY()
END TRY
BEGIN CATCH
SELECT #Result = CASE WHEN ERROR_NUMBER() <> 0 THEN ERROR_NUMBER() ELSE 1 END,
#ResultMessage = ERROR_MESSAGE()
GOTO EXIT_SUB
END CATCH
SUCCESS:
SET #Result = 0
SET #ResultMessage = N'Procedure completed successfully'
RETURN #Result
EXIT_SUB:
IF #Result <> 0
BEGIN
-- Do some error handling stuff
END
RETURN #Result
I can successfully retrieve the ResultSet using the following code.
var conn = myConnectionProvider.getConnection();
String sql = "{? = call dbo.sp_Thing_Add(?, ?, ?)}"
call = conn.prepareCall(sql);
call.registerOutParameter(1, TYPES.Integer); // Return value
call.setString("Name", thing.getName());
call.setString("Description", thing.getDescription());
call.registerOutParameter("ResultMessage", TYPES.NVARCHAR);
ResultSet rs = call.executeQuery();
// Try to get the return value. This appears to close the ResultSet and prevents data retrieval.
//int returnValue = call.getInt(1);
// Normally there'd be a check here to make sure things executed properly,
// and if necessary the output parameter(s) may also be leveraged
if (rs.next()) {
thing.setId(rs.getLong("ThingID"));
// Other stuff actually happens here too...
}
If I try retrieving the return value using the line that's commented out, I get an error stating that the ResultSet is closed.
com.microsoft.sqlserver.jdbc.SQLServerException: The result set is closed.
I've been through the documentation and have seen how to do return values, output parameters, and result sets. But how can I leverage all 3?
Given the order of processing in your stored procedure (insert, select, then populate result parameters), you need to process the result set before you retrieve the return value with CallableStatement.getXXX.
The output is in the ResultSet rs retrieved from executeQuery().
You may want to use the excute method as such:
call.execute();
String returnValue = call.getString("ResultMessage");
You also want to map correctly to the output type.
Your connection got closed once the execute query is executed. Basically mysql jdbc connection extends to AutoCloseable implicitly. Since your result is only entity from procedure,please get the value by index 0 and do a proper index out of bound exception handling.
Here is my code..I got error
"UCanAccess error - net.ucanaccess.jdbc.UcanaccessSQLException: incompatible data type in operation: at following line..
PreparedStatement pStmt = conn.prepareStatement(sql)
public void showCeilingMaterials(Site_Details site_detail)
{
String sql="SELECT SiteName, SUM(PlanTileQuantity), SUM(PlanTilePrice), SUM(PellingQuantity),SUM(PellingPrice), SUM(PowderQuantity),SUM(PowderPrice),SUM(LpattiQuantity),SUM(LpattiPrice),LpattiSize,SUM(CeilingTotalPrice) FROM CeilingMaterials Where SiteName='?' AND Date<='?' AND Date>=?";
try (PreparedStatement pStmt = conn.prepareStatement(sql)) {
SimpleDateFormat format = new SimpleDateFormat("MM/dd/yyyy");
java.util.Date parsed = format.parse(site_detail.getStartDate());
java.sql.Date sql_date1 = new java.sql.Date(parsed.getTime());
format.format(sql_date1);
java.util.Date parsed1 = format.parse(site_detail.getEndDate());
java.sql.Date sql_date2 = new java.sql.Date(parsed1.getTime());
format.format(sql_date2);
pStmt.setString(1, site_detail.getSiteName());
pStmt.setDate(2, sql_date1);
pStmt.setDate(2,sql_date2);
ResultSet rs= pStmt.executeQuery();
while(rs.next()){
showCeil.setSiteName(rs.getString("SiteName"));
showCeil.setTileQuantity(rs.getString("PlanTileQuantity"));
showCeil.setTilePrice(rs.getString("PlanTilePrice"));
showCeil.setPellingQuantity(rs.getString("PellingQuantity"));
showCeil.setPellingPrice(rs.getString("PellingPrice"));
showCeil.setLpattiQuantity(rs.getString("LpattiQuantity"));
showCeil.setLpattiPrice(rs.getString("LpattiPrice"));
showCeil.setLpattiSize(rs.getString("LpattiSize"));
showCeil.setPowderQuantity(rs.getString("PowderQuantity"));
showCeil.setPowderPrice(rs.getString("PowderPrice"));
showCeil.setTotalCeilingPrice(rs.getString("CeilingTotalPrice"));
show_ceil_w=new Site_Details_Show_Interface();
show_ceil_w.showGui(showCeil);
}
}
}
The SQL command text for a parameterized query must never include quotes (or other delimiters) around parameter placeholders. You have the following, which is incorrect:
... Where SiteName='?' AND Date<='?' AND Date>=?
Specifically, it is Date<='?' that is causing the error cited in the question, although the error message is slightly different in newer versions of UCanAccess (in this case, v3.0.2):
net.ucanaccess.jdbc.UcanaccessSQLException: UCAExc:::3.0.2 incompatible data types in combination
Instead, you need to have
... Where SiteName=? AND [Date]<=? AND [Date]>=?
[Note that Date is a reserved word (built-in function name) in Access so you should use square brackets around it if you want to refer to a column named Date.]
Once that error is corrected then other errors in your SQL manifest themselves. The next one you will have to address is:
net.ucanaccess.jdbc.UcanaccessSQLException: UCAExc:::3.0.2 expression not in aggregate or GROUP BY columns: PUBLIC.CEILINGMATERIALS.SITENAME
because you have included SiteName in your list of columns to be returned, but it is not part of an aggregate function (e.g., MIN(), MAX()) or a GROUP BY clause. You have that same problem with LpattiSize as well.
You also have
pStmt.setDate(2, sql_date1);
pStmt.setDate(2,sql_date2);
where you have assigned a value to parameter #2 twice (so parameter #3 has no value).
Finally, be aware that when you SUM() a column without providing an alias, as in
SELECT ... SUM(PlanTileQuantity), ...
the resulting column will not be named "PlanTileQuantity". UCanAccess will assign it an arbirtary column name like "C1", "C2", etc.. It is always best to explicitly assign an alias, e.g.,
SELECT ... SUM(PlanTileQuantity) AS SumOfPlanTileQuantity, ...
I'm trying to use a to_date function inside a callableStatement.
My statement ends up being
RGPKG.PKG_RG_LEAD.ADD_LEAD('TO_DATE('05-Aug-2014 11:53:34 AM', 'DD-MON-RR HH.MI.SSXFF AM')',
<More-parameters-here>)
I'm using the following code to build up the TO_DATE function:
CallableStatement stmt
String dateParam = "TO_DATE('" + sTS + "', 'DD-MON-RR HH.MI.SSXFF AM')";
stmt.setString(1, dateParam);
//set more parameters
stmt.execute();
Where sTS is a string in the right date format. I can see that the problem is that the setString is wrapping my string in single quotes, but how do I set this on the callable statement?
create or replace
PACKAGE BODY PKG_RG_LEAD AS
PROCEDURE ADD_LEAD
(p_created_tstamp IN RG_LEAD.CREATED_TSTAMP%type,
p_created_by IN RG_LEAD.CREATED_BY%type,
And the column on the database is created as
CREATED_TSTAMP TIMESTAMP(6) No systimestamp 2
Why don't want to convert your string into date and then send it to your procedure? I have answered similar question already
If you are intent on passing a string into the call, your statement should be:
RGPKG.PKG_RG_LEAD.ADD_LEAD(TO_TIMESTAMP(?, 'DD-MON-RR HH.MI.SSXFF AM'), ?, ...)
Then you can set the value with:
stmt.setString(1, sTS);
You need to_timestamp() rather than to_date() if you want fractional seconds and the XFF part of the format mask, although your sample values doesn't have fractional seconds anyway.
But it would be much better to pass an actual timestamp value, using stmt.setTimestamp() as zaratustra suggests. Here's an example:
String sTS = "05-Aug-2014 11:53:34 AM";
stmt = conn.prepareCall("{ call RGPKG.PKG_RG_LEAD.ADD_LEAD(?, ?, ...) }";
SimpleDateFormat sdf = new SimpleDateFormat("dd-MMM-yy hh:mm:ss a");
stmt.setTimestamp(1, new Timestamp(sdf.parse(sTS).getTime()));
...
If your actual value does have fraction seconds then make the format "dd-MMM-yy hh:mm:ss.S a".
String datum = datumInvoer.getText();
**String bdate = bdatumInvoer.getText();**
String[] speler = spelers.getSelectedItem().toString().split(" ");
String[] toernooi = toernooien.getSelectedItem().toString().split(" ");
try {
PreparedStatement query = con.prepareStatement("INSERT INTO `fullhouse`.`inschrijving_toernooi` ( `IT_datum`, `IT_betaaldatum`, `speler`, `toernooi`) VALUES (?, ?, ? ,?)");
query.setString(1, datum);
query.setString(2, bdatum);
query.setString(3, speler[0]);
query.setString(4, toernooi[0]);
query.execute();
i have set the default to NULL , but it still wont insert it i am close to changing the datatype to varchar.
ERROR: incorrect date value
delimiter $$
CREATE TABLE `inschrijving_toernooi` (
`IT_code` int(11) NOT NULL AUTO_INCREMENT,
`IT_datum` date DEFAULT NULL,
`IT_betaaldatum` date DEFAULT NULL,
`speler` int(11) NOT NULL,
`toernooi` int(11) NOT NULL,
PRIMARY KEY (`IT_code`),
UNIQUE KEY `aaa` (`speler`,`toernooi`),
KEY `FS_code_idx` (`speler`),
KEY `FT_code_idx` (`toernooi`),
First Convert your date parameter from string to date. For that follow code below.
String bdate = bdatumInvoer.getText();
// get the correct date Format
// follow the link to get correct date format
// throws ParseException
Date date = new SimpleDateFormat("dd-MM-yyyy").parse(bdate);
Class SimpleDateFormat API
Now in prepared statement set them as date like shown below. As your table structure allows date in table.
query.setDate(2, date);
Now you still want to set null to that column then you can use and tell your query to set null by using following format in prepared statement.
query.setNull(2, java.sql.Types.DATE);
OR
query.setDate(2, null);
setNull API
Mapping of java.sql.Types to SQL types
I think this will solve your issue.
You need to change how you are passing parameters to you prepared statement
It should be something like below. And datum and bdatum should be of type Date. If you do not use what types are defined in your db you could put pass invalid data to your sql which would cause exceptions.
query.setDate(1, datum);
query.setDate(2, bdatum);
query.setInt(3, speler[0]);
query.setInt(4, toernooi[0]);
I suspect your bdatum variable contains an empty string. If you want to insert a SQL null, you need to pass in null, not empty string. (When I tried this on my machine with a similar insert, I got an "Incorrect date value" when trying to insert an empty string, but not with a null.)
if ("".equals(bdatum))
bdatum = null;
ps.setString(2, bdatum);
When you pass in a string in JDBC for a date value, MySQL will try to parse it, but empty string ("") is not a valid value. This works similarly to if you tried to do an insert with a date literal:
INSERT INTO `some_table` (`some_nullable_date_column`) VALUES ('2000-01-01') -- this works
INSERT INTO `some_table` (`some_nullable_date_column`) VALUES (NULL) -- this works
INSERT INTO `some_table` (`some_nullable_date_column`) VALUES ('') -- this fails
As an aside, passing in a string for a date value is semantically wrong and possibly less robust than parsing the string to a Date object before passing it to the PreparedStatement.