when I run the query I get this error: ORA-06550 - sql

i have this error when i run this query.
PLS-00428: an INTO clause is expected in this SELECT statement
Query:
DECLARE
v_flag_tipo_factu varchar2(20);
BEGIN
SELECT valor_param INTO v_flag_tipo_factu FROM t_param WHERE cod_param =
'TIPOFAC';
if v_flag_tipo_factu = 'FN' THEN
SELECT
substr('00' || to_char(cta.cod_correo), -2) ||
substr('000000000' || to_char(cta.num_cta_cte), -9) ||
substr('000000000' || to_char(max(distinct fac.num_fac)),- 9)
FROM
t_acc_const cta,
t_fac fac
WHERE
cta.num_cta_cte = fac.num_cta_cte AND
fac.num_factura < 900000000
GROUP BY cta.cod_correo, cta.num_cta_cte;
end if;
END;
I expect 240,000 results like this:
13000291956000774037
06000167340000223372
13000089241000246480
13000057283000105163
06001632092003471840
13000093581000257191
12000252313001947873
06000120216000066999
06000309294001948770
13000192054000285006

If you don't like the PL/SQL rules, where the queries must be stored in variables for each step, you could use a query like this which should return the same
with v as (
SELECT valor_param FROM t_param WHERE cod_param = 'TIPOFAC'
)
SELECT
substr('00' || to_char(cta.cod_correo), -2) ||
substr('000000000' || to_char(cta.num_cta_cte), -9) ||
substr('000000000' || to_char(max(distinct fac.num_fac)),- 9)
FROM
t_acc_const cta,
t_fac fac
WHERE
cta.num_cta_cte = fac.num_cta_cte AND
fac.num_factura < 900000000 AND
EXISTS (select 1 from v where valor_param = 'FN')
GROUP BY cta.cod_correo, cta.num_cta_cte;

As you were told, SELECT (the one inside the IF) lacks in then INTO clause. You'll have to declare one more local variable and use it:
DECLARE
v_flag_tipo_factu varchar2(20);
--
v_result varchar2(50); --> this
BEGIN
SELECT valor_param INTO v_flag_tipo_factu FROM t_param WHERE cod_param =
'TIPOFAC';
if v_flag_tipo_factu = 'FN' THEN
SELECT
substr('00' || to_char(cta.cod_correo), -2) ||
substr('000000000' || to_char(cta.num_cta_cte), -9) ||
substr('000000000' || to_char(max(distinct fac.num_fac)),- 9)
INTO v_result --> this
FROM
...
It'll work if that select returns a single value; otherwise, query will raise
no_data_found if there are no rows that satisfy conditions
too_many_rows. How to handle it? It depends on what you want to do ...

Related

ORA-04091 TABLE ODB.EMPLOYEE IS MUTATING, TRIGGER/FUNCTION MAY NOT SEE IT. IS THERE SOMETHING WRONG WITH MY TRIGGER?

Trying to create a trigger when there is an update of Status on Employee Table and capture some values for the record in Employee table and Employee_Header table for that record and send an email. The trigger throws an error.
CREATE OR REPLACE TRIGGER ODB.TRG_EMPLOYEE_STATUS_EMAIL
AFTER UPDATE OF STATUS ON ODB.EMPLOYEE
FOR EACH ROW
DECLARE
s_message varchar2(4000);
s_subject varchar2(1000);
s_return_message varchar2(4000);
s_database varchar2(50);
v_rm EMPLOYEE%ROWTYPE;
v_sh EMPLOYEE_HEADER%ROWTYPE;
BEGIN
if :old."STATUS" = 'HOLD' AND :new."STATUS" = 'ACTIVE' AND :new."CATEGORY" = 'FULLTIME' then
select * into v_rm from EMPLOYEE WHERE :new."STATUS" = 'ACTIVE' AND ROWNUM>1;
select * into v_sh from EMPLOYEE_HEADER WHERE ROWNUM>1;
s_subject := 'NAME ' || v_rm.NAME ||' message ' || ' CHECK LOG OF EMPLOYEE' || Chr(13) || ' STATUS: ' || v_rm.STATUS ;
s_message := 'SAMPLE' || Chr(10)||Chr(13) || 'THE STATUS IN EMPLOYEE_HEADER IS: ' || Chr(10)|| ' STATUS: ' || v_sh.STATUS ;
pkg_email.sendEmail('INPUT PARAMETERS TO SEND EMAIL');
end if;
END;
You can't select from a table which is just being changed; it is mutating. Though, as you can use the :new pseudorecord, you can "skip" that error. Also, where rownum > 1 is useless as it is never true. I don't know what you meant to say by using it.
I see you've created columns using double quotes. In Oracle, that's usually a mistake. Not that it won't work - it will, but you always have to reference columns using double quotes and match letter case.
Finally, trigger might look like this (read comments within code):
create or replace trigger odb.trg_employee_status_email
after update of status on odb.employee
for each row
declare
s_message varchar2(4000);
s_subject varchar2(1000);
s_return_message varchar2(4000);
s_database varchar2(50);
-- v_rm employee%rowtype; -- you don't need that
v_sh employee_header%rowtype;
begin
if :old."status" = 'HOLD' and :new."status" = 'ACTIVE' and
:new."category" = 'FULLTIME'
then
-- You can't select from a table which is just being changed - it is "mutating".
-- Besides, AND ROWNUM > 1 will never return anything. You can only check
-- ROWNUM <= some_value
--select * into v_rm from employee where :new."status" = 'ACTIVE' and rownum>1;
select * into v_sh from employee_header where rownum>1;
-- instead of SELECT ... INTO V_RM, use :NEW pseudorecord
s_subject := 'NAME ' || :new.name ||' message ' || ' CHECK LOG OF EMPLOYEE'
|| chr(13) || ' STATUS: ' || :new.status ;
s_message := 'SAMPLE' || chr(10)||chr(13) || 'THE STATUS IN EMPLOYEE_HEADER IS: ' || chr(10)|| ' STATUS: ' || v_sh.status ;
pkg_email.sendemail('INPUT PARAMETERS TO SEND EMAIL');
end if;
exception
when no_data_found then null;
end;

Count how many car/cars owner owns

I'm trying to learn plsql and got stuck in understanding some basic stuff. Here is a challenge that I'm trying to solve. I have two tables. One holds information about owners and the other is information about cars.
I want to to write an anonymous block that joins these two tables and with a for loop based on amount of cars that is registered to each owner prints how many cars each person own. furthermore I want an if statement which distinguishes between 1 Car (singular) and 2, 3 Cars (plural).
the tables are these:
CREATE TABLE owners(
id_nr VARCHAR2(13) PRIMARY KEY,
f_name VARCHAR2(20),
s_name VARCHAR2(20)
);
CREATE TABLE cars(
reg_nr VARCHAR2(6) PRIMARY KEY,
id_nr REFERENCES owners(pnr),
model VARCHAR2(20),
year NUMBER(4),
date DATE
);
The result may look like something like this:
19380321-7799, Hans, Anderson, Owns: 1 car
19490321-7899, Mike, Erikson, Owns: 2 cars
. . . etc
I know the this question was already answered but when I try following:
declare
v_suffix varchar2(1);
begin
for o in (select bilägare_pnr, fnamn, enamn,
(select count(1) from fordon where fordon_pnr = bilägare_pnr) as bilar_ägda
from bilägare)
loop
if o.pnr_fordon = 1
then v_suffix = 'bil'
else v_suffix = 'bilar'
end if;
dbms_output.put_line(o.pnr || ', ' || o.fnamn || ', ' || o.enamn
|| ' Äger: ' || o.pnr_fordon || ' bil' || v_suffix);
end loop;
end;
/
I get:
ORA-06550: line 9, column 27:
PLS-00103: Encountered the symbol "=" when expecting one of the following:
:= . ( # % ;
any tips? Im not sure how to declare v_suffix
EDIT (copied from comment on answer below):
Updating my code:
declare
cursor c_BILÄGARE is
select fnamn,enamn,pnr
from BILÄGARE;
begin
for rec in c_BILÄGARE loop
if (rec.antal>1) then
dbms_output.put_line (rec.pnr||','|| rec.fnamn || ',' ||
rec.enamn || ',' || rec.antal || 'bilar');
else
dbms_output.put_line (rec.pnr||','|| rec.fnamn || ',' ||
rec.enamn || ',' || rec.antal || 'bil');
end if;
end loop;
end;
getting:
ORA-06550: line 9, column 9: PLS-00302: component 'ANTAL' must be declared (antal=Quantity)
As noted above, you need to use := as the assignment operator. You also need a semi-colon after each statement - thus, you should use
then v_suffix := 'bil';
instead of
then v_suffix := 'bil'
So your code should look like:
declare
v_suffix varchar2(1);
begin
for o in (select bilägare_pnr, fnamn, enamn,
(select count(1)
from fordon
where fordon_pnr = bilägare_pnr) as bilar_ägda
from bilägare)
loop
if o.pnr_fordon = 1
then v_suffix := 'bil';
else v_suffix := 'bilar';
end if;
dbms_output.put_line(o.pnr || ', ' || o.fnamn || ', ' || o.enamn
|| ' Äger: ' || o.pnr_fordon || ' bil' || v_suffix);
end loop;
end;
Please try this piece of code:
begin
for rec in (select
o.id_nr || ',' || o.f_name || ',' || o.s_name || ', Owns: ' || coalesce(car.cnt, 0) || ' ' || decode(car.cnt , 1, 'Car', 'Cars') as res
from owners o
left outer join (select id_nr, count(1) as cnt from cars group by id_nr) car on (car.id_nr = o.id_nr)) loop
dbms_output.put_line(rec.res);
end loop;
end;
Thanks.
There are multiple issues in your code which is highlighted and fixed in following code:
declare
v_suffix varchar2(5); -- data length should be 5 or more
begin
for o in (select bilägare_pnr, fnamn, enamn,
(select count(1) from fordon where fordon_pnr = bilägare_pnr) as bilar_ägda
from bilägare)
loop
if o.bilar_ägda <= 1 -- replaced it from pnr_fordon and <= is used for 0 or 1 car
then v_suffix := 'bil'; -- := and ; is used here and in next statement
else v_suffix := 'bilar';
end if;
dbms_output.put_line(o.pnr || ', ' || o.fnamn || ', ' || o.enamn
|| ' Äger: ' || o.pnr_fordon || ' bil' || v_suffix);
end loop;
end;
/

i don't know how to display the cursor data oracle

I don't know how to display the cursor data I create a cursor that returns multiple rows and I want to view the row and I don't know how
SET SERVEROUTPUT ON;
DECLARE CURSOR CurEscal IS
SELECT
ESCALE.NUMVOL, ( to_number ( to_char ( ESCALE.DATEED, 'MI' ) ) - to_number ( to_char ( ESCALE.DATEEA, 'MI' ) ) ) AS "duree par min", AEROPORT.NOMAER
FROM
ESCALE
JOIN AEROPORT ON ESCALE.REFAER = AEROPORT.REFAER
WHERE
NUMVOL IN ( SELECT ESCALE.NUMVOL FROM ESCALE GROUP BY ESCALE.NUMVOL HAVING Count( ESCALE.NUMESC ) >= 1 );
BEGIN
--Open the CurEscal CURSOR
IF NOT (CurEscal%ISOPEN) THEN
OPEN CurEscal;
END IF;
--FETCH
FOR i IN CurEscal LOOP
DBMS_OUTPUT.PUT_LINE('I don't know how I need your help');
END LOOP;
--Close the CurEscal CURSOR
IF CurEscal%ISOPEN THEN
CLOSE CurEscal;
END IF;
END;
/
can someone help !!
That would be
dbms_output.put_line(i.numvol ||', '|| i."duree par min" ||', '|| i.NOMAER);
Though, if you use a cursor FOR loop, everything is somewhat simpler as you don't have to declare/open/fetch/close the cursor, e.g.
BEGIN
FOR i
IN (SELECT escale.numvol,
( TO_NUMBER (TO_CHAR (escale.dateed, 'MI'))
- TO_NUMBER (TO_CHAR (escale.dateea, 'MI')))
AS duree_par_min,
aeroport.nomaer
FROM escale JOIN aeroport ON escale.refaer = aeroport.refaer
WHERE numvol IN ( SELECT escale.numvol
FROM escale
GROUP BY escale.numvol
HAVING COUNT (escale.numesc) >= 1))
LOOP
DBMS_OUTPUT.put_line (
i.numvol || ', ' || i.duree_par_min || ', ' || i.nomaer);
END LOOP;
END;

SQL Error: ORA-01422: "exact fetch returns more than requested number of rows"

I'm having a hard time understanding what's wrong with my SQL-script.
I get following error message:
Fehlerbericht -
ORA-01422: Exakter Abruf gibt mehr als die angeforderte Zeilenzahl zurück
ORA-06512: in Zeile 58
00000 - "exact fetch returns more than requested number of rows"
*Cause: The number specified in exact fetch is less than the rows returned.
*Action: Rewrite the query or change number of rows requested
The Script:
DECLARE
obj_exists NUMBER (38, 0);
faqqestion VARCHAR2 (4000 BYTE);
targetobjid NUMBER (38, 0);
translatedtemplate BOOLEAN;
BEGIN -- prints header
DBMS_OUTPUT.Put_line (
'"'
|| 'TemplateID'
|| '";"'
|| 'Templatetext'
|| '";"'
|| 'Sprache'
|| '";');
-- iterates over the latest version of all 'de' templates
FOR latestgermanobjects
IN ( SELECT vs.sl_vs_id vsId,
vs.sl_obj_id vsObjId,
TRANSM.sl_obj_id transmObjId,
TRANSM.lang,
OBJ.sl_obj_id objObjId,
faq.faq_template_id faqTemplateId
FROM sl_versionset vs
INNER JOIN sl_pp01_trans_meta transM
ON VS.sl_obj_id = TRANSM.sl_obj_id
INNER JOIN sl_pp01_obj obj
ON TRANSM.sl_obj_id = OBJ.sl_obj_id
INNER JOIN sl_pp01_faq01 faq
ON OBJ.sl_obj_id = FAQ.sl_obj_id
WHERE VS.sl_vs_next IS NULL
AND VS.sl_vs_deleted_flag = 0
AND VS.sl_vs_state <> 'Deprecated'
AND transm.lang = 'de'
AND obj.sl_obj_objtyp_id IN (334)
AND obj.sl_obj_deleted_flag = 0
ORDER BY faq.faq_template_id ASC)
LOOP
-- iterate over all languages except 'de' to check translation
FOR singlelanguagecursor
IN (SELECT sl_metaval_varchar
FROM slma_meta_values
WHERE sl_metaval_varchar <> 'de' AND slma_metatype_id = 5)
LOOP
translatedtemplate := FALSE;
-- iterate over all versions of versionset of the german template to find old tranlsations
FOR templates
IN ( SELECT sl_obj_id
FROM sl_versionset
WHERE sl_vs_id = latestgermanobjects.vsid
AND sl_vs_deleted_flag = 0
ORDER BY sl_obj_id DESC)
LOOP
SELECT COUNT (1)
INTO obj_exists
FROM sl_pp01_trans_meta
WHERE source_io = templates.sl_obj_id
AND lang = singlelanguagecursor.sl_metaval_varchar;
-- checks, if a translation of the chosen language exists
IF obj_exists >= 1
THEN
translatedtemplate := TRUE;
-- if only a tranlsation of a older version of the source object exists
IF templates.sl_obj_id <> latestgermanobjects.objobjid
THEN
SELECT sl_obj_id
INTO targetobjid
FROM sl_pp01_trans_meta
WHERE source_io = templates.sl_obj_id
AND lang =
singlelanguagecursor.sl_metaval_varchar;
SELECT faq_question
INTO faqqestion
FROM sl_pp01_templ01
WHERE sl_obj_id = targetobjid;
-- prints 'Template Id', tranlsation of templatetext, language of translation of a transation of a older source object
DBMS_OUTPUT.Put_line (
'"'
|| latestgermanobjects.faqtemplateid
|| '";"'
|| faqqestion
|| '";"'
|| singlelanguagecursor.sl_metaval_varchar
|| '";');
END IF;
-- ends loop, after translation has found
EXIT;
END IF;
END LOOP;
-- if no translation is available
IF NOT translatedtemplate
THEN
DBMS_OUTPUT.Put_line (
'"'
|| latestgermanobjects.faqtemplateid
|| '";"'
|| 'translation n/a'
|| '";"'
|| singlelanguagecursor.sl_metaval_varchar
|| '";');
END IF;
END LOOP;
END LOOP;
END;
New to SQL and PL/SQL so I would appreciate any help.
Here some example-explaination-code for your error:
declare
v_text VARCHAR2(4000);
begin
-- this will work fine..
SELECT * INTO v_text FROM
( -- this is a fake-table
SELECT 'some text' FROM DUAL
);
dbms_output.put_line(v_text);
-- this will get you an no data found exception
BEGIN
SELECT * INTO v_text FROM
( -- this is a fake-table
SELECT 'some text' FROM DUAL
)
WHERE 1 = 2;
dbms_output.put_line(v_text);
EXCEPTION
WHEN NO_DATA_FOUND THEN
dbms_output.put_line('there is no data..');
END;
-- this will get you your exception 'too many rows'
BEGIN
SELECT * INTO v_text FROM
( -- this is a fake-table
SELECT 'some text' FROM DUAL UNION ALL
SELECT 'some text' FROM DUAL
);
dbms_output.put_line(v_text);
EXCEPTION
WHEN TOO_MANY_ROWS THEN
dbms_output.put_line('there is too much data..');
END;
end;
Your specific problem is row 69, i guess:
SELECT sl_obj_id
INTO targetobjid
FROM sl_pp01_trans_meta
WHERE source_io = templates.sl_obj_id
AND lang =
singlelanguagecursor.sl_metaval_varchar;
If you get more than one row, your INTO is not allowed. Fix your select (WHERE ROWNUM = 1 !!!Use only if result is correct!!!) or handle the exception.

Query for particular integer value from multiple columns with number datatype

I try to search a number from multiple columns (datatype number), but get ORA-01722: invalid number error.
My Query:
SELECT *
FROM CAMPAIGN
WHERE 1481125 IN (select column_name
from all_tab_columns
where table_name = 'CAMPAIGN'
AND data_type = 'NUMBER');
What is wrong with it?
You are comparing your number 1481125 with the names of the each column, not the values of each column in your table.
To go from a column's name (from dba_tab_columns) to the values in that column, you need to use some form of dynamic SQL. Here's a relatively simple example:
DECLARE
-- Since I don't have your CAMPAIGN table or data, I'm using DBA_OBJECTS in it's place.
l_table_name VARCHAR2 (30) := 'DBA_OBJECTS';
l_search_number NUMBER := 20; -- 1481125 in your example
l_record dba_objects%ROWTYPE;
l_sql VARCHAR2 (32000);
l_column_number NUMBER := 0;
l_cur SYS_REFCURSOR;
BEGIN
-- First: build dynamic SQL statement of the form:
-- SELECT * FROM table_name WHERE
-- ( ( col_name_a = 20 ) OR ( col_name_b = 20 ) OR ... )
l_sql := 'SELECT * FROM dba_objects WHERE ( ';
FOR r_number_column IN (SELECT column_name
FROM dba_tab_columns
WHERE table_name = l_table_name
AND data_type = 'NUMBER'
ORDER BY column_id) LOOP
IF l_column_number > 0 THEN
l_sql := l_sql || ' OR ';
END IF;
l_column_number := l_column_number + 1;
l_sql := l_sql || '(' || r_number_column.column_name || ' = ' || l_search_number || ')';
END LOOP;
IF l_column_number = 0 THEN
-- No number columns in table, so there should be no matches
l_sql := l_sql || ' 1=0';
END IF;
l_sql := l_sql || ')';
DBMS_OUTPUT.put_line (l_sql);
OPEN l_cur FOR l_sql;
LOOP
FETCH l_cur INTO l_record;
EXIT WHEN l_cur%NOTFOUND;
DBMS_OUTPUT.put_line ('Object Name ' || l_record.object_name || ' has search number ' || l_search_number);
END LOOP;
END;
Your query is:
SELECT * FROM CAMPAIGN WHERE 1481125 IN
(select column_name from all_tab_columns where table_name = 'CAMPAIGN' AND data_type='NUMBER')
Breaking that down we have:
SELECT * FROM CAMPAIGN WHERE 1481125 IN (<a set of numbers>)
and the subquery:
select column_name from all_tab_columns
where table_name = 'CAMPAIGN'
AND data_type='NUMBER'
That subquery is going to return a list of column names e.g.
CAMPAIGN_COUNT
CAMPAIGN_ID
CAMPAIGN_NUMBER_OF_SOMETHINGS
Your query is thus equivalent to:
SELECT * FROM CAMPAIGN WHERE 1481125 IN
('CAMPAIGN_COUNT', 'CAMPAIGN_ID', 'CAMPAIGN_NUMBER_OF_SOMETHINGS')
You can see why you would get the ORA-01722 error there?
You would need to write dynamic SQL to achieve your aim.