my trigger wont print what i want it to - sql

so im a student working in Oracle SQL and i wrote a trigger to notify me if the item quantity is under a certain value. my trigger was created without compilation errors but when i test it i do not see the output that i want... I am sure there may be better ways to do certain parts of this but i am concerned mostly with how to get it to print to the command line. also if possible i would like the first if statement to contain a break statement so that the quantity cannot be less than 0. is that done by addint 'BREAK;' before the 'END IF;'?
SQL> #345lowqtytrigger
SQL> CREATE OR REPLACE TRIGGER low_qty_trigger
2 BEFORE INSERT OR UPDATE OF vnd_itm_qty ON Vending_Machine_Item
3 FOR EACH ROW
4 DECLARE
5 tempstr varchar2(1000);
6 name varchar2(1000);
7 vndadd varchar2(1000);
8 tempint int;
9 cursor itm_des_cursor is
10 SELECT itm_des FROM item WHERE itm_id = item.itm_id;
11 cursor vnd_addr_cursor is
12 SELECT vnd_addr FROM Vending_Machine WHERE vnd_id = Vending_Machine.vnd_id;
13 BEGIN
14 open itm_des_cursor;
15 fetch itm_des_cursor into name;
16 open vnd_addr_cursor;
17 fetch vnd_addr_cursor into vndadd;
18 IF :NEW.vnd_itm_qty < 0 THEN
19 tempstr := concat(:new.vnd_id,concat(' can not have less than 0 quantity for ',name));
20 dbms_output.put_line(tempstr);
21 end if;
22 tempint := :new.vnd_itm_qty_max*.15;
23 IF
24 :NEW.vnd_itm_qty <= tempint
25 and
26 :NEW.vnd_itm_qty >= 0
27 THEN
28 tempstr := concat('There will be less than ',
29 concat(to_char(tempint),
30 concat(' of ',
31 concat(name,
32 concat(' in Vending Machine ',
33 concat(to_char(:new.vnd_id),
34 concat(' located at ',vndadd)))))));
35 dbms_output.put_line(tempstr);
36 END IF;
37 close itm_des_cursor;
38 close vnd_addr_cursor;
39 END;
40 /
Trigger created.
SQL> SET ECHO OFF;
No errors.
SQL> spool off;
TEST CASE
SQL> update vending_machine_item set vnd_itm_qty = 1 where vnd_id = 956 and itm_id = 193;
1 row updated.

How are you testing this? It has to be in an interactive session to see any output generated by dbms_output. Try an update on vending_machine_item from a sql*plus session with set serveroutput on.

Related

IF condition containing IN operator inside ORACLE Trigger is not working

I have a trigger that uses IF condition with IN operator and two variables v_audit_user and v_evdnse_user inside IN. Both variables are containing comma separated ID values. The trigger gets compiled successfully with no errors. I am not understanding why the IF condition with IN is not working. When I select the function that assigns value to the variables independently, I do see the comma separated values, so nothing is wrong with function (see screenshot).
create or replace TRIGGER TRG_CHK_HRCQA_CASE_ACTIONS
AFTER INSERT ON KDD_CASE_ACTIONS
FOR EACH ROW
DECLARE
user_audit kdd_review_owner.OWNER_ID%TYPE; /* The user that is displayed in audit */
user_evdnse kdd_review_owner.OWNER_ID%TYPE; /* The user that took action in evidence tab */
v_audit_user NUMBER; /* The HRCO/QA user from audit tab */
v_evdnse_user NUMBER; /* The HRCO/QA user from evidence tab */
LV_ERRORCODE VARCHAR2(1000);
BEGIN
/* pass the username into the variables */
SELECT kro.OWNER_ID into user_audit from kdd_review_owner kro where kro.OWNER_SEQ_ID = :NEW.ACTION_BY_ID;
SELECT kro.OWNER_ID into user_evdnse from kdd_review_owner kro where kro.OWNER_SEQ_ID = :NEW.ACTION_BY_ID;
/* fetch the comma separated IDs */
v_audit_user := F_GET_HRCQA_ACTIONS(:NEW.CASE_INTRL_ID,user_audit,'AUDIT');
v_evdnse_user := F_GET_HRCQA_ACTIONS(:NEW.CASE_INTRL_ID,user_evdnse,'EVDNSE');
-- select ENTITY_ID into v_evdnse_user from table(f_get_arg_table(F_GET_HRCQA_ACTIONS(:NEW.CASE_INTRL_ID,user_evdnse,'EVDNSE')));
/* If the action taken is by QA or HRCO role */
IF (:NEW.ACTION_SEQ_ID in (v_audit_user,v_evdnse_user))
THEN
/* then insert record in the SC_HRCQA_CASE_ACTIONS table with IS_HRCO_QA flag as Y */
Insert into SC_HRCQA_CASE_ACTIONS (ACTION_SEQ_ID,ACTION_BY_ID,ACTION_TS,STATUS_CD,CASE_INTRL_ID,ACTION_ID,NEW_CASE_OWNR_ASSGN_ID,CASE_DUE_TS,PREV_CASE_OWNR_ASSGN_ID,IS_HRCO_QA)
values (:NEW.ACTION_SEQ_ID, :NEW.ACTION_BY_ID, :NEW.ACTION_TS, :NEW.STATUS_CD, :NEW.CASE_INTRL_ID, :NEW.ACTION_ID, :NEW.NEW_CASE_OWNR_ASSGN_ID, :NEW.CASE_DUE_TS, :NEW.PREV_CASE_OWNR_ASSGN_ID,'Y');
-- ELSE
--
-- /* else the logged in user is NOT HRCO/QA hence insert record in the SC_HRCQA_CASE_ACTIONS table with IS_HRCO_QA flag as N */
--
-- Insert into SC_HRCQA_CASE_ACTIONS (ACTION_SEQ_ID,ACTION_BY_ID,ACTION_TS,STATUS_CD,CASE_INTRL_ID,ACTION_ID,NEW_CASE_OWNR_ASSGN_ID,CASE_DUE_TS,PREV_CASE_OWNR_ASSGN_ID,IS_HRCO_QA)
-- values (:NEW.ACTION_SEQ_ID, :NEW.ACTION_BY_ID, :NEW.ACTION_TS, :NEW.STATUS_CD, :NEW.CASE_INTRL_ID, :NEW.ACTION_ID, :NEW.NEW_CASE_OWNR_ASSGN_ID, :NEW.CASE_DUE_TS, :NEW.PREV_CASE_OWNR_ASSGN_ID,'N');
END IF;
EXCEPTION
WHEN OTHERS THEN LV_ERRORCODE := SQLCODE;
INSERT INTO KDD_LOGS_MSGS (LOG_DT, LOG_INFO_TX, REMARK_TX)
VALUES (SYSDATE,'ErrorCode - ' || LV_ERRORCODE,'TRG_CHK_HRCQA_CASE_ACTIONS');
END;
You cannot pass a comma-delimited string stored in a single variable to an IN condition and expect it to be parsed as multiple values as it is not.
If you want to use a single variable containing a delimited list then you will need to use string functions to find a sub-string match:
create or replace TRIGGER TRG_CHK_HRCQA_CASE_ACTIONS
AFTER INSERT ON KDD_CASE_ACTIONS
FOR EACH ROW
DECLARE
v_owner_id kdd_review_owner.OWNER_ID%TYPE;
v_audit_user VARCHAR2(1000);
v_evdnse_user VARCHAR2(1000);
LV_ERRORCODE VARCHAR2(1000);
BEGIN
SELECT OWNER_ID
into v_owner_id -- You only need one variable here
from kdd_review_owner
where OWNER_SEQ_ID = :NEW.ACTION_BY_ID;
v_audit_user := F_GET_HRCQA_ACTIONS(:NEW.CASE_INTRL_ID, v_owner_id, 'AUDIT');
v_evdnse_user := F_GET_HRCQA_ACTIONS(:NEW.CASE_INTRL_ID, v_owner_id, 'EVDNSE');
IF ','||v_audit_user||','||v_evdnse_user||',' LIKE '%,'||:NEW.ACTION_SEQ_ID||',%'
THEN
Insert into SC_HRCQA_CASE_ACTIONS (
ACTION_SEQ_ID, ACTION_BY_ID, ACTION_TS, STATUS_CD, CASE_INTRL_ID,
ACTION_ID, NEW_CASE_OWNR_ASSGN_ID, CASE_DUE_TS, PREV_CASE_OWNR_ASSGN_ID, IS_HRCO_QA
) values (
:NEW.ACTION_SEQ_ID, :NEW.ACTION_BY_ID, :NEW.ACTION_TS, :NEW.STATUS_CD, :NEW.CASE_INTRL_ID,
:NEW.ACTION_ID, :NEW.NEW_CASE_OWNR_ASSGN_ID, :NEW.CASE_DUE_TS, :NEW.PREV_CASE_OWNR_ASSGN_ID,'Y'
);
END IF;
EXCEPTION
WHEN OTHERS THEN LV_ERRORCODE := SQLCODE;
INSERT INTO KDD_LOGS_MSGS (LOG_DT, LOG_INFO_TX, REMARK_TX)
VALUES (SYSDATE,'ErrorCode - ' || LV_ERRORCODE,'TRG_CHK_HRCQA_CASE_ACTIONS');
END;
/
I don't have your tables so I'll try to illustrate it using my own code.
This is what you're doing now: to us (humans), it is obvious that L_NEW_ID (its value is 10) is contained in L_VAR1 (its value is '10,20'). However, Oracle doesn't recognize that and returns "Not OK":
SQL> declare
2 -- does L_NEW_ID exist in L_VAR1 and L_VAR2 (using your code)?
3 l_new_id number := 10;
4 --
5 l_var1 varchar2(20) := '10,20';
6 l_var2 varchar2(20) := '30,40';
7 begin
8 if l_new_id in (l_var1, l_var2) then
9 dbms_output.put_line('OK');
10 else
11 dbms_output.put_line('Not OK');
12 end if;
13 end;
14 /
Not OK
PL/SQL procedure successfully completed.
SQL>
So, what to do? One option is to split variables to rows and then check whether search value (10, right?) exists in such a list of values (rows). The result is - as you can see - "OK":
SQL> declare
2 l_new_id number := 10;
3 --
4 l_var1 varchar2(20) := '10,20';
5 l_var2 varchar2(20) := '30,40';
6 l_cnt number;
7 begin
8 -- count how many times L_NEW_ID exists in L_VAR1 nad L_VAR2
9 select count(*)
10 into l_cnt
11 from (-- split L_VAR1 into rows
12 select regexp_substr(l_var1, '[^,]+', 1, level) val
13 from dual
14 connect by level <= regexp_count(l_var1, ',') + 1
15 union all
16 -- split L_VAR2 into rows
17 select regexp_substr(l_var2, '[^,]+', 1, level)
18 from dual
19 connect by level <= regexp_count(l_var2, ',') + 1
20 ) x
21 where x.val = l_new_id;
22
23 if l_cnt > 0 then
24 dbms_output.put_line('OK');
25 else
26 dbms_output.put_line('Not OK');
27 end if;
28 end;
29 /
OK
PL/SQL procedure successfully completed.
SQL>
Just to verify it, let's change L_NEW_ID value to e.g. 99 and see what happens; as expected, "Not OK" as 99 isn't contained in 10, 20 nor 30, 40.
SQL> l2
2* l_new_id number := 10;
SQL> c/10/99
2* l_new_id number := 99;
SQL> /
Not OK
PL/SQL procedure successfully completed.
SQL>

PL SQL Loop Table after insert and update

I'm trying loop through a table called broker after an insert to a different table called appointment and update a value on the broker table this what i have. When i try to create the trigger it comes up with an error saying "Trigger created with compilation errors"
CREATE OR REPLACE TRIGGER broker_level_trigger
AFTER INSERT ON appointment
DECLARE
counter integer := 1;
BEGIN
for o in (SELECT * FROM broker)
loop
SELECT COUNT(appointment.broker_id) INTO app_number FROM appointment INNER JOIN broker ON broker.broker_id = appointment.broker_id WHERE broker.broker_id = counter;
IF app_number > 15 THEN
UPDATE broker SET broker_level = 'gold' WHERE broker_id = counter;
counter := counter + 1;
end loop;
end;
/
The broker table has a field called broker_level and it changes based on the appointments, i want it to change if the broker_id field on appointments gets to more then 15
show err is a wonderful thing. (I created dummy tables you use).
SQL> CREATE OR REPLACE TRIGGER broker_level_trigger
2 AFTER INSERT ON appointment
3 DECLARE
4 counter integer := 1;
5 BEGIN
6 for o in (SELECT * FROM broker)
7 loop
8 SELECT COUNT(appointment.broker_id)
9 INTO app_number
10 FROM appointment INNER JOIN broker
11 ON broker.broker_id = appointment.broker_id
12 WHERE broker.broker_id = counter;
13
14 IF app_number > 15 THEN
15 UPDATE broker SET
16 broker_level = 'gold'
17 WHERE broker_id = counter;
18 counter := counter + 1;
19
20 end loop;
21 end;
22 /
Warning: Trigger created with compilation errors.
SQL> show err
Errors for TRIGGER BROKER_LEVEL_TRIGGER:
LINE/COL ERROR
-------- -----------------------------------------------------------------
18/7 PLS-00103: Encountered the symbol "LOOP" when expecting one of
the following:
if
If you look closer, you'll see that IF misses its END IF. Let's add it:
SQL> CREATE OR REPLACE TRIGGER broker_level_trigger
2 AFTER INSERT ON appointment
3 DECLARE
4 counter integer := 1;
5 BEGIN
6 for o in (SELECT * FROM broker)
7 loop
8 SELECT COUNT(appointment.broker_id)
9 INTO app_number
10 FROM appointment INNER JOIN broker
11 ON broker.broker_id = appointment.broker_id
12 WHERE broker.broker_id = counter;
13
14 IF app_number > 15 THEN
15 UPDATE broker SET
16 broker_level = 'gold'
17 WHERE broker_id = counter;
18 counter := counter + 1;
19 END IF; --> missing
20 end loop;
21 end;
22 /
Warning: Trigger created with compilation errors.
SQL> show err
Errors for TRIGGER BROKER_LEVEL_TRIGGER:
LINE/COL ERROR
-------- -----------------------------------------------------------------
6/5 PL/SQL: SQL Statement ignored
7/12 PLS-00201: identifier 'APP_NUMBER' must be declared
8/7 PL/SQL: ORA-00904: : invalid identifier
12/5 PL/SQL: Statement ignored
12/8 PLS-00201: identifier 'APP_NUMBER' must be declared
APP_NUMBER is missing now; you use it, but never declared it. Let's do it now:
SQL> CREATE OR REPLACE TRIGGER broker_level_trigger
2 AFTER INSERT ON appointment
3 DECLARE
4 counter integer := 1;
5 app_number number; --> missing
6 BEGIN
7 for o in (SELECT * FROM broker)
8 loop
9 SELECT COUNT(appointment.broker_id)
10 INTO app_number
11 FROM appointment INNER JOIN broker
12 ON broker.broker_id = appointment.broker_id
13 WHERE broker.broker_id = counter;
14
15 IF app_number > 15 THEN
16 UPDATE broker SET
17 broker_level = 'gold'
18 WHERE broker_id = counter;
19 counter := counter + 1;
20 END IF; --> missing
21 end loop;
22 end;
23 /
Trigger created.
SQL>
That would be it.
If you don't use SQL*Plus but some other tool, you can always query user_errors:
Warning: Trigger created with compilation errors.
SQL> select line, position, text from user_errors where name = 'BROKER_LEVEL_TRIGGER' order by sequence;
LINE POSITION TEXT
----- --------- ------------------------------------------------------------
8 12 PLS-00201: identifier 'APP_NUMBER' must be declared
9 7 PL/SQL: ORA-00904: : invalid identifier
7 5 PL/SQL: SQL Statement ignored
13 8 PLS-00201: identifier 'APP_NUMBER' must be declared
13 5 PL/SQL: Statement ignored
SQL>

Prime Number using GOTO statement in PL/SQL

This is my code for Prime Number using goto statement
set serveroutput on;
SQL>
SQL> declare
2 msg varchar2 (30);
3 n pls_integer := 83;
4
5 begin
6 for i in 2..round( sqrt(n) ) loop
7 if n mod i=0 then
8 msg := ' is not a prime number';
9 goto when_prime;
10 end if;
11 end loop;
12
13 msg := ' is a prime number';
14
15 <>
16 dbms_output.put_line(to_char(n) || msg);
17 end;
18 /
I'm getting the following error :
<>
*
ERROR at line 15:
ORA-06550: line 15, column 1:
PLS-00103: Encountered the symbol ">" when expecting one of the following:
( begin case declare end exception exit for goto if loop mod
null pragma raise return select update while with
<an identifier> <a double-quoted delimited-identifier>
<a bind variable> << continue close current delete fetch lock
insert open rollback savepoint set sql execute commit forall
merge pipe purge
ORA-06550: line 16, column 40:
PLS-00103: Encountered the symbol ";" when expecting one of the following:
. ( ) , * % & - + / at mod remainder rem <an exponent (**)>
and or || multiset
I want to check prime number or not a prime number using goto statement
You are not properly declaring the when_prime label.
Just replace this:
<>
With:
<<when_prime>>
Demo on DB Fiddle:
dbms_output:
83 is a prime number
You misused the label declaration section, it should be wrapped in << >> and not < >
Your code should be something like this:
SQL> DECLARE
2 MSG VARCHAR2(30);
3 N PLS_INTEGER := 83;
4 BEGIN
5 FOR I IN 2..ROUND(SQRT(N)) LOOP
6 IF N MOD I = 0 THEN
7 MSG := ' is not a prime number';
8 GOTO WHEN_PRIME;
9 END IF;
10 END LOOP;
11
12 MSG := ' is a prime number';
13 << WHEN_PRIME >>
14 DBMS_OUTPUT.PUT_LINE(TO_CHAR(N) || MSG);
15 END;
16 /
83 is a prime number
PL/SQL procedure successfully completed.
SQL>
UPDATE - Important
May be irrelevant for the error you are getting but you can directly use the following query to find the prime number:
SQL> WITH NUMBR AS (SELECT 83 NUMBR FROM DUAL)
2 SELECT NUMBR,
3 CASE WHEN SUM(CASE WHEN MOD(NUMBR, LEVEL) = 0
4 THEN 1 END) = 1
5 THEN 'prime'
6 ELSE 'not prime'
7 END AS "Prime?"
8 FROM NUMBR
9 CONNECT BY LEVEL <= FLOOR(NUMBR / 2)
10 GROUP BY NUMBR;
NUMBR Prime?
---------- ---------
83 prime
SQL>
Cheers!!

Trying to update Oracle Vendor-site flexfields. Cursor not working

I'm pretty new to PL/SQL and am having some trouble getting this to run. I am trying to pass the vendor_site_id in two places using my cursor. (Eventually the list will be longer, just trying in Dev with 2 IDs)
The code was obtained from Oracle, however we are trying to pass a mass update for these flexfields.
Here it is:
SET SERVEROUTPUT ON
DECLARE
lc_return_status VARCHAR2(2000);
ln_msg_count NUMBER;
ll_msg_data LONG;
Ln_Vendor_Id NUMBER;
Ln_Vendor_site_Id NUMBER;
ln_message_int NUMBER;
Ln_Party_Id NUMBER;
lrec_vendor_site_rec ap_vendor_pub_pkg.r_vendor_site_rec_type;
CURSOR cVendorSite
IS
SELECT VENDOR_SITE_ID
FROM ap_supplier_SITES_ALL
where vendor_site_id IN ('1631833', '1630833');
BEGIN
FOR rVendorSite IN cVendorSite
LOOP
Ln_Vendor_site_Id := rVendorSite.vendor_site_id;
Lrec_Vendor_site_Rec.vendor_site_id := rVendorSite.vendor_site_id;
Lrec_Vendor_site_Rec.ATTRIBUTE1 := 'Yes';
AP_VENDOR_PUB_PKG.Update_Vendor_Site_public ( p_api_version => 1,--
x_return_status => lc_return_status, --
x_msg_count => ln_msg_count, --
x_msg_data => ll_msg_data, --
p_vendor_site_rec => Lrec_Vendor_site_Rec, --
p_Vendor_site_Id => Ln_Vendor_site_Id);
IF (lc_return_status <> 'S') THEN
IF ln_msg_count >= 1 THEN
FOR v_index IN 1..ln_msg_count
LOOP
fnd_msg_pub.get (p_msg_index => v_index, p_encoded => 'F', p_data => ll_msg_data, p_msg_index_out => ln_message_int );
Ll_Msg_Data := 'UPDATE_VENDOR_SITE '||SUBSTR(Ll_Msg_Data,1,3900);
dbms_output.put_line('Ll_Msg_Data - '||Ll_Msg_Data );
END LOOP;
End If;
END IF;
END LOOP --Cursor Loop
EXCEPTION
WHEN OTHERS THEN
dbms_output.put_line('SQLERRM - '||SQLERRM );
END;
/
COMMIT;
EXIT;
END LOOP Needs a Semicolon
You have
END LOOP --Cursor Loop
It needs a semicolon:
END LOOP; --Cursor Loop
Once I modify this plsql block, I just identify two supplier_site_id's which I can modify in lieu of (1631833, 1630833). Of course, execute this for your supplier_site_id.
With this condition, you have the datatype wrong for supplier_site_id. It is of type, NUMBER, and not VARCHAR2. I would expect the database to dynamically cast these VARCHAR2's back to NUMBER's during execution.
Before I invoke the block, here are values associated with two sites I have picked (both NULL) using SQLCl:
APPS#dev>SELECT
2 attribute1
3 FROM
4 apps.ap_supplier_sites_all
5 WHERE
6 vendor_site_id IN (
7 812119,812118
8 );
ATTRIBUTE1
Next, I invoke the plsql block which calls Oracle Applications api associated with performing updates to the vendor site records:
APPS#dev>DECLARE
2 lc_return_status VARCHAR2(2000);
3 ln_msg_count NUMBER;
4 ll_msg_data LONG;
5 ln_vendor_id NUMBER;
6 ln_vendor_site_id NUMBER;
7 ln_message_int NUMBER;
8 ln_party_id NUMBER;
9 lrec_vendor_site_rec ap_vendor_pub_pkg.r_vendor_site_rec_type;
10 CURSOR cvendorsite IS
11 SELECT
12 vendor_site_id
13 FROM
14 ap_supplier_sites_all
15 WHERE
16 vendor_site_id IN (
17 812119,812118
18 );
19
20 BEGIN
21 FOR rvendorsite IN cvendorsite LOOP
22 ln_vendor_site_id := rvendorsite.vendor_site_id;
23 lrec_vendor_site_rec.vendor_site_id := rvendorsite.vendor_site_id;
24 lrec_vendor_site_rec.attribute1 := 'Yes';
25 ap_vendor_pub_pkg.update_vendor_site_public(
26 p_api_version => 1,--
27 x_return_status => lc_return_status, --
28 x_msg_count => ln_msg_count, --
29 x_msg_data => ll_msg_data, --
30 p_vendor_site_rec => lrec_vendor_site_rec, --
31 p_vendor_site_id => ln_vendor_site_id
32 );
33
34 IF
35 ( lc_return_status <> 'S' )
36 THEN
37 IF
38 ln_msg_count >= 1
39 THEN
40 FOR v_index IN 1..ln_msg_count LOOP
41 fnd_msg_pub.get(
42 p_msg_index => v_index,
43 p_encoded => 'F',
44 p_data => ll_msg_data,
45 p_msg_index_out => ln_message_int
46 );
47
48 ll_msg_data := 'UPDATE_VENDOR_SITE '
49 || substr(
50 ll_msg_data,
51 1,
52 3900
53 );
54 dbms_output.put_line('Ll_Msg_Data - ' || ll_msg_data);
55 END LOOP;
56
57 END IF;
58 END IF;
59
60 END LOOP; --Cursor Loop
61 EXCEPTION
62 WHEN OTHERS THEN
63 dbms_output.put_line('SQLERRM - ' || sqlerrm);
64 END;
65 /
PL/SQL procedure successfully completed.
Next, I check these records to see the updates we just made through calling the vendor site update api:
APPS#dev>SELECT
2 attribute1
3 FROM
4 apps.ap_supplier_sites_all
5 WHERE
6 vendor_site_id IN (
7 812119,812118
8 );
ATTRIBUTE1
Yes
Yes
Since I did not perform a commit, I rollback my changes to leave the records unchanged:
APPS#dev>rollback;
Rollback complete.
APPS#dev>SELECT
2 attribute1
3 FROM
4 apps.ap_supplier_sites_all
5 WHERE
6 vendor_site_id IN (
7 812119,812118
8 );
ATTRIBUTE1
Thus, my environment is unchanged.

COUNT function for files?

Is it possible to use COUNT in some way that will give me the number of tuples that are in a .sql file? I tried using it in a query with the file name like this:
SELECT COUNT(*) FROM #q65b;
It tells me that the table is invalid, which I understand because it isn't a table, q65b is a file with a query saved in it. I'm trying to compare the number of rows in q65b to a view that I have created. Is this possible or do I just have to run the query and check the number of rows at the bottom?
Thanks
You can do this in SQL*Plus. For example:
Create the text file, containing the query (note: no semicolon!):
select * from dual
Save it in a file, e.g. myqueryfile.txt, to the folder accessible from your SQL*Plus session.
You can now call this from within another SQL query - but make sure the # as at the start of a line, e.g.:
SQL> select * from (
2 #myqueryfile.txt
3 );
D
-
X
I don't personally use this feature much, however.
Here is one approach. It's a function which reads a file in a directory, wraps the contents in a select count(*) from ( .... ) construct and executes the resultant statement.
1 create or replace function get_cnt
2 ( p_file in varchar2 )
3 return number
4 as
5 n pls_integer;
6 stmt varchar2(32767);
7 f_line varchar2(255);
8 fh utl_file.file_type;
9 begin
10 stmt := 'select count(*) from (';
11 fh := utl_file.fopen('SQL_SCRIPTS', p_file, 'R');
12 loop
13 utl_file.get_line(fh, f_line );
14 if f_line is null then exit;
15 elsif f_line = '/' then exit;
16 else stmt := stmt ||chr(10)||f_line;
17 end if;
18 end loop;
19 stmt := stmt || ')';
20 execute immediate stmt into n;
21 return n;
22* end get_cnt;
SQL>
Here is the contents of a sql file:
select * from emp
/
~
~
~
"scripts/q_emp.sql" 3L, 21C
And here is how the script runs:
SQL> select get_cnt ('q_emp.sql') from dual
2 /
GET_CNT('Q_EMP.SQL')
--------------------
14
SQL>
So it works. Obviously what I have posted is just a proof of concept. You will need to include lots of error handling for the UTL_FILE aspects - it's a package which can throw lots of exceptions - and probably some safety checking of the script that gets passed.