PL/SQL take input as table - sql

DECLARE
tablename table;
nor number(10);
BEGIN
tablename:=&tablename;
select count(*) into nor from tablename;
dbms_output.put_line('The number of rows are '||nor);
END;
/
I am using this code to take table name as input from user and displaying the row count but it shows errors but if use a specific table name it runs fine!

DECLARE
tablename table;
nor number(10);
BEGIN
tablename:=&tablename;
execute immediate 'select count(*) from '|| tablename
into nor;
dbms_output.put_line('The number of rows are '||nor);
END;
/
You can try to use EXECUTE IMMDEDIATE

Related

ORACLE SQL CURSOR / FOR LOOP

I need to verify converted data, distinct values and records counts. I would like to write statements so that I can enter a table name, then retrieve it's columns and use them in a query to get its distinct values (the actual values, not just a count of how many distinct) and their count.
I think I need to a CURSOR or CURSOR FOR LOOP and create something like this:
declare
cursor field_name
is
select COLUMN_NAME
from user_tab_cols
where table_name='TABLE1'
c_field_name field_name%ROWTYPE;
BEGIN
OPEN field_name
loop
fetch field_name INTO c_field_name;
exit when field_name%NOTFOUND;
end loop;
CLOSE field_name;
end;
Then run a query using that above in something like
select field_name, count(*)
from table1
group by field_name
Do I need to create 2 loop statements? I've not yet created one and can't quite get the context to get my results so far.
BEGIN
FOR myrow in (select field_name, count(*) as "count" from table1 group by field_name)
loop
dbms_output.put_line(myrow.field_name);
dbms_output.put_line(myrow.count);
end loop;
end;
Considering you will be giving the table name as parameter below code will print all the values of all the columns one by one along with the count of the values
create or replace PROCEDURE PR_PREP(
P_TABLE_NAME IN VARCHAR2)
IS
CURSOR CUR_COLUMNS (PA_TABLE_NAME VARCHAR2)
IS
SELECT COLUMN_NAME FROM ALL_TAB_COLUMNS WHERE TABLE_NAME = PA_TABLE_NAME;
COL_NAMES CUR_COLUMNS%ROWTYPE;
TYPE TYP_RECORD
IS
RECORD
(
FIELD_NAME VARCHAR2(255),
CNT INT);
TYPE TYP_OP_TABLE
IS
TABLE OF TYP_RECORD;
OP_TABLE TYP_OP_TABLE;
I INT;
V_SQL VARCHAR2(2000);
BEGIN
FOR COL_NAMES IN CUR_COLUMNS(P_TABLE_NAME)
LOOP
V_SQL := 'SELECT ' || COL_NAMES.COLUMN_NAME || ' AS FIELD_NAME ,
COUNT(*) AS CNT FROM ' ||
P_TABLE_NAME || ' GROUP BY ' || COL_NAMES.COLUMN_NAME ;
-- DBMS_OUTPUT.PUT_LINE (V_SQL);
EXECUTE IMMEDIATE V_SQL BULK COLLECT INTO OP_TABLE;
dbms_output.put_line('columna name = ' ||COL_NAMES.COLUMN_NAME);
FOR I IN OP_TABLE.FIRST .. OP_TABLE.LAST
LOOP
DBMS_OUTPUT.PUT_LINE('FIELD VALUE '||OP_TABLE(I).FIELD_NAME || ' COUNT = ' || OP_TABLE(I).CNT);
END LOOP;
DBMS_OUTPUT.PUT_LINE('ONE FILED ENDED , NEXT STARTED');
END LOOP;
END;

Query not giving poper output when using cursor

I have a PL/SQL block where I am trying to get the count of filled and not filled values for each column of a table i.e. "demo_table".
select count(*) into v_count from demo_table
where owner='OWNER_1' and(rec.COLUMN_NAME is null OR
REGEXP_LIKE(rec.COLUMN_NAME,'^-$') OR REGEXP_LIKE (rec.COLUMN_NAME,'^-$'));
I am displaying the v_count through dbms_output. But I am not able to get the count.
This is what I am doing:
declare
CURSOR C1 IS
SELECT COLUMN_NAME FROM ALL_TAB_COLUMNS
WHERE TABLE_NAME ='demo_table';
v_count number(10);
begin
for rec in c1 loop
dbms_output.put_line(rec.COLUMN_NAME);
select count(*) into v_count from demo_table
where owner='OWNER_1'
and(rec.COLUMN_NAME is null
OR REGEXP_LIKE(rec.COLUMN_NAME,'^-$')
OR REGEXP_LIKE (rec.COLUMN_NAME,'^-$'));
dbms_output.put_line(v_count);
end loop;
dbms_output.put_line(v_count);
end;

select statement not working with variables, but does with fixed values

So i have this statement:
execute immediate 'SELECT count(*) INTO counter FROM (SELECT table_a.NUMBERWANG FROM table_a MINUS SELECT table_b.NUMBERWANG FROM table_b )';
But if i try and make one of the values into a variable, the statement seems to no longer work.
If it try
execute immediate 'SELECT count(*) INTO counter FROM (SELECT table_a.NUMBERWANG FROM table_a MINUS SELECT table_b.NUMBERWANG FROM ' || variable_1 || ' )';
I get the missing keyword error.
Where it gets unusual is if i remove the "INTO COUNTER" it will run.
Is it my placement of the INTO that is wrong or is it something else entirely?
You can't have an into clause inside the string you are executing.
You need to move this out of the string and tell the execute immediate to do that:
declare
l_count integer;
l_sql varchar(4000);
begin
l_sql := 'SELECT count(*) FROM (SELECT table_a.NUMBERWANG FROM table_a MINUS SELECT table_b.NUMBERWANG FROM table_b )';
execute immediate l_sql into l_count;
end;
/
I don't think you can perform a SELECT...INTO... dynamically. When I try this:
DECLARE
counter NUMBER;
BEGIN
EXECUTE IMMEDIATE 'SELECT COUNT(*) INTO COUNTER FROM TEST_TABLE';
DBMS_OUTPUT.PUT_LINE('COUNTER=' || COUNTER);
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('Error: ' || SQLERRM);
END;
I get ORA-00905: missing keyword. I can get rid of the error by removing the INTO clause, but then of course I still don't get a value into counter.
If you want to execute this sort of statement dynamically and be able to retrieve the value(s) into variables you'll need to use a cursor, as in:
DECLARE
counter NUMBER;
c SYS_REFCURSOR;
BEGIN
OPEN c FOR 'SELECT COUNT(*) FROM TEST_TABLE';
FETCH c INTO counter;
CLOSE c;
DBMS_OUTPUT.PUT_LINE('COUNTER=' || COUNTER);
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('Error: ' || SQLERRM);
END;
Share and enjoy.

select statement not working in procedure

create table Employee(Id number,
Name varchar(20),
Age number,
DId number,
Salary number,
primary key(Id),
foreign key(DId) references Department on delete cascade);
declare
total number;
procedure myFunction(x in number) is
begin
insert into Employee values(17,'Jaskaran Singh',31,1,200000);
dbms_output.put_line('successfully executed');
select * from Employee;
end;
begin
myFunction(3);
end;
To return data from stored procedure, you should create a cursor and return that select like the following:
CREATE OR REPLACE PACKAGE TYPES
AS
TYPE DATA_CURSOR IS REF CURSOR;
END;
then in your code is going to be like:
CREATE OR REPLACE PROCEDURE MYPROC(RESULTSET OUT TYPES.DATA_CURSOR) AS
BEGIN
INSERT INTO EMPLOYEE VALUES(17,'Jaskaran Singh',31,1,200000);
DBMS_OUTPUT.PUT_LINE('successfully executed');
OPEN RESULTSET FOR
SELECT * FROM EMPLOYEE;
END;
The Execution part like
DECLARE THE_RESULT_SET OUT TYPES.DATA_CURSOR;
BEGIN
MYPROC(3, THE_RESULT_SET);
-- You can now get the THE_RESULT_SET and take the result from it...
END;
Important: if you want to print as I understand the other case, you can get that result (same code), and loop whatever you want and print the result from the THE_RESULT_SET
If you want to print what's in the EMPLOYEES table you have loop a cursor over the EMPLOYEES table, printing each row appropriately. Here's an example:
DECLARE
TOTAL NUMBER;
PROCEDURE MYFUNCTION(X IN NUMBER) IS
BEGIN
INSERT INTO EMPLOYEE VALUES(17,'Jaskaran Singh',31,1,200000);
DBMS_OUTPUT.PUT_LINE('successfully executed');
FOR aRow IN (SELECT * FROM EMPLOYEE) LOOP
DBMS_OUTPUT.PUT_LINE('ID=' || aRow.ID ||
' NAME=''' || aRow.NAME || '''' ||
' AGE=' || aRow.AGE ||
' DID=' || aRow.DID ||
' SALARY=' || aRow.SALARY);
END LOOP;
END;
BEGIN
MYFUNCTION(3);
END;
Share and enjoy.

Cursor and table cannot be found

I have a procedure that will select MAX from some tables, but for some reason it is not able to find these tables. Could anybody help me?
declare
varible1 varchar2 (255);
temp varchar2 (255);
last_val number(9,0);
cursor c1 is Select distinct table_name from user_tab_cols order by table_name;
begin
FOR asd in c1
LOOP
temp := asd.table_name;
varible1 := '"'||temp||'"';
select max("id") into last_val from varible1 ;
END LOOP;
end;
For example, the first table name is acceptance_form and for select I need to use "acceptance_form".
Code after edit:
declare
varible1 varchar2 (255);
temp varchar2 (255);
last_val number(9,0);
cursor c1 is Select distinct table_name from user_tab_cols where column_name = 'id';
begin
FOR asd in c1
LOOP
temp := asd.table_name;
execute immediate 'select NVL(max('||'id'||'),0) from "'||varible1||'"' into last_val;
END LOOP;
end;
Can't cuz db is Case sensitive Oracle express 10g tables and rows was created like this
CREATE TABLE "ADMINMME"."acceptance_form"
(
"group_id" NUMBER(9, 0),
"id" NUMBER(4, 0) DEFAULT '0' NOT NULL ,
"is_deleted" NUMBER(4, 0),
"name" NVARCHAR2(30) NOT NULL
);
Can u tell me how to handle exception sequence dosn't exist for this;
Nevermind exception was in wrong block :)
declare
temp varchar2 (255);
last_val number(9,0);
cursor c1 is Select distinct table_name from user_tab_cols where column_name = 'id';
begin
FOR asd in c1
LOOP
temp := asd.table_name;
execute immediate 'select NVL(max("id"),0)+1 from "'||temp||'"' into last_val;
begin
EXECUTE IMMEDIATE 'drop sequence "seq_'|| temp||'"';
EXECUTE IMMEDIATE 'create SEQUENCE "seq_'|| temp ||'" MINVALUE '||last_val||'MAXVALUE 999999999999999999999999999 INCREMENT BY 1 NOCACHE';
EXECUTE IMMEDIATE 'select '||temp||'.nextval from dual';
EXECUTE IMMEDIATE 'ALTER SEQUENCE "seq_'||temp||'" INCREMENT BY 1';
exception when others then
null;
end;
END LOOP;
end;
Dynamic sql doesn't work in that way.
declare
varible1 varchar2 (255);
temp varchar2 (255);
last_val number(9,0);
cursor c1 is Select distinct table_name from user_tab_cols order by table_name;
begin
FOR asd in c1
LOOP
temp := asd.table_name;
begin
execute immediate 'select max(id) from '||temp into last_val;
dbms_output.put_line('max(id) for table: ' ||temp||' = '||last_val);
exception when others then
dbms_output.put_line('Failed to get max(id) for table: ' ||temp);
end;
END LOOP;
end;
You can't use a variable for the table name.
What you can do is creating the complete sql statement as a string and use execute immediate
Here are some examples how to do that: http://docs.oracle.com/cd/B19306_01/appdev.102/b14261/dynamic.htm#CHDGJEGD