PreparedStatement and 'null' value in WHERE clause - jdbc

I am using PrepareStatement and BatchUpdate for executimg a UPDATE query. In for loop I create a Batch. At end of loop I execute batch.
Above logic works fine if SQL query used in PrepareStatement does not have null values in WHERE claues.
Update Statement fails if there is null value in WHERE clasue.
My code looks something like this,
connection = getConnection();
PreparedStatement ps = connection.prepareStatement(
"UPDATE TEST_TABLE SET Col1 = true WHERE Col2 = ? AND Col3 = ?");
for (Data aa : InComingData){
if(null == aa.getCol2()){
ps.setNull(1, java.sql.Types.INTEGER);
}
else {
ps.setInteger(1,aa.getCol2())
}
if(null == aa.getCol3()) {
ps.setNull(2, java.sql.Types.INTEGER);
}
else {
ps.setInteger(2,aa.getCol3())
}
ps.addBatch();
}
ps.executeBatch();
connection.commit();
Any help would be appreciated.

If you do not wish to generate SQL dynamically, you may use NVL on all the nullable columns in your WHERE clause to convert null into some value that the column will never contain; and while setting the bind variables in Statement just convert null to the same value used in NVL function. For example,
String sql = "UPDATE TEST_TABLE SET Col1 = true
WHERE NVL(Col2, -1) = ? AND NVL(Col3, -1) = ?";
And in Statement:
ps.setInt(1, aa.getCol2() == null ? -1 : aa.getCol2().intValue());
ps.setInt(2, aa.getCol3() == null ? -1 : aa.getCol3().intValue());

That's because in SQL, something = null is always false, even if something is null. To compare a column with null, you must use where col2 is null, instead of where col2 = null.

Related

Oracle decode null date variable

I have a query as part of a larger function and having trouble making DECODE work with null dates. This portion of my query is in the WHERE condition of the query:
NVL(datRunDate,SYSDATE)
BETWEEN NVL(EFFECTIVE_DATE,NVL(datRunDate,SYSDATE-1))
AND DECODE(STOP_DATE, NULL, NVL(datRunDate,SYSDATE + 1), STOP_DATE + (59/86400))
Where:
datRunDate DATE
EFFECTIVE_DATE DATE
STOP_DATE DATE
My issue is that the STOP_DATE is typically NULL and the DECODE doesn't work. Any ideas / help to work around this is appreciated.
EDIT
Adding some sample data as suggested:
datRunDate 2016-01-14 06:41:54
EFFECTIVE_DATE 2013-04-01 09:53:00
STOP_DATE NULL
EDIT2
Adding the entire query text here as the problem probably lies here. Note: I have replaced the variables manually. These variables are populated before this query with simple SELECT INTO statements.
datRunDate DATE;
SELECT COMP_DATE INTO datRunDate where IDL_SEQ = 2320;
SELECT EFFECTIVE_DATE, STOP_DATE from IDLS where IDL_SEQ = 2320;
DESC IDL_TABLE
DESC SCHEDULES COMP_DATE = datRunDate
...
SELECT I.IDL_SEQ
FROM IDLS I, IDL_CMPS IC
WHERE I.RECORD_TYPE = 'M'
AND IC.IDL_SEQ = I.IDL_SEQ
AND IC.CMP = '71-43-2'
AND I.METHOD = 'N0'
AND ((I.RUN_INSTRU = '') OR (I.RUN_INSTRU IS NULL))
AND ((I.PREP_METHOD = 'K9') OR (I.PREP_METHOD IS NULL))
AND ((I.MATRIX = 'SO') OR (I.MATRIX IS NULL))
AND ((I.COLUMN_ID = '') OR (I.COLUMN_ID IS NULL))
AND COALESCE(datRunDate, SYSDATE)
BETWEEN COALESCE(I.EFFECTIVE_DATE, datRunDate, SYSDATE - 1)
AND COALESCE(I.STOP_DATE + (59/86400), datRunDate, SYSDATE + 1)
AND ((I.SAMPLE_TYPE = 'SAMPLE') OR (SAMPLE_TYPE IS NULL))
AND ((I.CUST_SAMPLE_ID = 'SB-7') OR (CUST_SAMPLE_ID IS NULL))
AND ((I.LOCATION = '') OR (LOCATION IS NULL))
AND (
(OTHER_CRITERIA IS NOT NULL AND 404324 IS NOT NULL AND OTHER_CRITERIA = 'P|'||404324) OR
(OTHER_CRITERIA IS NOT NULL AND 28936 IS NOT NULL AND OTHER_CRITERIA = 'R|'||28936) OR
(OTHER_CRITERIA IS NOT NULL AND 'ECO' IS NOT NULL AND OTHER_CRITERIA = 'C|'||'ECO') OR
(OTHER_CRITERIA IS NULL));
Now when I run this I get: ORA-00932: inconsistent datatypes: expected CHAR got DATE
I would write this as:
COALESCE(datRunDate, SYSDATE) BETWEEN COALESCE(EFFECTIVE_DATE, datRunDate, SYSDATE - 1) AND
COALESCE(STOP_DATE + (59/86400), dateRunDate, SYSDATE + 1)
The ANSI standard function COALESCE() is simpler than using NVL() and DECODE() (which should be obsoleted anyway).

ORACLE SQL // IF ELSE?

I got a small problem in my SQL code :
LEFT JOIN
(SELECT *
FROM pilotage_usines_valeurs
WHERE c_indicateur IS NOT NULL) v
ON v.id_usine = d.id_usine
AND v.annee = 2015
AND V.MOIS = D.MOIS
AND V.C_INDICATEUR = pi1.c_indicateur
Sometime pi1.c_indicateur is null. How can i test it and write the line if pi1.c_indicateur is not null don't write it if pi1.c_indicateur is null ?
If I understand your intentions correctly I suggest you add the NOT NULL condition to the ON clause:
LEFT JOIN (SELECT *
FROM PILOTAGE_USINES_VALEURS
WHERE C_INDICATEUR IS NOT NULL) v
ON v.ID_USINE = d.ID_USINE
AND v.ANNEE = 2015
AND v.MOIS = D.MOIS
AND v.C_INDICATEUR = pi1.C_INDICATEUR
AND pi1.C_INDICATEUR IS NOT NULL
NVL is used to substitute null value by something else. Syntax is similar to
NVL (FIELD_TO_BE_TESTED_FOR_NULL, VALUE_IF_NULL);
Option 1:
Replace pi1.c_indicateur when null with some value so that V.C_INDICATEUR will never be equal to that value.
AND V.C_INDICATEUR = NVL(pi1.c_indicateur,'IMPOSSIBLE VALUE FOR V.C_INDICATEUR ');
Option 2:
Replace V.C_INDICATEUR with some value if null and replace pi1.c_indicateur with some other value, so that both will never match if NULL.
AND (V.C_INDICATEUR,'ABC') = NVL(pi1.c_indicateur,'DEF');

If condition with select query in oracle

How to Use IF Condition with Select Query in Oracle. Please suggest
IF (SELECT ptr_forecast_dt from ptr_details WHERE ptr_line_id = prmptr_line_id AND ptr_actual_dt IS NULL) IS NOT NULL THEN
SELECT ptr_forecast_dt INTO Forcast_dt from ptr_details WHERE ptr_line_id = prmptr_line_id AND ptr_actual_dt IS NULL;
END IF;
You can simply add another condition in the WHERE clause, as below:
SELECT ptr_forecast_dt
INTO Forcast_dt
FROM ptr_details
WHERE ptr_line_id = prmptr_line_id
AND ptr_actual_dt IS NULL
AND ptr_forecast_dt IS NOT NULL;
If you want to insert an alternate value if ptr_forecast_dt is NULL, then you can use the NVL function, as below:
SELECT NVL(ptr_forecast_dt, TO_DATE('01/01/2014', 'MM/DD/YYYY'))
INTO Forcast_dt
FROM ptr_details
WHERE ptr_line_id = prmptr_line_id
AND ptr_actual_dt IS NULL;

Case When Variable Is null then is null

In my sql query I'm having this where condition:
WHERE
parentID = prj.parent_id
and mandator_fk = mandator_id
The variable parentID is null as default.
If this variable is null the WHERE condition should be parentID is null and not like in the query above (parentID = prj.parent_id). If this variable is filled the WHERE condition should be parentID = prj.parent_id.
How can I perform this with only one sql query?
EDIT: its inside a function, thats why I would have only one sql query for this.
This is not working I know that, but this is like what I need:
WHERE
CASE
WHEN parentID is null THEN parentID is null
ELSE
parentID = prj.parent_ID
END
and mandator_fk = mandator_id
TIA
frgtv10
Seems you want to join on nulls, so you'll need to convert them first. Try this:
where
NVL(parentId, 0) = NVL(prj.parent_id, 0)
and ...
I'm not sure if NVL() function is surgable, so here is another way to write the condition:
WHERE
( parentID = prj.parent_id
OR parentID IS NULL AND prj.parent_id IS NULL
)
AND mandator_fk = mandator_id

If statement within Where clause

I am working with a query which contains "IF" statements within a "WHERE" clause. But PL\SQL Developer is giving some errors while executing it. Can anyone please help me with the correct query? Here is the query:
SELECT t.first_name,
t.last_name,
t.employid,
t.status
FROM employeetable t
WHERE IF status_flag = STATUS_ACTIVE then t.status = 'A'
IF status_flag = STATUS_INACTIVE then t.status = 'T'
IF source_flag = SOURCE_FUNCTION then t.business_unit = 'production'
IF source_flag = SOURCE_USER then t.business_unit = 'users'
AND t.first_name LIKE firstname
AND t.last_name LIKE lastname
AND t.employid LIKE employeeid;
I receive the error "ORA-00920: invalid relational operator".
Placing brackets around status_flag = STATUS_ACTIVE results in error "ORA-00907: missing right parenthesis"
CASE might help you out:
SELECT t.first_name,
t.last_name,
t.employid,
t.status
FROM employeetable t
WHERE t.status = (CASE WHEN status_flag = STATUS_ACTIVE THEN 'A'
WHEN status_flag = STATUS_INACTIVE THEN 'T'
ELSE null END)
AND t.business_unit = (CASE WHEN source_flag = SOURCE_FUNCTION THEN 'production'
WHEN source_flag = SOURCE_USER THEN 'users'
ELSE null END)
AND t.first_name LIKE firstname
AND t.last_name LIKE lastname
AND t.employid LIKE employeeid;
The CASE statement evaluates multiple conditions to produce a single value. So, in the first usage, I check the value of status_flag, returning 'A', 'T' or null depending on what it's value is, and compare that to t.status. I do the same for the business_unit column with a second CASE statement.
You can't use IF like that. You can do what you want with AND and OR:
SELECT t.first_name,
t.last_name,
t.employid,
t.status
FROM employeetable t
WHERE ((status_flag = STATUS_ACTIVE AND t.status = 'A')
OR (status_flag = STATUS_INACTIVE AND t.status = 'T')
OR (source_flag = SOURCE_FUNCTION AND t.business_unit = 'production')
OR (source_flag = SOURCE_USER AND t.business_unit = 'users'))
AND t.first_name LIKE firstname
AND t.last_name LIKE lastname
AND t.employid LIKE employeeid;

Resources