How to get the number of rows affected by an UPDATE statement - oracle

I am trying to get the number of rows affected by an UPDATE statement, however I am getting the following error:
ORA-06550: line 2, column 9:
PLS-00103: Encountered the symbol ";" when expecting one of the following:
constant exception <an identifier>
<a double-quoted delimited-identifier> table columns long
double ref char time timestamp interval date binary national
character nchar
The symbol "exception" was substituted for ";" to continue.
The query that I am executing is the following:
DECLARE
var_rows;
BEGIN
var_rows:=SQL%ROWCOUNT;
UPDATE {Product} SET {Product}.[Name] = concat({Product}.[Name], ' - test') WHERE {Product}.[ProductTypeId] = 2;
SELECT var_rows FROM DUAL;
END;

Use SQL%rowcount properly. i.e. immediately after the update
Example
create table tab1 as
select 1 id, 'a' col from dual union all
select 1, 'b' from dual;
set serveroutput on;
declare
rn int;
begin
update tab1
set col = 'z';
rn := SQL%rowcount;
dbms_output.put_line(rn);
end;
/
2
PL/SQL procedure successfully completed.

Related

PLS-00103: Encountered the symbol "end-of-file" when expecting one of the following: begin function pragma procedure subtype type <an identifier>

I am working on sqldeveloper (pl/sql)
DECLARE
CUSTOMER_NAME VARCHAR(50);
PRODUCT VARCHAR(100);
BEGIN
SELECT C.FIRST_NAME ||','|| C.SURNAME, P.PRODUCT
INTO CUSTOMET_NAME, PRODUCT
FROM CUSTOMER C, PRODUCT P, BILLING B, PRODUCT_BILLING PB
WHERE B.BILL_ID = PB.BILL_ID
AND P.PRODUCT_ID = PB.PRODUCT_ID
AND C.CUSTOMER_ID = B.CUSTOMER_ID
AND P.PRICE > 10000;
DBMS_OUTPUT.PUT_LINE('CUSTOMER: '||CUSTOMER_NAME);
DBMS_OUTPUT.PUT_LINE('PRODUCT: '||PRODUCT);
END;
i executed declare part, but i got this error message. i googled it but i couldn't figured it out.
Error starting at line : 160 in command -
DECLARE
CUSTOMER_NAME VARCHAR(50);
PRODUCT VARCHAR(100);
Error report -
ORA-06550: line 3, column 25:
PLS-00103: Encountered the symbol "end-of-file" when expecting one of the following:
begin function pragma procedure subtype type <an identifier>
<a double-quoted delimited-identifier> current cursor delete
exists prior
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action:
As you didn't provide test case (CREATE TABLE and INSERT INTO statements), I created my own (empty) table set. Doing so, such a code compiles; as tables are empty, my query doesn't return anything, but still might point you to the right direction.
Note datatypes, sizes, exception handling section.
SQL> set serveroutput on
SQL>
SQL> declare
2 l_customer_name varchar2(100); -- at least size of first name + surname
3 l_product product.product%type;
4 begin
5 select c.first_name ||', '|| c.surname,
6 p.product
7 into l_customer_name,
8 l_product
9 from customer c join billing b on c.customer_id = b.customer_id
10 join product_billing pb on pb.bill_id = b.bill_id
11 join product p on p.product_id = pb.product_id
12 where p.price > 10000;
13
14 dbms_output.put_line('Customer: ' || l_customer_name);
15 dbms_output.put_line('Product : ' || l_product);
16 exception
17 when no_data_found then
18 dbms_output.put_line('Nothing matches');
19 when too_many_rows then
20 dbms_output.put_line('Too many products match');
21 end;
22 /
Nothing matches
PL/SQL procedure successfully completed.
SQL>
If it still doesn't help, as I said: provide test case.

Plsql Procedure in invalid state

I have created following procedure:
create or replace function getDepartmentById(name varchar2)
return number
is v_dep number(10)
begin
--the sql statement is totally fine
select deptno into v_dep from dept where dname = name;
end;
/
but when I call
select getDepartmentById('SALES') into dep from dual;
I get this error message
Error report -
ORA-06550: line 20, column 14:
PL/SQL: ORA-06575: Package or function GETDEPARTMENTBYID is in an invalid state
ORA-06550: line 20, column 7:
PL/SQL: SQL Statement ignored
You need to add a return value for the function. It goes like this :
CREATE OR replace FUNCTION Getdepartmentbyid(name VARCHAR2)
RETURN NUMBER
IS
v_dep NUMBER(10);
BEGIN
--the sql statement is totally fine
SELECT deptno
INTO v_dep
FROM dept
WHERE dname = name;
RETURN v_dep;
END;
You can not use a INTO in your select statement. You should call the function like this.
select getDepartmentById('SALES') from dual;

Oracle returning statement for an insert into operation with 'select from' source

We would like to return ids inserted from an insert statement that has a 'select from' clause as its source of values.
Example:
Create table Table1 (Col1 Number)
declare
vId number;
begin
insert into Table1 (select 1 from dual)
returning COL1 into vId;
end;
Error:
ORA-06550: line 5, column 5:
PL/SQL: ORA-00933: SQL command not properly ended
Is there something missing in the syntax, is it possible to do this? Thank you.
Returning into works only, when columns are listed before VALUES:
declare
vId number;
begin
insert into Table1 (col1) VALUES ((select 1 from dual))
returning COL1 into vId;
dbms_output.put_line( vId);
end;
==========
vId: 1

"ORA-01007: variable not in select list" when no rows are returned by EXECUTE IMMEDIATE

I have a procedure which receives as parameter a where clause (i.e. where col1 = 1). I am using this clause to search in some tables using an EXECUTE IMMEDIATE statement and the result to be inserted into a nested table, and than be displayed.
The procedure works fine if any data is found but in case no data is found, then the above error is thrown.
Can someone explain what cause this error, please?
Here is the procedure:
create or replace procedure prc_checks(pi_where varchar2) as
cursor c_tables is
select object_name,
case object_name
when 'XP_IMPORT_MW' THEN 99999999
when 'XP_IMPORT_MW_ARCH' THEN 99999998
else TO_NUMBER(SUBSTR(object_name, -8, 8))
end to_order
from dba_objects
where object_type = 'TABLE'
and object_name IN ('XP_IMPORT_MW', 'XP_IMPORT_MW_ARCH')
or REGEXP_LIKE (object_name, 'XP_IMPORT_MW_ARCH_201(5|6|7)[0-9]{4}') order by 2 desc;
type t_result is table of xp_import_mw%rowtype;
v_result t_result;
v_sql varchar2(300);
BEGIN
for i in c_tables
loop
v_sql := 'select * from ' || i.object_name || ' ' || pi_where;
execute immediate v_sql bulk collect into v_result;
if v_result.count > 0
then
for j in v_result.first .. v_result.last
loop
dbms_output.put_line(v_result(j).art_nr);
end loop;
dbms_output.put_line('... the required information was found on table name ' || upper(i.object_name));
exit;
end if;
end loop;
END prc_checks;
You'll get this is one of the tables being found by the cursor has fewer columns than xp_import_mw. For example:
create table xp_import_mw (col1 number, art_nr number, dummy number);
create table xp_import_mw_arch_20160102 (col1 number, art_nr number, dummy number);
create table xp_import_mw_arch_20160101 (col1 number, art_nr number);
insert into xp_import_mw_arch_20160101 values (1, 42);
So the main xp_import_mw table has three columns but no matching data. One of the old archive tables has one fewer columns.
I added a dbms_output.put_line(v_sql) to the procedure to see which table it fails against, then ran it:
set serveroutput on
exec prc_checks('where col1 = 1');
which got output:
select * from XP_IMPORT_MW where col1 = 1
select * from XP_IMPORT_MW_ARCH_20160102 where col1 = 1
select * from XP_IMPORT_MW_ARCH_20160101 where col1 = 1
Error starting at line : 49 in command -
BEGIN prc_checks('where col1 = 1'); END;
Error report -
ORA-01007: variable not in select list
ORA-06512: at "MY_SCHEMA.PRC_CHECKS", line 25
ORA-06512: at line 1
01007. 00000 - "variable not in select list"
*Cause:
*Action:
So the problem isn't that there is no data found; the problem is that there is matching data in a table which has the wrong structure.
You could construct the select list based on the xp_import_mw table's structure, instead of using *; that won't stop it failing, but would at least give you a slightly more helpful error message - in this case ORA-00904: "DUMMY": invalid identifier instead of ORA-01007.
You could do a quick and crude check for discrepancies with something like:
select table_name, count(column_id) as column_count,
listagg(column_name, ',') within group (order by column_id) as columns
from dba_tab_columns
where table_name IN ('XP_IMPORT_MW', 'XP_IMPORT_MW_ARCH')
or REGEXP_LIKE (table_name, 'XP_IMPORT_MW_ARCH_201(5|6|7)[0-9]{4}')
group by table_name
having count(column_id) != (
select count(column_id) from dba_tab_columns where table_name = 'XP_IMPORT_MW'
);
... although if you're using dba_* or all_* view you should really be including the owner, here and in your procedure.

dbms_out returning column 1: PLS-00428: an INTO clause is expected in SELECT statement

Running this query in sql-developer :
SET SERVEROUTPUT ON
BEGIN
DBMS_OUTPUT.PUT_LINE ('schema > table > key ');
SELECT 'table_name' TABLE_NAME , t.* FROM table_name t ;
END ;
I get this message :
Error report -
ORA-06550: line 4, column 1: PLS-00428: an INTO clause is expected in
this SELECT statement
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action:
while when I run the two statements one by one it works fine.
so why do I get the error and how to avoid it ?
many thanks,
You're confusing SQL and PL/SQL statements, as explained in comments. You can select into something, but you'd either get a single row of data, or select into a collection and then iterate over that manually, as Aramillo showed.
You can use a 'cursor for-loop' to iterate over your rows instead:
SET SERVEROUTPUT ON
BEGIN
DBMS_OUTPUT.PUT_LINE ('schema > table > key ');
FOR rec IN (SELECT 'table_name' TABLE_NAME , t.* FROM table_name t)
LOOP
DBMS_OUTPUT.PUT_LINE (rec.COLUMN_NAME1||','||rec.COLUMN_NAME2);
END LOOP;
END;
/
But given your starting point it's simpler to leave the query as plan SQL and run it after the block:
SET SERVEROUTPUT ON
BEGIN
DBMS_OUTPUT.PUT_LINE ('schema > table > key ');
END;
/
SELECT 'table_name' TABLE_NAME , t.* FROM table_name t;
or in SQL*Plus or SQL Developer, use the client prompt command instead of dbms_output:
prompt schema > table > key
SELECT 'table_name' TABLE_NAME , t.* FROM table_name t;
For example, if you want to print columns COLUMN_NAME of your table, you can do somthing like this:
DECLARE
TYPE TABLE_OBJ IS TABLE OF TABLE_NAME%ROWTYPE;
TABLE_T TABLE_OBJ;
BEGIN
SELECT * BULK COLLECT INTO TABLE_T FROM TABLE_NAME;
FOR i IN 1..TABLE_T.COUNT LOOP
DBMS_OUTPUT.PUT_LINE(TABLE_T(i).COLUMN_NAME1||','||TABLE_T(i).COLUMN_NAME2);
END LOOP;
END;

Resources