SQL command not properly ended in Python OracleSQL - sql

I'm having some trouble with SQL code that works when I run it in DBeaver, but when I execute it with cx_Oracle it comes up with the error of:
cx_Oracle.DatabaseError: ORA-00933: SQL command not properly ended
The python code is good, but I'm not much of a SQL programmer, so maybe someone can look to see if there is any obvious coding errors. It's just weird that the code works in DBeaver but not with cx_Oracle.
Here is the code:
WITH MDVC_LP_HEADER_DATA AS
(select
distinct trunc(lh.start_time) as "Consumption Date",
md.client_co_account_id as "NMI",
md.MR_MDVC_NUMBER as "Meter",
lh.mdvc_id,
lh.header_id,
lh.lp_attribute_id,
lh.entry_date,
lh.rec_status,
cm.register_id as "Register",
nvl(st.crm_register_id, st.register_id) as "Register_ID",
st.stream_id as "Stream"
from WACSMDMS.mdvc_lp_header lh,
WACSMDMS.metering_device md,
WACSMDMS.lp_attribute_config c,
WACSMDMS.ozwave_register_channel_map cm,
WACSMDMS.nem12_subs_members st
where 1=1
and md.mdvc_id = lh.mdvc_id
and lh.entry_date between to_date('26-JUL-2021') + 1 and to_date('2-AUG-2021')+1
and lh.rec_status in ('VFD', 'VDD')
and lh.lp_attribute_id = c.lp_attribute_id
and cm.channel_id = c.channel_id
and st.nmi = md.client_co_account_id
and st.meter_number = md.MR_MDVC_NUMBER
and st.register_id = cm.register_id
and st.stream_id != 'X'
and st.subscriber_acr = 'EVERGY'
),
mdvc_lp_dta as
(
select
distinct
lh."Consumption Date" as "Consumption Date",
lh."NMI" as "NMI",
lh."Meter" as "Meter",
lh.mdvc_id as "MDVC_ID",
lh.lp_attribute_id,
lh.rec_status,
lp.comments as "Reason Description",
lp.DATA_ID, lp.STATUS, lp.reason_code, lh."Register", lh."Stream" , lh."Register_ID"
from WACSMDMS.mdvc_lp_data lp, WACSMDMS.MDVC_LP_HEADER_DATA lh
where 1=1
and lh.mdvc_id = lp.mdvc_id
and lh.lp_attribute_id = lp.lp_attribute_id
and lh.header_id = lp.header_id
and lp.end_time > lh.entry_date -1
and lp.end_time <= lh.entry_date
),
base as
(select
lp."Consumption Date",
lp."NMI",
lp."Meter",
lp."MDVC_ID",
lp."Reason Description",
lp.DATA_ID,
lp.STATUS,
lp.reason_code,
NVL(a.GUI_DISPLAY_DESC,a.description) subs_type,
CASE
WHEN orcd.reason_code IS NOT NULL THEN orcd.reason_code||' ('||orcd.reason_description|| ')'
ELSE NULL
END AS "Reason Code",
CASE
WHEN lp.DATA_ID = 1 AND lp.STATUS IS NOT NULL THEN 'Substituted'
ELSE
CASE WHEN lp.DATA_ID = 0 THEN 'Actual'
ELSE NVL(LDS.GUI_DISPLAY_DESC,LDS.DESCRIPTION)
END
END AS read_data_id,
NVL(a.GUI_DISPLAY_DESC,a.description) AS read_data_status,
lp.rec_status as rec_status2,
lds.dataid_status_ind,
a.dataid_status_ind dataid_status_ind2, lp."Register", lp."Stream", lp."Register_ID"
from
WACSMDMS.mdvc_lp_dta lp,
WACSMDMS.lp_data_status a,
WACSMDMS.lp_data_status lds,
WACSMDMS.ozwave_reason_code_dim orcd
where 1=1
and a.mr_gateway_id IS NULL
AND a.dataid_status_ind(+) = 'S'
AND a.file_data_status_id(+) = lp.status
AND lp.data_id = lds.file_data_status_id (+)
AND lds.mr_gateway_id (+) IS NULL
AND lds.dataid_status_ind (+) = 'D'
and lp.reason_code =orcd.reason_code (+)
)
select "Consumption Date","NMI","Meter","Register","MDVC_ID",
( case when subs_type is null and read_data_id = 'Churn Substitution' and
read_data_status is null then 'Type 19 Zero' else subs_type end ) as "Substitution Type",
"Reason Code","Reason Description",read_data_id as "Data Quality", "Stream", "Register_ID"
from base
where 1=1
and ( ( base.read_data_id = 'Churn Substitution' and base.read_data_status is null ) or
( base.rec_status2 = 'VDD' and base.subs_type is not null and base.read_data_id <> 'Final Substitution' ))
order by 1,2,3,4;

Query itself looks OK (as you said, it works in DBeaver). Maybe it is that Python doesn't "like" closing statement terminator (semi-colon at the very end of the query) - try to remove it.
Apart from that, I'd suggest you not to rely on Oracle's guessing date format. Instead of TO_DATE ('26-JUL-2021'), use TO_DATE ('26-JUL-2021', 'DD-MON-YYYY') (i.e. always provide appropriate format mask). Note that MON can be tricky if database doesn't speak English (for example, it would fail in my database which speaks Croatian) so - it is safer to use e.g. TO_DATE ('26.07.2021', 'DD.MM.YYYY')

Related

GETTING ERROR-- ORA-00936:MISSING EXPRESSION for below query please help on this

SELECT CASE (SELECT Count(1)
FROM wf_item_activity_statuses_v t
WHERE t.activity_label IN ('WAITING_DISB_REQ',
'LOG_DDE',
'LOG_SENDBACK_DDE')
AND t.item_key IN(
SELECT r.i_item_key
FROM wf_t_item_xref r
WHERE r.sz_appl_uniqueid = '20400000988')
)
WHEN 0 THEN
(
delete
from t_col_val_document_uploaded p
WHERE p.sz_application_no = '20400000988'
AND p.sz_collateral_id = 'PROP000000000PRO1701'
AND p.i_item_key = '648197'
AND p.i_document_srno = '27' )
WHEN 1 THEN
(
DELETE
FROM t_col_val_document_uploaded p
WHERE p.sz_application_no = '20400000988'
AND p.sz_collateral_id = 'PROP000000000PRO1701'
AND p.i_document_srno = '28' )
ELSE NULL
END
FROM dual;
You need to recreate your query and make sure to follow the flow of the clauses properly, please check the next two links to get a better understanding :
[ORA-00936: missing expression tips]
How do I address this ORA-00936 error?
Answer: The Oracle oerr utility notes this about the ORA-00936 error:
ORA-00936 missing expression
Cause: A required part of a clause or expression has been omitted. For example, a SELECT statement may have been entered without a list of columns or expressions or with an incomplete expression. This message is also issued in cases where a reserved word is misused, as in SELECT TABLE.
Action: Check the statement syntax and specify the missing component.
The ORA-00936 happens most frequently:
1 - When you forget list of the column names in your SELECT statement.
2. When you omit the FROM clause of the SQL statement.
ora-00936-missing-expression
I hope this can help you.
You cannot use a simple select query like this. You have to use a PL/SQL block like below -
DECLARE NUM_CNT NUMBER := 0;
BEGIN
SELECT Count(1)
INTO NUM_CNT
FROM wf_item_activity_statuses_v t
WHERE t.activity_label IN ('WAITING_DISB_REQ',
'LOG_DDE',
'LOG_SENDBACK_DDE')
AND t.item_key IN(SELECT r.i_item_key
FROM wf_t_item_xref r
WHERE r.sz_appl_uniqueid = '20400000988');
IF NUM_CNT = 0 THEN
delete
from t_col_val_document_uploaded p
WHERE p.sz_application_no = '20400000988'
AND p.sz_collateral_id = 'PROP000000000PRO1701'
AND p.i_item_key = '648197'
AND p.i_document_srno = '27';
ELSIF NUM_CNT = 1 THEN
DELETE
FROM t_col_val_document_uploaded p
WHERE p.sz_application_no = '20400000988'
AND p.sz_collateral_id = 'PROP000000000PRO1701'
AND p.i_document_srno = '28' )
END IF;
END;

Case expression with Boolean from PostgreSQL to SQL Server

I am translating a query from PostgreSQL to SQL Server. I didn't write the query in PostgreSQL and it's quite complicated for my knowledge so i don't understand every piece of it.
From my understand: we are trying to find the max version from p_policy and when insurancestatus = 7 or 14 / transactiontype = CAN, we compare two dates (whose format are BIG INT).
This is the PG Query:
SELECT *
FROM BLABLABLA
WHERE
pol.vnumber = (
SELECT MAX(pol1.vnumber)
FROM p_policy pol1
AND ( CASE WHEN pol1.insurancestatus IN (7,14)
or pol1.transactiontype IN ('CAN')
-- ('CAN','RCA')
THEN pol1.veffectivedate = pol1.vexpirydate
ELSE pol1.veffectivedate <> pol1.vexpirydate
END
)
AND pol1.vrecordstatus NOT IN (30,254)
etc.
I am used to have a where statement where I compare it to a value. I understand here from the Case statement we will have a boolean, but still that must be compared to something?
Anyway the main purpose is to make it work in SQL, but I believe SQL can't read a CASE statement where THEN is a comparison.
This is what I tried:
SELECT *
FROM BLABLABLA
WHERE pol.vnumber =
(
SELECT MAX(pol1.vnumber)
FROM p_policy pol1
WHERE sbuid = 4019
AND ( CASE WHEN pol1.insurancestatus IN (7,14)
or pol1.transactiontype IN ('CAN')
THEN CASE
WHEN pol1.veffectivedate = pol1.vexpirydate THEN 1
WHEN pol1.veffectivedate <> pol1.vexpirydate THEN 0
END
END
)
AND pol1.vrecordstatus NOT IN (30,254)
etc.
And then I get this error from SQL Server (which directly the last line of the current code - so after the double case statement)
Msg 4145, Level 15, State 1, Line 55
An expression of non-boolean type specified in a context where a condition is expected, near 'AND'.
Thank you !Let me know if it is not clear
I think you want boolean logic. The CASE expression would translate as:
(
(
(pol1.insurancestatus IN (7,14) OR pol1.transactiontype = 'CAN')
AND pol1.veffectivedate = pol1.vexpirydate
) OR (
NOT (pol1.insurancestatus IN (7,14) OR pol1.transactiontype = 'CAN')
AND pol1.veffectivedate <> pol1.vexpirydate
)
)
There are 2 main issues with your snippet, SQL Server-syntax-wise.
SELECT * FROM BLABLABLA WHERE
pol.vnumber = /* PROBLEM 1: we haven't defined pol yet; SQL Server has no idea what pol.vnumber is here, so you're going to get an error when you resolve your boolean issue */
(
SELECT MAX(pol1.vnumber)
FROM p_policy pol1
WHERE sbuid = 4019
AND ( CASE WHEN pol1.insurancestatus IN (7,14)
or pol1.transactiontype IN ('CAN')
THEN CASE
WHEN pol1.veffectivedate = pol1.vexpirydate THEN 1
WHEN pol1.veffectivedate <> pol1.vexpirydate THEN 0
END
END
) /* PROBLEM 2: Your case statement returns a 1 or a 0..
which means your WHERE is saying
WHERE sbuid = 4019
AND (1)
AND pol1.vrecordstatus NOT IN (30,254)
SQL Doesn't like that. I think you meant to add a boolean operation using your 1 or 0 after the parenthesis.
like this: */
= 1
AND pol1.vrecordstatus NOT IN (30,254)

where statement not allowed with group by function

I'm still a newbie with oracle, here I have a query that returns data like :
0.52
0.01
1
12
Desired result :
1
12
i have tried to do something like this in where part but it returns group function is not allowed here:
to_char((Max(start_time_timestamp+ (2/24))- p.port_statusmoddat), 999.999) >1
the query I'm working with:
select to_char((Max(start_time_timestamp+ (2/24))- p.port_statusmoddat), 999.999) as Diff
from ZAJBIREJ.UDR_ST r,directory_number d, CONTR_SERVICES_CAP C, MPUSNTAB SN, unicam.vw_contr_imsi_sim x, port p
where reject_reason_code = 'ISUBS'
and r.s_p_port_address = p.port_num (+)
and c.co_id = x.co_id (+)
and s_p_number_address = d.dn_num (+)
and d.dn_id =c.dn_id
AND C.SNCODE = sn.SNCODE
and C.MAIN_DIRNUM = 'X'
and c.cs_deactiv_date is null
and p.port_status = 'd'
AND nvl(C.cs_deactiv_date,'01-jan-2300') = (SELECT MAX(nvl(CA.cs_deactiv_date,'01-jan-2300'))
FROM CONTR_SERVICES_CAP CA, MPUSNTAB SNT
WHERE CA.DN_ID = D.DN_ID
AND SNT.SHDES = SN.SHDES)
group by reject_reason_code ,c.co_id, s_p_number_address,r.s_p_port_address,x.IMSI,p.port_status, p.port_statusmoddat
You need to use the HAVING clause:
group by reject_reason_code ,c.co_id, s_p_number_address, r.s_p_port_address,
x.IMSI, p.port_status, p.port_statusmoddat
having Max(start_time_timestamp+ (2/24))- p.port_statusmoddat >1
I also removed the redundant TO_CHAR as you want to test the number exceeds 1, not that a string of characters exceeds 1.

SQL Server switch data to display something else

I am trying to figure out I can change the data on the fly.
This is my current query:
SELECT [EmployeeTC_No] AS "Employee TC#"
,[pye_nlast] AS "Name Last"
,[pye_nfirst] AS "Name First"
,[Dept] AS "Department"
,[pye_status] AS "Active"
,[HireDate] AS "Hire Date"
,[SeparationDate] AS "Separation Date"
FROM [testing].[dbo].[testing]
In the column of pye_status the data comes in as "A" or "T" and I want it to be "1" or "0".
I have tried to add a case statement trying to do some kind of switch but nothing appears to even get me close.
CASE/WHEN should do the trick:
,CASE WHEN [pye_status] = 'A' THEN 1
WHEN [pye_status] = 'T' THEN 0
ELSE NULL END AS "Active"
Or a simple case/when will work too:
, CASE [pye_status]
WHEN 'A' THEN 1
WHEN 'T' THEN 0
ELSE NULL END AS "Active"
Use CASE expression or IIF() function as
CASE WHEN [pye_status] = 'A' THEN 1 ELSE 0 END AS [Active]
OR
IIF([pye_status] = 'A', 1, 0) AS [Active]

how to not display the NULL rows when using CASE When?

Here is a sample code:
select i.computerguid, i.logfile_enabled, i.logfile_logExtFileFlags
,Case
When
CHARINDEX('Date' , i.logfile_logExtFileFlags) = 0 or
CHARINDEX('Time' , i.logfile_logExtFileFlags) = 0 or
CHARINDEX('ClientIP', i.logfile_logExtFileFlags) = 0
Then 'Need these W3SVC fields enabled by default: Date, Time, ClientIP'
End as 'Reason'
,Case When i.logfile_enabled = 'true' Then 'Enabled the IIS log fields (via IIS MMC console) for site: ' + i.sitename End as 'Remediation'
from aspr_iissite i inner join aspr_root r on r.computerguid = i.computerguid
where i.logfile_enabled = 'true'
Here is a screen shot, I dont want to display the rows when 'Reason' is NULL:
Thank you
In your case, it is easiest to use a subquery:
select *
from (select i.computerguid, i.logfile_enabled, i.logfile_logExtFileFlags,
(Case When CHARINDEX('Date' , i.logfile_logExtFileFlags) = 0 or
CHARINDEX('Time' , i.logfile_logExtFileFlags) = 0 or
CHARINDEX('ClientIP', i.logfile_logExtFileFlags) = 0
Then 'Need these W3SVC fields enabled by default: Date, Time, ClientIP'
End) as Reason,
(Case When i.logfile_enabled = 'true'
Then 'Enabled the IIS log fields (via IIS MMC console) for site: ' + i.sitename
End) as Remediation
from aspr_iissite i inner join
aspr_root r
on r.computerguid = i.computerguid
where i.logfile_enabled = 'true'
) ir
where Reason is not null;
You could repeat the conditions in the case statement, but that makes the code harder to modify and maintain.
Two notes:
I think it is easier to follow the conditional logic using like: i.logfile_logExtFileFlags not like '%Date%'`. This is standard SQL.
Only use single quotes for string and date constants. Don't use them for column aliases.