i have several errors of PLS-00049 - plsql

cursor is there to check for eligibility in student. however i cant even compile the script as i keep getting several of error:
[Error] PLS-00049 (395: 46): PLS-00049: bad bind variable 'SORLCUR_PIDM'.
CURSOR C_ENSP IS
SELECT SFRENSP_ESTS_CODE
,STVESTS_DESC
FROM STVESTS,SFRENSP
WHERE SFRENSP_PIDM = :Sorlcur_PIDM
AND SFRENSP_TERM_CODE = :sorlcur_TERM_CODE
AND SFRENSP_KEY_SEQNO = :SORLCUR_KEY_SEQNO
AND STVESTS_CODE = SFRENSP_ESTS_CODE;
CURSOR C_ENSP_SECOND IS
SELECT 'Y'
FROM SORLCUR, SFRENSP
WHERE SORLCUR_PIDM = :Sorlcur_PIDM
and SORLCUR_PIDM = SFRENSP_PIDM
AND sorlcur_TERM_CODE = :sorlcur_TERM_CODE
AND sorlcur_TERM_CODE = SFRENSP_TERM_CODE
AND SORLCUR_CURRENT_CDE = 'Y'
AND SORLCUR_CACT_CODE = 'ACTIVE'
AND SORLCUR_LMOD_CODE = 'LEARNER'
AND SORLCUR_PRIORITY_NO = 2
AND SFRENSP_KEY_SEQNO = SORLCUR_KEY_SEQNO
AND SFRENSP_ESTS_CODE NOT IN ( 'W', 'X' , 'Z');
v_ENSP_SECOND VARCHAR2(1);
CURSOR c_cohort IS
SELECT chrt.sgrchrt_chrt_code
FROM sgrchrt chrt
WHERE sgrchrt_pidm = :sorlcur_pidm
AND NVL(chrt.sgrchrt_stsp_key_sequence,99999999) = :sorlcur_key_seqno
AND NVL(sgrchrt_term_code_eff,'~') = :stvterm_term_code;
CURSOR c_resd IS
SELECT sgbstdn_resd_code,stvresd_desc
FROM sgbstdn,stvresd
WHERE SGBSTDN_PIDM = :KEY_BLOCK.PIDM
AND SGBSTDN_TERM_CODE_EFF = :KEY_BLOCK.STVTERM_TERM_CODE
AND stvresd_code = sgbstdn_resd_code;
cursor c1 is
select skricas_cas_number,
skricas_cas_status
from skricas a
where a.SKRICAS_PIDM = :key_block.PIDM
and exists (select 'x' from sorlcur
where sorlcur_pidm = skricas_pidm
and sorlcur_seqno = skricas_lcur_seqno
and sorlcur_term_code = :key_block.stvterm_term_code)
and skricas_cas_status = 'USED'
and skricas_cas_exp_date = (select max(a1.skricas_cas_exp_date)
from skricas a1
where a1.skricas_pidm = a.skricas_pidm
and a1.skricas_cas_status = a.skricas_cas_status
);
-- TT06987 start
CURSOR get_JSopt_in IS
SELECT szrasop_opt_in
FROM szrasop
WHERE szrasop_pidm = :sorlcur.Sorlcur_PIDM
AND szrasop_term_code = :sorlcur.Sorlcur_TERM_CODE;
--- v_elig VARCHAR2(1);
CURSOR get_max_szrolps IS
SELECT MAX( SZROLPS_SEQ_NO)
FROM SATURN.SZROLPS
WHERE SZROLPS_PIDM = :sorlcur.Sorlcur_PIDM
AND SZROLPS_TERM_CODE = :sorlcur.Sorlcur_TERM_CODE;
v_max_stage szrolps.szrolps_seq_no%TYPE;
-- TT06987 end
BEGIN
IF :sorlcur_program IS NOT NULL THEN
:SORLCUR_SMRPCMT_TEXT := F_UOG_GET_COMMENT(:sorlcur_program, :sorlcur_term_code, 'PRGTIT');
OPEN C_ENSP;
FETCH C_ENSP INTO :SFRENSP_ESTS_CODE, :ESTS_DESCRIPTION;
CLOSE C_ENSP;
OPEN C_ENSP_SECOND;
FETCH C_ENSP_SECOND INTO v_ENSP_SECOND ;
IF C_ENSP_SECOND%NOTFOUND THEN
:secondary_prog := 'N';
ELSE
:secondary_prog := 'Y';
END IF;
CLOSE C_ENSP_SECOND;
END IF;
OPEN c_cohort;
FETCH c_cohort
INTO :ENTRY_COHORT;
CLOSE c_cohort;
OPEN c_resd;
FETCH c_resd
INTO :sgbstdn_resd_code,:stvresd_desc;
CLOSE c_resd;
SELECT STVATTS_DESC
INTO :mode_desc
FROM STVATTS
WHERE :sorlcur_mode_code = STVATTS.STVATTS_CODE
AND STVATTS.STVATTS_CODE LIKE 'M%';
select stvstyp_desc
into :sorlcur.styp_desc
from stvstyp
where :SORLCUR_STYP_CODE = stvstyp_code;
:sorlcur.SITE_DESC := gb_stvsite.f_get_description(:SORLCUR_SITE_CODE);
get_last_section_completed;
-- added by Mary for 5095
open c1;
fetch c1 into :cas_number,
:cas_status;
close c1;
-- TT06987 start
-- Student eligible??
IF hwzkimag.F_eligible_js (:sorlcur.Sorlcur_PIDM, :sorlcur.sorlcur_TERM_CODE)
THEN
:optin_elig := 'Y';
END IF;
--message(:optin_elig);message(:optin_elig);
IF NVL(:optin_elig,'XXX') = 'Y' THEN
OPEN get_max_szrolps;
FETCH get_max_szrolps
INTO v_max_stage;
CLOSE get_max_szrolps;
-- ELigible and got passed the opt in / opt out stage 7.
IF v_max_stage >= 7 THEN
OPEN get_JSopt_in;
FETCH get_JSopt_in
INTO :optin_yes;
CLOSE get_JSopt_in;
set_item_property('jsopt_message',visible,property_false);
-- Eligible but has not passed opt in / opt out stage 7.
ELSE
:jsopt_message := 'OLR not complete';
set_item_property('jsopt_message',visible,property_true);
END IF;
END IF;
-- TT06987 end

i've solved the problem. There were two errors in the below code. 1st is bad bind variable and 2nd is invalid identifier.
CURSOR C_ENSP IS
SELECT SFRENSP_ESTS_CODE
,STVESTS_DESC
FROM STVESTS,SFRENSP
WHERE SFRENSP_PIDM = :Sorlcur_PIDM
AND SFRENSP_TERM_CODE = :sorlcur_TERM_CODE
AND SFRENSP_KEY_SEQNO = :SORLCUR_KEY_SEQNO
AND STVESTS_CODE = SFRENSP_ESTS_CODE;
1st - i took out the colons on the columns name (e.g. :sorlcur_pidm to just sorlcur_pidm)
2nd - the table name sorlcur wasnt defined as i was calling table columns from 3 different tables.
-- The correct Syntax is below --
CURSOR C_ENSP IS
SELECT SFRENSP_ESTS_CODE
,STVESTS_DESC
FROM STVESTS,SFRENSP,SORLCUR
WHERE SFRENSP_PIDM = Sorlcur_PIDM
AND SFRENSP_TERM_CODE = sorlcur_TERM_CODE
AND SFRENSP_KEY_SEQNO = SORLCUR_KEY_SEQNO
AND STVESTS_CODE = SFRENSP_ESTS_CODE;

Related

Assign variable error if 'no rows selected' from query

I want to assign a variable from the sale of today by the menu item input. If the menu item has been sold yet, the variable should return 0. But it showed error instead:
Error report -
SQL Error: ORA-00905: missing keyword
00905. 00000 - "missing keyword"
This is my code:
SELECT SUM(Selling_Price*Quantity_Sold)
INTO V_Today_Sale
FROM Bill_Item BI, Bill B
WHERE BI.Bill_Number = B.Bill_Number AND
Menu_Item_Number = 1 AND
Bill_Date = sysdate AND
(NVL(Paid_YN,'N') = 'Y' OR NVL(Posted_YN,'N') = 'Y')
GROUP BY Menu_Item_Number
ORDER BY Menu_Item_Number;
If I remove the variable assignment
SELECT SUM(Selling_Price*Quantity_Sold)
FROM Bill_Item BI, Bill B
WHERE BI.Bill_Number = B.Bill_Number AND
Menu_Item_Number = 1 AND
Bill_Date = sysdate AND
(NVL(Paid_YN,'N') = 'Y' OR NVL(Posted_YN,'N') = 'Y')
GROUP BY Menu_Item_Number
ORDER BY Menu_Item_Number;
the result will be:
no rows selected
It's correct since no sale has been made for today yet. But how can I make the query return 0 instead of no rows selected so that I can assign it to the variable?
Are you running the query as shown to test without putting it in a block (using PL/SQL or Toad)? If so, you need to define the variable and structure like this, with a call to NVL() around the SUM() call so V_Today_Sale gets a value if both inputs to SUM() are NULL, and add an exception to catch the NO_DATA_FOUND condition that sets V_Today_Sale to 0 if the where clause conditions are not met:
SET SERVEROUTPUT ON;
DECLARE
V_Today_Sale number := 0;
BEGIN
SELECT NVL(SUM(Selling_Price*Quantity_Sold), 0)
INTO V_Today_Sale
FROM Bill_Item BI, Bill B
WHERE BI.Bill_Number = B.Bill_Number AND
Menu_Item_Number = 1 AND
Bill_Date = sysdate AND
(NVL(Paid_YN,'N') = 'Y' OR NVL(Posted_YN,'N') = 'Y')
GROUP BY Menu_Item_Number
ORDER BY Menu_Item_Number;
EXCEPTION
WHEN NO_DATA_FOUND THEN
V_Today_Sale :=0;
END;
DBMS_OUTPUT.PUT_LINE(V_Today_Sale);

SQL Developer - Bind Variable "prmMediaDate" is Not Declared

I am running the below PL/SQL block in SQL Developer. I am getting the error Bind Variable "prmMediaDate" is Not Declared. Someone please tell what is missing here:
set serveroutput on;
/* RUN the following as a SCRIPT (F5) */
DECLARE
VARIABLE prmMediaDate varchar2(10);
VARIABLE prmSchdDiv varchar2(2);
VARIABLE prmSchdStore varchar2(4);
VARIABLE prmSchdAssoc varchar2(8);
BEGIN
select '07/17/2017' into :prmMediaDate FROM DUAL;
select '91' into :prmSchdDiv FROM DUAL;
select '91916559' into :prmSchdAssoc FROM DUAL;
SELECT
NVL(ODIV,LA.LABORLEV1NM) AS "schd_division"
,NVL(OLOC,LA.LABORLEV4NM) AS "schd_location"
,NVL(OZONE,LA.LABORLEV5NM) AS "schd_dept"
,NVL(O.ORGPATHTXT,LA.LABORLEV1NM||'-'||LA.LABORLEV4NM||'-'||LA.LABORLEV5NM) AS "orgpath_of_shift"
,SA.SHIFTASSIGNID AS "shiftassignid"
,SA.SHIFTCODEID AS "shiftcodeid"
,SA.ENTEREDONDTM AS "assignmnt_add_dtm"
,ST.ENTEREDONDTM AS "assignmnt_edit_dtm"
,CASE WHEN ST.ACTIONTYPEID IS NULL THEN SA.ENTEREDONDTM ELSE ST.ENTEREDONDTM END as "last_action_dt"
,ST.ACTIONTYPEID AS "last_action_cd"
,AT.SHORTNM AS "last_action_descr"
,SA.DELETEDSW AS "deletedsw"
,TRUNC(SA.SHIFTSTARTDATE) AS "shift_start_date"
,TRUNC(SA.SHIFTENDDATE) AS "shift_end_date"
,TO_CHAR(SA.SHIFTSTARTDATE, 'HH24:MI:SS') AS "shift_start_time"
,TO_CHAR(SA.SHIFTENDDATE, 'HH24:MI:SS') AS "shift_end_time"
,CASE SA.SHIFTTYPEID WHEN 1 THEN 'WORK SHIFT' WHEN 2 THEN 'UNAVAIL' WHEN 3 THEN 'HIDE SHFT' WHEN 4 THEN 'SCHD PAYCD EDIT' WHEN 5 THEN 'HIDE WRK SHFT' WHEN 6 THEN 'HIDE UNAVAIL DAY' ELSE 'UNDEFINED' END as "segment"
,NVL(LA.LABORLEV2DSC,'9999') AS "sell_nonsell"
,P.PERSONNUM AS "assoc_nbr"
,SA.ENTEREDONDTM AS "entered_on_dtm"
from PERSON P
JOIN SHIFTASSIGNMNT SA on SA.EMPLOYEEID = P.PERSONID
JOIN COMBHOMEACCT HA on (P.PERSONID = HA.EMPLOYEEID)
LEFT JOIN SHFTSEGORGTRAN SSOT on SSOT.SHIFTASSIGNID = SA.SHIFTASSIGNID
LEFT JOIN ORGX O on O.ORGIDSID = SSOT.ORGIDSID
LEFT JOIN SHFTASGNMNTTRC ST on ST.SHIFTASSIGNID = SA.SHIFTASSIGNID
LEFT JOIN ACTIONTYPE AT on AT.ACTIONTYPEID = ST.ACTIONTYPEID
LEFT JOIN LABORACCT LA on (LA.LABORACCTID = HA.LABORACCTID)
WHERE
TRUNC(SA.SHIFTSTARTDATE) = :prmMediaDate
AND :prmMediaDate BETWEEN HA.EFFECTIVEDTM AND (HA.EXPIRATIONDTM - 1)
AND ((:prmMediaDate BETWEEN O.EFFECTIVEDTM AND (O.EXPIRATIONDTM - 1)) OR (O.EFFECTIVEDTM IS NULL))
AND (SSOT.SEGMENTNUM = 1 OR SSOT.SEGMENTNUM IS NULL)
AND (TRUNC(SSOT.SHIFTSTARTDATE) = :prmMediaDate OR SSOT.SHIFTSTARTDATE IS NULL)
AND SA.DELETEDSW = 0
AND (O.ODIV = :prmSchdDiv OR LA.LABORLEV1NM = :prmSchdDiv)
AND P.PERSONNUM = :prmSchdAssoc;
end;
/
I have tried multiple options like declaring VARIABLE as var, set Scan ON etc.. But it didnt help.
You need to understand that declare is pl/sql and variable is part of sql*plus program commands.
So to successfully execute that code you need to remove DECLARE command.
Set Serveroutput On;
/* RUN the following as a SCRIPT (F5) */
--DECLARE
Variable Prmmediadate Varchar2(10);
Begin
Select '07/17/2017' Into :Prmmediadate From Dual;
End;
/
print :Prmmediadate
PL/SQL procedure successfully completed.
PRMMEDIADATE
--------------------------------------------------------------------------------
07/17/2017

error in executing ODCIIndexStart() routine

I have a SEARCH package with several functions within that each return a pipelined table.
I am getting the following error:
ORA-29902: error in executing ODCIIndexStart() routine
ORA-06512: at "<SCHEMA_NAME>.SEARCH", line 955
ORA-06512: at "<SCHEMA_NAME>.SEARCH", line 216
ORA-06512: at line 1
ORA-06512: at "<SCHEMA_NAME>.SEARCH", line 1143
ORA-06512: at line 1
29902. 00000 - "error in executing ODCIIndexStart() routine"
*Cause: The execution of ODCIIndexStart routine caused an error.
*Action: Examine the error messages produced by the indextype code and
take appropriate action.
The command that I use to get this error is:
select * from table(search.user_search(10000003, '', 1, 20, 5, '', '', ''));
Here is the code around line 1143 of the SEARCH body:
FUNCTION USER_SEARCH(p_user_id number, p_search varchar2, p_page number, p_num_results number, p_concept_type_id number := null, p_standard_org varchar2 := null, p_standard_title varchar2 := null, p_standard_number varchar2 := null) RETURN SEARCH_RESULTS_TABLE AS
v_sub char(1);
v_rtn search_results_table := search_results_table();
v_user_id number;
v_page number;
v_num_results number;
v_query varchar2(4000);
cursor c_concept is
select * from table(search.concept_new(v_user_id, v_query, v_page, v_num_results, p_concept_type_id, p_standard_org, p_standard_title, p_standard_number));
BEGIN
v_page := p_page;
v_num_results := p_num_results;
v_query := p_search;
if (v_query = '') then
v_query := null;
end if;
-- ONLY DURING DEVELOPMENT
v_user_id := p_user_id;
if v_user_id = 0 then
v_user_id := 2;
end if;
if v_page = null then
v_page := 1;
end if;
if v_num_results = null then
v_num_results := -1;
end if;
select security.has_permission(p_user_id, 'UNLIMITED_RESULTS') into v_sub from dual;
case v_sub
when 'N' then
v_rtn := search.term(v_user_id, p_search, 1, 20, P_concept_type_id, p_standard_org, p_standard_title, p_standard_number);
when 'Y' then
for r_concept in c_concept loop -- line 1143
v_rtn.extend;
v_rtn(v_rtn.last) := search_results_row(r_concept.SCORE, r_concept.FROM_TABLE, r_concept.ID, r_concept.IN_DICTIONARY);
end loop;
end case;
return v_rtn;
END USER_SEARCH;
The code around line 216:
FUNCTION CONCEPT_NEW(p_user_id number, p_search varchar2, p_page number := 1, p_num_results number := -1, p_concept_type_id number := null, p_standard_org varchar2 := null, p_standard_title varchar2 := null, p_standard_number varchar2 := null) RETURN SEARCH_RESULTS_TABLE PIPELINED AS
out_rec search_results_row := search_results_row(null,null,null,null);
v_num_pages number;
v_num_results number;
cursor c_count is
select count(*) cnt, ceil(count(*) / p_num_results) num_pages from (
select * from (
select rownum rn, bb.* from (
select * from (
select sum(score) score, concept_id from
(
(
select
sum(score) score,
concept_id
from
(
select
s.score + (case
when c.eotd = 'N' then
200
else
0
end) score,
ct.concept_id
from
table(search.synonym_search(p_search)) s,
term_synonym ts,
concept_term ct,
concept c
where
c.eotd = 'N' and
s.table_id = ts.synonym_id and
ts.term_id = ct.term_id and
c.concept_id = ct.concept_id
)
group by
concept_id
)
union all
(
select
sum(score) score,
concept_id
from
(
select
s.score + (case
when c.eotd = 'N' then
200
else
0
end) score,
cd.concept_id
from
table(search.definition_search(p_search)) s,
concept_definition cd,
concept c
where
c.eotd = 'N' and
s.table_id = cd.definition_id and
c.concept_id = cd.concept_id
)
group by
concept_id
)
)
group by concept_id
) order by score desc
) bb) where score > 100) where rn < 1000;
-- another cursor here called c_search (removed for cleanliness)
v_added boolean;
v_in_dict varchar(1);
v_concept_id number;
cursor c_in_dict is
select * from dictionary_concept where concept_id = v_concept_id and dictionary_id in (select dictionary_id from company_dictionary where client_company_id in (select client_company_id from users where users_id = p_user_id));
v_in_dict_result c_in_dict%rowtype;
BEGIN
open c_count;
fetch c_count into v_num_results, v_num_pages; -- line 216
close c_count;
out_rec.SCORE := v_num_results;
out_rec.FROM_TABLE := 'HEADER';
out_rec.ID := v_num_pages;
out_rec.IN_DICTIONARY := 'N';
pipe row(out_rec);
-- more code here but been removed
RETURN;
END CONCEPT_NEW;
The code around line 995:
FUNCTION STANDARD_SEARCH(p_search varchar2) RETURN RESULT_TABLE
PIPELINED
AS
out_rec result_type := result_type(null, null);
cursor c_search is
select
45 score,
source_id
from
source
where
source_title = p_search or
standard_number = p_search
union all
select
40,
source_id
from
source
where
lower(source_title) = lower(p_search) or
lower(standard_number) = lower(p_search)
union all
select
35,
source_id
from
source
where
lower(source_title) like lower(p_search) || '%' or
lower(standard_number) like lower(p_search) || '%'
union all
select
30,
source_id
from
source
where
lower(source_title) like '%' || lower(p_search) || '%' or
lower(standard_number) like '%' || lower(p_search) || '%'
union all
select
10 * contains(source_title, lower(p_search)),
source_id
from
source
where
contains(source_title, lower(p_search)) > 1
union all
select
10 * contains(standard_number, lower(p_search)),
source_id
from
source
where
contains(standard_number, lower(p_search)) > 1;
BEGIN
for r_search in c_search loop -- line 995
out_rec.SCORE := r_search.SCORE;
out_rec.TABLE_ID := r_search.SOURCE_ID;
pipe row(out_rec);
end loop;
return;
END;
Change = null to is null. Zero-length strings in Oracle are already NULL so = '' is also incorrect.
Those are some obvious bugs but the code is so complex I'm not sure if they are directly related to the errors. You may need to shrink your code down until it can fit inside a small, reproducible test case. That can take hours of work sometimes.
Another suggestion is to rethink whether you need to use pipelined functions. In my experience pipelined functions are buggy and over-used. Sometimes they can be replaced by regular SQL statements. Sometimes they can be replaced by a simpler function that returns a complete collection, instead of returning it one row at a time. Unless the collection is so ginormous that it can't reasonably fit in memory, or you need the function to return the first N results so they can be processed immediately, the pipelined feature doesn't help.

SQL Statement ignored

I am writing this code in SQL and getting the following error:
LINE/COL ERROR
-------- -----------------------------------------------------------------
7/2 PL/SQL: SQL Statement ignored
Statement:
CREATE OR REPLACE FUNCTION GET_C_O(vretail_outlet_id int,
vtran_year varchar)
RETURN number
AS
stock number;
BEGIN
select vretail_outlet_id,
SUM(GET_C_O_STOCKFN_TEST(61, a.BATCHID, 1,
to_date('204-04-01','yyyy-mm-dd'),
vretail_outlet_id, vtran_year, 1) * QP.PRODUCTRATE) AS OPENING
From Promas
inner join Product A
on Promas.Pcode = A.Pcode and
vretail_outlet_id = A.Retail_outlet_id and
vtran_year = a.tran_year
inner Join QryProductrate Qp
on Qp.batchid = a.batchid and
QP.Retail_outlet_id = a.REtail_outlet_id and
Qp.Tran_year = a.tran_year
where a.tran_year = '2014_2015' and
1=1
group by vretail_outlet_id)
into stock
from dual;
Return Stock;
END;
The SELECT statement is not correct. Try:
select SUM(GET_C_O_STOCKFN_TEST(61, a.BATCHID, 1,
to_date('2014-04-01','yyyy-mm-dd'),
vretail_outlet_id, vtran_year, 1) * QP.PRODUCTRATE) AS OPENING
into stock
From Promas
inner join Product A
on Promas.Pcode = A.Pcode and
vretail_outlet_id = A.Retail_outlet_id and
vtran_year = a.tran_year
inner Join QryProductrate Qp
on Qp.batchid = a.batchid and
QP.Retail_outlet_id = a.REtail_outlet_id and
Qp.Tran_year = a.tran_year
where a.tran_year = '2014_2015';
Share and enjoy.

PL/SQL: Conditional Where

I have the following scenario:
CREATE OR REPLACE PROCEDURE GETINBOX
(
inHasAttachments IN int
)
AS
BEGIN
SELECT M.MailId,
M.SenderId,
E.Emp_Name As "Sender",
MI.RecipientId,
M.Subject
FROM MAIL M INNER JOIN MAILINBOX MI ON M.MailId = MI.MailId
WHERE MI.RecipientId = '547' AND
M.NotificationSelected = 'Y'
IF inHasAttachments = '1' THEN
AND M.Attachments = 'Y'
END IF;
END GETINBOX;
Is it possible to add conditions to the where clause based on the value of a parameter?
WHERE MI.RecipientId = '547' AND
M.NotificationSelected = 'Y'
IF inHasAttachments = '1' THEN
AND M.Attachments = 'Y'
END IF;
Obviously this is not allowed but is it possible to do this in some way in PL/SQL?
I know one way to do it is to duplicate the query and execute a different query based on the value of the parameter but I don't want to duplicate my code.
As I understand your requirements: if the value of parameter inHasAttachments is 1 then you want to filter further by M.Attachments = 'Y', and if its value isn't 1 then you don't care about M.Attachments. This is in addition to the condition MI.RecipientId = '547' AND M.NotificationSelected = 'Y'.
You can do it like this:
SELECT M.MailId,
M.SenderId,
E.Emp_Name As "Sender",
MI.RecipientId,
M.Subject
FROM MAIL M INNER JOIN MAILINBOX MI ON M.MailId = MI.MailId
WHERE MI.RecipientId = '547' AND M.NotificationSelected = 'Y'
AND (inHasAttachments <> '1' OR M.Attachments = 'Y')

Resources