I want to insert record in oracle11g database table. I am calling a stored procedure from java.
While executing stored procedure I am getting following error.
ORA-01843: not a valid month.
I am converting my date from String to Date in java as follows
date=new SimpleDateFormat("MM/dd/yyyy").parse(visitDate);
In my stored procedure I have following insert query
create or replace PROCEDURE CREATE_VISIT(p_visit_date varchar2)
insert into visit(VISIT_ID,visit_date) values
(frc.SEQ_VISIT.nextval,nvl(to_date(p_visit_date, 'mm/dd/yyyy hh:mi am'),
sysdate));
END CREATE_VISIT;
You have a String in Java. You convert that to a Date in Java. So far, presumably, so good.
Your procedure, however, accepts a varchar2. So at some point the Date that you constructed is being explicitly or implicitly cast to a varchar2. You don't say where that is happening (in Java or in PL/SQL) or whether it is being done explicitly or implicitly. If the conversion is being done implicitly in PL/SQL, then that would use your session's NLS_DATE_FORMAT which may be different for different sessions in the same database. In a default US-based install of the database and of the client, that would be DD-MON-RR.
Within your procedure, you then call to_date on the string that was passed in using an explicit format mask. If the string that is passed in is not in the format mm/dd/yyyy hh:mi am you'll either get an error or, worse, you'll get an incorrect result (this is the old question of whether the string 01/02/03 represents January 2, 2003 or February 1, 2003 or February 3, 1901).
If we guess that the Date in Java is being implicitly cast to a varchar2 using your session's default NLS_DATE_FORMAT of DD-MON-YYYY, then we can see why your to_date conversion would fail. If you have a Date of May 30, 2014, for example, that would be implicitly cast to the string "30-MAY-14". If you then try to cast that back to a date using to_date and a format mask of mm/dd/yyyy hh:mi am, Oracle would try to convert the 30 from your string to a month and raise an error since there is no 30th month.
Realistically, you should be using the proper data type throughout and you should be avoiding implicit casts like the plague. If you declare your procedure to take a date parameter, then you can pass a Date from your Java code and omit the to_date call in your procedure. The Date will be passed from Java to PL/SQL without needing to be converted to a varchar2 and then converted back to a date and you won't have to worry about making sure that all your format masks align throughout your code base.
create or replace PROCEDURE CREATE_VISIT(p_visit_date date)
AS
BEGIN
insert into visit(VISIT_ID,visit_date)
values (frc.SEQ_VISIT.nextval,nvl(p_visit_date, sysdate);
END CREATE_VISIT;
Related
I am making a Application Using Java. to pick the date i am using JCalender.jar file , and saving it in MYSQL . their date format does not match MYSQL date format . how can i change it
First of all, this isn't really a Swing question but more of a JDBC question. As Jon Skeet already pointed out, you shouldn't be trying to embed a formatted date into a SQL statement. Instead, you should use PreparedStatement's setDate() method, passing in an instance of java.sql.Date. Using that method will insulate you from details like what date format the database expects (you won't know or care) which in turn means that your code won't break if it's run against a database expecting a different format from the one that would work for you today.
I have to insert data(which is also containing the timezone, i.e. 2013-01-19 00:00:00 +0530) which is in String form and the datatype of the column is DATETIMEOFFSET. I have tried both java.util.date and sql.date but could not find any solution.
If you're using the Microsoft JDBC driver, you can use the DateTimeOffset class, constructing instances with the valueOf method.
You'll need to parse the value out into local time and offset (in order to pass the two parts separately) but that shouldn't be too bad using SimpleDateFormat. (The Z format specifier in SimpleDateTimeFormat will handle offsets like +0530.) Alternatively, use Joda Time which will make life easier still, as it will allow you to parse to a DateTime which lets you get the offset as well as the local time in one go. I would personally use Joda Time and create a method to convert from a DateTime to a DateTimeOffset.
I have a MySQL database in which one column is of type DATETIME and stores the values in IST (as my server time zone is IST).
I am getting a two string in EST from the user for which I need to match the date part in my database with that column.
I am using this query :
SELECT * FROM my_table where date(convert_tz(`myDate`,'+05:30','-05:00'))
between '2012-12-01' and '2012-12-02';
Note: That in my database mysql.time_zone is empty meaning I cannot use strings likeGMTetc in my query, they instructed me to download a package, but I don't want to download it, its fine for me to use00:05` as I will be framing my query in Java.
This query runs fine as I have hardcoded the the time zone offset (for EST.
But I am worried that this query will give wrong data for the dates that fall in Daylight timings i.e. for EDT.
So how do I get the time zone difference (meaning it should return '-05:00' for EST and '-04:00 for EDT ) so that I can directly use them when building my query string in java.
My query string may look like :
SELECT * FROM my_table where date(convert_tz(`myDate`,'+05:30','???'))
between '2012-12-01' and '2012-12-02';
where I want the value at ??? to be dynamically allocated using a prepared statement.
I am using Joda Time API, but don't have much knowledge of it, whether it has something that can return me the timezone offser for a given timezone string.
I would suggest that:
You start storing your values as UTC, for the sake of sanity. (The data shouldn't depend on the server's location.)
You compute the UTC value for the start/end points within Java (using a DateTime set in the right time zone, and then converting to UTC)
You pass the UTC start/end directly into the query via SQL parameters (don't include the values in the SQL text) and avoid the database doing any conversion
If you really, really can't change the database to use UTC instead, you should convert your "target timezone" values into IST values instead, and pass those to the database. Again, the query doesn't need to do conversion: convert your inputs beforehand instead.
So far, I have not found a clear answer to this.
I'd like to know what the equivalent is for a SQL type DATETIME and the java type, using a PreparedStatement.
I have found: http://www.java2s.com/Code/Java/Database-SQL-JDBC/StandardSQLDataTypeswithTheirJavaEquivalents.htm
But it states that SQL type "DATETIME" is the same as sql.date, but when looking at the SQL date docs (http://download.oracle.com/javase/7/docs/api/java/sql/Date.html), it says the time is truncated (all zeros).
What I want is to be able to specify a preparedStatement.setDateTime() or some sort.
The only other way I see is using a timestamp, but that would require me to change the column type, while I cannot imagine someone else never had this problem before?
Any hints?
Edit: I am using MYSQL.
The java.sql package has three date/time types:
java.sql.Date - A date only (no time part)
java.sql.Time - A time only (no date part)
java.sql.Timestamp - Both date and time
You want the last one: java.sql.Timestamp.
If you are using these types, you don't need to call a specific setter; just use:
java.util.Date date = new Date();
Object param = new java.sql.Timestamp(date.getTime());
// The JDBC driver knows what to do with a java.sql type:
preparedStatement.setObject(param);
The equivalent of MS SQL Server or MySQL DATETIME data type or Oracle DATE data type is java.sql.Timestamp.
In Java we have java.util.Date to handle both Date and Time values.
In SQL, you have commonly Dates (only dates), Time (only time) and DateTime/Timestamp (date and time).
In your Java program, usually you'll always have java.util.Date, so each time you're setting Dates/Times/DateTimes in PreparedStatements, always choose exactly which one you need, according to the database.
I had a similar problem with my Mysql having SQL date and locally in my app i only had Date
I solved like this
java.sql.Date dataStartSql = new java.sql.Date(start.getTime());
After that used the setDate normally, and I used a getTimestamp to retrive the first value.
where start is a Date object.
I have a SQL query that is returning an oracle Date object.
e.g.:
SELECT sysdate FROM DUAL
There is code currently that does the following:
String s = rs.getString("sysdate");
The problem is, this returns different date format on different environments (database is the same).
One environment will return:
2011-01-31 12:59:59.0
The other will return something weirder:
2011-1-31 12.15.32.0 (the time is separated by decimals)
Maybe this has something do with Locale... one machine is "English (Canada)" as reported by java, the other is "English (United States)".
What I'm interested in is, when the resultset transforms the date object into a string, where is that format coming from?
From Oracle's site:
At database connection time, the JDBC
Class Library sets the server
NLS_LANGUAGE and NLS_TERRITORY
parameters to correspond to the locale
of the Java VM that runs the JDBC
driver
So yes, the difference in the response is because the machines have a different locale specified. The correct solution should be to use getDate() or getTimestamp() or have the database server return the date as a string in a specific format as mentioned earlier.
I suggest not calling getString at all. The value you've asked for isn't a string, it's a date or timestamp. So call getDate or getTimestamp instead. (I don't know which of them is most appropriate offhand; it depends on the exact semantics of sysdate.)
If you then need to format it, you can do so in an appropriate manner.
Fundamentally, the fewer text conversions you introduce between your code and the database, the better. That's one reason to use parameterized queries - you don't have to care about how the database will parse numeric values or dates and times; you just provide the value. This is the same sort of thing, but in reverse.
In the 11g drivers the format seems to be hard-coded. Calling getString() on the result set ultimately calls this:
oracle.sql.TIMESTAMPTZ.toString(int year, int month, int day, int hours, int minutes, int seconds, int nanos, String regionName)
For dates, oracle.jdbc.driver.DateAccessor.getString() calls this with nanos=-1 and the result uses the format "yyyy-mm-dd HH:MM:SS"
For Timestamps, the format is "yyyy-mm-dd HH:MM:SS.S". Up to 9 digits of nanoseconds will be included.
Actually another interesting result is that this has changed significantly from 10g to 11g:
10.2.0.5.0:
select a DATE value and use getString to read it
2009-04-20 00:00:00.0
select a TIMESTAMP value and use getString to read it
2010-10-15.10.16. 16. 709928000
11.2.0.2.0:
select a DATE value and use getString to read it
2009-04-20 00:00:00
select a TIMESTAMP value and use getString to read it
2010-10-15 10:16:16.709928
Could your environments be using different versions of the Oracle JDBC drivers?
If you are really wanting it as a String you are better off using to_char in the query.
SELECT to_char(sysdate, 'MM/DD/YYYY') FROM DUAL;
This will be consistent.
Don't use getString, use getDate (or getTimestamp). That way it will won't rely on the database engine to convert it to a string.