How to use bind variables for date literals? - sql

Consider the following SQL
SELECT * FROM employee WHERE dob = DATE '1980-05-15'
I need to rewrite the query to get rid of the hard coded values and use bind variables instead. So, my rewritten query looks like this
SELECT * FROM employee WHERE dob = DATE :dateOfBirth
However, the query doesn't work. I've tried all possible formats (1980-05-15, 15-MAY-80, 15-MAY-1980) for :dateOfBirth variable, without any luck. I always get ORA-00936: missing expression error.
Note 1: I'm aware of to_date() function that can solve my issue, but I can't use that because the query originates from a different system on which I don't have any control over.
Note 2: DD-MON-RR is the nls_date_format in my database as specified in nls_session_parameters & nls_database_parameters

You can't, you need to to_date it:
SELECT * FROM employee WHERE dob = to_date ( :dateOfBirth, '<fmt>' );

Related

Using Where Clause with Dates When Reading SQL Query in R

I am attempting to query an Oracle datebase from R using the SQL function found here.
When I complete an easy query, such as
'SELECT * FROM TABLE_1'
the query executes fine. However, when I add a conditional date statement to the query, such as
'SELECT * FROM TABLE_1 WHERE START_DT BETWEEN '01-JUL-2018' AND '30-JUN-2019'
I get the following error message:
Error in .oci.SendQuery(conn, statement, data = data, prefetch =
prefetch, : ORA-00904: "30-JUN-2019": invalid identifier
Any idea how I can fix this?
The exact error appears to be that you didn't escape the single quotes you placed around the date literals in your R query string. But, fixing that still leaves the problem that your date literals are invalid for Oracle. I recommend using this:
sql <- "SELECT * FROM TABLE_1 WHERE START_DT BETWEEN DATE '2018-07-01' AND DATE '2019-06-30'"
You could also use the TO_DATE function, e.g. TO_DATE('01-JUL-2018', 'DD-MON-YYYY'), but this is a bit harder to read than using the DATE keyword.

Concurrent program parameter of date type gave error ORA-01843: not a valid month

I have 2 parameters in my report Query of datatype date, I have selected the fnd_standard_date as value set, here is my query
Select ordered_date, order_number, customer_id
From order_tbl xx
Where NVL(:P_ORDER_NUMBER, xx.order_number) = xx.order_number
and xx.ordered_date between NVL(trunc(TO_DATE(:P_FROM_DATE, 'YYYY/MM/DD HH24:MI:SS')), xx.ORDERED_DATE) and NVL(trunc(TO_DATE(:P_TO_DATE, 'YYYY/MM/DD HH24:MI:SS'), xx.ORDERED_DATE)
AND NVL(:P_CUSTOMER, xx.customer_id) = xx.customer_id>
In SQLDeveloper the result is ok, but in Oracle apps, I am facing
java.sql.SQLDataException: ORA-01843: not a valid month
What value set can I use for this parameter?
And what format can I pass?
If your parameters are already DATEs as you say, then you should not be calling TO_DATE() for them. That will do an implicit conversion of the date to a string using the session's NLS_DATE_FORMAT, and then try to convert that string back into a date using the format model you have specified.
That will work if NLS_DATE_FORMAT happens to match what you specified, but you should not rely on that being the case, and should not do implicit conversions; and you're doing more work than you need to anyway.
So just simplify it to:
Select ordered_date, order_number, customer_id
From order_tbl xx
Where NVL(:P_ORDER_NUMBER, xx.order_number) = xx.order_number
and xx.ordered_date between NVL(trunc(:P_FROM_DATE), xx.ORDERED_DATE)
and NVL(trunc(:P_TO_DATE), xx.ORDERED_DATE)
AND NVL(:P_CUSTOMER, xx.customer_id) = xx.customer_id>
If you're running it from SQL Developer with P_DATE_FROM and _TO declared as strings via the variable command, then you will need to use TO_DATE() of course. The two situations are not the same.
Thank you very much!
The problem is with xml publisher / ebs concurrent parameters, just did the following and solved.
used the canonical_to_date in query
Where trunc(xx.ordered_date) between NVL(trunc(fnd_date.canonical_to_date(:P_FROM_DATE)), xx.ORDERED_DATE) and NVL(trunc(fnd_date.canonical_to_date(:P_TO_DATE)), xx.ORDERED_DATE)
used the FND_STANDARD_DATE value set

Sql Query using 'Like' is giving results but using '=' does not returns any result in Oracle

The Query using LIKE :(This query when fired gives the desired result)
select * from catissue_audit_event where event_timestamp like '16-DEC-14'
But when using query with '=' results in an empty resultset
select * from catissue_audit_event where event_timestamp='16-DEC-14'
Here event_timestamp is of type Date
Strange thing is that the query runs for other dates such as:
select * from catissue_audit_event where event_timestamp='15-DEC-14'
What can be the issue? I already checked for leading and trailing spaces in the data
Output after running the first query:
In Oracle a DATE (and of course a TIMESTAMP) column contains a time part as well.
Just because your SQL client is hiding the time, doesn't mean it isn't there.
If you want all rows from a specific day (ignoring the time) you need to use trunc()
select *
from catissue_audit_event
where trunc(event_timestamp) = DATE '2014-12-16';
Be aware that this query will not use an index on the event_timestamp column.
You should also not rely on implicit data type conversion as you do with the expression event_timestamp = '16-DEC-14. That statement is going to fail if I run it from my computer because of different NLS settings. Always use a proper DATE literal (as I have done in my statement). If you don't like the unambiguous ISO date, then use to_date():
where trunc(event_timestamp) = to_date('16-12-2014', 'dd-mm-yyyy');
You should avoid using month names unless you know that all environments (which includes computers and SQL clients) where your SQL statement is executed are using the same NLS settings. If you are sure, you can use e.g. to_date('16-DEC-14', 'dd-mon-yy')
The reason why this is different is different to the solution to your issue.
The solution to your issue is to stop performing date comparisons by implicit conversion to a string. Convert your string to a date to perform a date comparison:
select * from catissue_audit_event where event_timestamp = date '2014-12-16'
I cannot stress this enough; when performing a date comparison only compare dates.
Your column EVENT_TIMESTAMP is being implicitly (this is bad) converted to a date in accordance with your NLS_DATE_FORMAT, which you can find as follows:
select * from nls_session_parameters
This governs how date-data is displayed and implicitly converted. The reason why LIKE works and and = doesn't is because your NLS_DATE_FORMAT is masking additional data. In other words, your date has a time component.
If you run the following and then re-select the data from your table you'll see the additional time component
alter session set nls_date_format = 'yyyy-mm-dd hh24:mi:ss'
Thus, if you want all the data for a specific date without constraint on time you'll need to remove the time component:
select * from catissue_audit_event where trunc(event_timestamp) = date '2014-12-16'
have you tried matching the event_timestamp format example: DD-MMM-YY with the date that you are passing?

Oracle: between dates statement gives error 'not valid month'

I'm not sure what I'm doing wrong here. I'm trying to build an oracle query that I will be executing from my php project via oci. I need to select all records between a specific date range.
In trying to get the syntax down, I wrote out this test query:
SELECT * FROM SHIPPED
WHERE user_seq_id = 381 AND
LOT_DATE BETWEEN TO_DATE('05/27/2014', 'MM/DD/YYYY')
AND TO_DATE('06/03/2014','MM/DD/YYYY');
This syntax seems like it should work but it's not. I'm definitely not an oracle developer so I'm positive I"m misunderstanding something. When I've looked at similar posts I haven't found anything that would point to what I'm doing wrong.
This is a rather tricky error. The problem would occur if LOT_DATE were stored as a character string rather than a date -- and the string contained invalid data.
By explicitly converting the right hand side of the comparison to dates, the comparison is attempted by converting the field to a date. And there is an error.
The fix is to fix the data in the field. if something is in a field called "date", then it should probably have a date data type.
For identifying unsupported string value for date - You can create a PL/SQL function which accepts string and validate for correct date format, sample of function:
CREATE OR REPLACE FUNCTION VERIFY_DATE(v_date IN VARCHAR2) RETURN NUMBER IS
v_date1 DATE;
BEGIN
select to_date(v_date) into v_date1 from dual;
RETURN 1;
Exception WHEN Others THEN
RETURN 0;
END;
Now, identify rows which are having invalid string value for which you should correct to run your query:
select * from
(
select VERIFY_DATE(LOT_DATE) DateVerified,s.* from SHIPPED s
)
where
DateVerified=0

ORA-01843 not a valid month- Comparing Dates

I have a problem when try to select data from a table filtering by date.
For example:
SELECT * FROM MYTABLE WHERE MYTABLE.DATEIN = '23/04/49';
The Oracle Error is:
Informe de error:
Error SQL: ORA-01843: mes no válido
01843. 00000 - "not a valid month"
*Cause:
*Action:
Probably the source data of table is corrupted, in this case:
How can i solve this problem?
Can I change this dates for null?
The results of this select, select * from nls_session_parameters; , is:
PARAMETER VALUE
------------------------------ ----------------------------------------
NLS_LANGUAGE SPANISH
NLS_TERRITORY SPAIN
NLS_CURRENCY ¿
NLS_ISO_CURRENCY SPAIN
NLS_NUMERIC_CHARACTERS ,.
NLS_CALENDAR GREGORIAN
NLS_DATE_FORMAT DD/MM/RR
NLS_DATE_LANGUAGE SPANISH
NLS_SORT SPANISH
NLS_TIME_FORMAT HH24:MI:SSXFF
NLS_TIMESTAMP_FORMAT DD/MM/RR HH24:MI:SSXFF
NLS_TIME_TZ_FORMAT HH24:MI:SSXFF TZR
NLS_TIMESTAMP_TZ_FORMAT DD/MM/RR HH24:MI:SSXFF TZR
NLS_DUAL_CURRENCY ¿
NLS_COMP BINARY
NLS_LENGTH_SEMANTICS BYTE
NLS_NCHAR_CONV_EXCP FALSE
You should use the to_date function (oracle/functions/to_date.php
)
SELECT * FROM MYTABLE WHERE MYTABLE.DATEIN = TO_DATE('23/04/49', 'DD/MM/YY');
You are comparing a date column to a string literal. In such a case, Oracle attempts to convert your literal to a date, using the default date format.
It's a bad practice to rely on such a behavior, as this default may change if the DBA changes some configuration, Oracle breaks something in a future revision, etc.
Instead, you should always explicitly convert your literal to a date and state the format you're using:
SELECT * FROM MYTABLE WHERE MYTABLE.DATEIN = TO_DATE('23/04/49','MM/DD/YY');
If you don't need to check exact timestamp, use
SELECT * FROM MYTABLE WHERE trunc(DATEIN) = TO_DATE('23-04-49','DD-MM-YY');
otherwise, you can use
SELECT * FROM MYTABLE WHERE DATEIN = TO_DATE('23-04-49 20:18:07','DD-MM-YY HH24:MI:SS');
Here, you use hard code date,if you directly compare then you must use DD-MM-YY HH24:MI:SS else you might get ORA-01849: hour must be between 1 and 12.
I know this is a bit late, but I'm having a similar issue. SQL*Plus executes the query successfully, but Oracle SQL Developer shows the ORA-01843: not a valid month error.
SQL*Plus seems to know that the date I'm using is in the valid format, whereas Oracle SQL Developer needs to be told explicitly what format my date is in.
SQL*Plus statement:
select count(*) from some_table where DATE_TIME_CREATED < '09-12-23';
VS
Oracle SQL Developer statement:
select count(*) from some_table where DATE_TIME_CREATED < TO_DATE('09-12-23','RR-MM-DD');
Just in case this helps, I solved this by checking the server date format:
SELECT * FROM nls_session_parameters WHERE parameter = 'NLS_DATE_FORMAT';
then by using the following comparison (the left field is a date+time):
AND EV_DTTM >= ('01-DEC-16')
I was trying this with TO_DATE but kept getting an error. But when I matched my string with the NLS_DATE_FORMAT and removed TO_DATE, it worked...
In a comment to one of the answers you mention that to_date with a format doesn't help. In another comment you explain that the table is accessed via DBLINK.
So obviously the other system contains an invalid date that Oracle cannot accept. Fix this in the other dbms (or whatever you dblink to) and your query will work.
Having said this, I agree with the others: always use to_date with a format to convert a string literal to a date. Also never use only two digits for a year. For example '23/04/49' means 2049 in your system (format RR), but it confuses the reader (as you see from the answers suggesting a format with YY).
If the source date contains minutes and seconds part, your date comparison will fail.
you need to convert source date to the required format using to_char and the target date also.
If you are using command line tools, then you can also set it in the shell.
On linux, with a sh type shell, you can do for example:
export NLS_TIMESTAMP_FORMAT='DD/MON/RR HH24:MI:SSXFF'
Then you can use the command line tools and it will use the specified format:
/path/to/dbhome_1/bin/sqlldr user/pass#host:port/service control=table.ctl direct=true
Try using:
SELECT *
FROM MYTABLE
WHERE MYTABLE.DATEIN is not null
AND MYTABLE.DATEIN = '23/04/49';
Use the month as a string.
Example:
(12-Apr-2002) or (12-April-2002)
Although the answers using TO_DATE are correct, I prefer to use the ANSI SQL format for dates:
DATEIN = DATE '1949-04-23'
It works in Oracle and other DBMS ANSI SQL compliant. This is specially important if your application is DBMS agnostic.
Try alter session set NLS_DATE_FORMAT='DD/MM/YY'; -- or whatever format you want
I faced the same problem, on PROD, all the code were already in this format, but on preprod, it's not set,
So this means you change the default date format used by oracle
ALTER session set NLS_LANGUAGE=’AMERICAN’;