Inserting value from VARRAY in pl/SQL DROP query - plsql

I am trying to populate a array through a select query and then dropping values grabbed in select query.
DECLARE
TYPE name_list is varray(20) of VARCHAR2(30);
existingConstraints name_list:=name_list();
BEGIN
SELECT COUNT(1) INTO v_constraint_exists FROM user_constraints
WHERE constraint_name != 'some_value' AND table_name = 'some_value';
for i in NVL(existingConstraints.FIRST,0)..NVL(existingConstraints.LAST,-1) loop
#set($name=existingConstraints(i))
EXECUTE IMMEDIATE 'ALTER TABLE ${some_value} DROP CONSTRAINT ${name} DROP INDEX';
end loop;
END
But i am getting Exception. Can someone suggest me right approach for the same.

`DECLARE
TYPE name_list is varray(20) of VARCHAR2(30);
existingConstraints name_list:=name_list();
BEGIN
SELECT constraint_name INTO existingConstraints FROM user_constraints
WHERE constraint_name != 'some_value' AND table_name = 'some_value' AND constraint_type='U';
for i in NVL(existingConstraints.FIRST,0)..NVL(existingConstraints.LAST,-1) loop
#set($name=existingConstraints(i))
EXECUTE IMMEDIATE 'ALTER TABLE ${tableName} DROP CONSTRAINT ${name} DROP INDEX';
end loop;
END`

I did it in a slightly different way but problem solved, just for the reference.
DECLARE
TYPE name_list is table of VARCHAR2(30);
v_constraint_exists NUMBER;
existingConstraints name_list:=name_list();
dropConstraintName VARCHAR2(30);
BEGIN
SELECT constraint_name bulk collect INTO existingConstraints FROM user_constraints
WHERE constraint_name != 'some_name' AND table_name = 'some_name' AND constraint_type='U';
for i in NVL(existingConstraints.FIRST,0)..NVL(existingConstraints.LAST,-1) loop
dropConstraintName:=existingConstraints(i);
EXECUTE IMMEDIATE 'ALTER TABLE ${tableName} DROP CONSTRAINT '||dropConstraintName||' DROP INDEX';
end loop;
END

Related

oracle plsql procedure dynamic count of the tables in cursor loop

I want to update all the tables having ABC column.Need to skip the tables which doesn't have data.I am having problem in checking the count of the table in a cursor loop.
PLSQL code
create or replace procedure testp is
CURSOR c_testp
IS
SELECT table_name,
column_name
FROM all_tab_columns
WHERE column_name IN('ABC')
ORDER BY table_name;
c int;
BEGIN
FOR table_rec IN c_testp
LOOP
BEGIN
SELECT COUNT(*)
INTO c
FROM table_rec.table_name;
IF(c>0) THEN
query := 'update '||table_rec.table_name||' set '||table_rec.column_name ||'= xyz';
EXECUTE IMMEDIATE query;
COMMIT;
END IF;
EXCEPTION
WHEN no_data_found THEN
dbms_output.put_line('data not found');
WHEN OTHERS THEN
dbms_output.put_line('others');
END;
END LOOP;
END;
In your code, use this:
EXECUTE IMMEDIATE 'SELECT count(*) FROM ' || table_rec.table_name INTO c;
instead of this:
SELECT COUNT(*)
INTO c
FROM table_rec.table_name;
However, as mentioned in comments - there is actually no need to perform that condition check, as no update will be performed when table is empty.

error while executing insert triggers

DROP TRIGGER EPI_BOREHOLE_INI;
CREATE OR REPLACE TRIGGER EPI_BOREHOLE_INI
INSTEAD of Insert ON EPI_BOREHOLE for each row
DECLARE
V_ID number(10);
V_USER varchar2(100);
BEGIN
if (:new.UBHI is null or :new.NAME is null or) then
Raise_Application_Error(-20101, 'Insert failed. The key values of BOREHOLE(UBHI, NAME) cannot be null');
end if;
begin
select BOREHOLE_ID.nextval into V_ID from dual;
SELECT USER INTO V_USER FROM DUAL;
INSERT INTO EPI_BOREHOLE (ID, UBHI, NAME, INSERT_DATE ,INSERT_NAME, UPDATE_DATE,UPDATE_NAME) VALUES (V_ID,:NEW.UBHI, :NEW.NAME, SYSDATE, V_USER, SYSDATE, V_USER);
end;
END;
I see little error in your code: Please see below:
if (:new.UBHI is null or :new.NAME is null or) then <-- An additional OR written.
remove it and try or put one more condition.
I dont see any issue with the code.
Try doing
SET DEFINE OFF

Cursor inside cursor and how pass variable

I need to make two cursors or one cursor and a loop. But one must be inside other. I'm trying with two cursors and with a for but don't recognize me the variable value of name table of the outside cursor.
Could you help me? Could you suggest me the best way to do these? I'm newbie with pl/sql. Thanks. I put the code:
DECLARE
TABLENAME VARCHAR2(30);
LINK VARCHAR2(30);
CURSOR FIRST_SELECT IS
SELECT A.TABLE_NAME AS TABLENAME, B.LINK AS LINK
FROM ALL_TABLES A, TABLE_CONNECT_LINK B
WHERE A.TABLE_NAME=B.COMPARE_TABLE;
BEGIN
OPEN FIRST_SELECT;
LOOP
FETCH FIRST_SELECT INTO TABLENAME,LINK;
EXIT WHEN FIRST_SELECT%NOTFOUND;
DECLARE
PEPELU VARCHAR2(4000);
TABLE VARCHAR2(70);
stringconsult VARCHAR2(4000);
COMPONENTE NUMBER(5);
TABLE_INSERTAR VARCHAR2(30);
COLUMN VARCHAR2(30);
OWNER VARCHAR2(30);
CURSOR ALL IS
SELECT TABLE,COLUMN,OWNER FROM TABLENAME;
BEGIN
OPEN ALL;
LOOP
FETCH ALL INTO TABLE,COLUMN,OWNER;
EXIT WHEN ALL%NOTFOUND;
stringconsult:='select ' || owner||','|| TABLE||','|| COLUMN||' from ' || INSERTNAME || ' minus select owner, table_name, column_name from all_tab_columns#'|| LINK||'';
DBMS_OUTPUT.PUT_LINE(stringconsult || ';');
DBMS_OUTPUT.PUT_LINE('COMMIT;');
COMMIT;
END LOOP;
CLOSE ALL;
END;
END LOOP;
CLOSE FIRST_SELECT;
END;
/

Sequence and Trigger PL/SQL script for Automatic ID generation on a table

Can someone help me fix that code. It doesn´t run on PL/SQL (SQLPLUS #script.sql), giving
SP2-0552: Bind variable "NEW" not declared.
Script.SQL
prompt Creating Table SYSTEMDATALOG;
declare
counter1 integer;
counter2 integer;
begin
SELECT COUNT(*) INTO counter1 FROM ALL_TABLES WHERE TABLE_NAME='SYSTEMDATALOG' AND OWNER='MZMESDB';
if counter1 = 1 then
DROP TABLE SYSTEMDATALOG;
end if;
SELECT COUNT(*) INTO counter2 FROM ALL_SEQUENCES WHERE SEQUENCE NAME='SEQSYSTEMDATALOG';
if counter2 = 1 then
DROP SEQUENCE SEQSYSTEMDATALOGID;
endif;
CREATE TABLE "MZMESDB"."SYSTEMDATALOG" ( "ID" INTEGER NOT NULL ,
"DATETIME" DATE NOT NULL ,
"TYPE" VARCHAR2(64) NOT NULL,
"SEVERITY" INTEGER NOT NULL,
"SOURCE" VARCHAR2(64) NOT NULL,
"USER" VARCHAR2(64) NOT NULL,
"MESSAGE" VARCHAR2(1024), PRIMARY KEY ("ID") VALIDATE );
CREATE SEQUENCE SEQSYSTEMDATALOGID;
CREATE OR REPLACE TRIGGER TRIGSYSTEMDATALOGID
BEFORE INSERT ON SYSTEMDATALOG
FOR EACH ROW
BEGIN
SELECT SEQSYSTEMDATALOGID.NEXTVAL INTO :NEW.ID FROM DUAL;
END TRIGSYSTEMDATALOGID;
end;
/
Thanks in advance for any kind of help.
[DEFINITIVE CODE]
prompt Creating Table SYSTEMDATALOG;
declare
counter1 integer;
counter2 integer;
begin
SELECT COUNT(*) INTO counter1 FROM ALL_TABLES WHERE TABLE_NAME='SYSTEMDATALOG' AND OWNER='MZMESDB';
if counter1 = 1 then
execute immediate 'DROP TABLE SYSTEMDATALOG';
end if;
SELECT COUNT(*) INTO counter2 FROM ALL_SEQUENCES WHERE SEQUENCE_NAME='SEQSYSTEMDATALOG';
IF counter2 = 1 then
execute immediate 'DROP SEQUENCE SEQSYSTEMDATALOGID';
END IF;
execute immediate 'CREATE TABLE "MZMESDB"."SYSTEMDATALOG" (
"ID" INTEGER NOT NULL ,
"DATETIME" DATE NOT NULL ,
"TYPE" VARCHAR2(64) NOT NULL,
"SEVERITY" INTEGER NOT NULL,
"SOURCE" VARCHAR2(64) NOT NULL,
"USER" VARCHAR2(64) NOT NULL,
"MESSAGE" VARCHAR2(1024), PRIMARY KEY ("ID") VALIDATE )';
execute immediate 'CREATE SEQUENCE SEQSYSTEMDATALOGID';
execute immediate 'CREATE OR REPLACE TRIGGER TRIGSYSTEMDATALOGID
BEFORE INSERT ON SYSTEMDATALOG
FOR EACH ROW
BEGIN
SELECT SEQSYSTEMDATALOGID.NEXTVAL INTO :NEW.ID FROM DUAL;
END TRIGSYSTEMDATALOGID;';
end;
One problem is that you are mixing PL/SQL (an anonymous PL/SQL block) and DDL. While you can write DML statements (SELECT/INSERT/UPDATE/DELETE) in PL/SQL you cannot write DDL (CREATE/DROP etc) directly in PL/SQL.
You need to either run your DDL statements outside the anonymous PL/SQL block or use
EXECUTE IMMEDIATE '<statement>';.
As for the error on :NEW I think it will disappear when you fix the other issue. If it doesn't, try adding:
SET SCAN OFF
In the beginning of your SQL*PlUS file.

opening implicit cursor with for loop

I have a stored procedure that has following pl/sql block. This block was using select query in for statement but i need to change that static variable to dynamic query. As I changed that it has error. Is there any way to use variable with FOR LOOP in implicit cursor.
declare
sql_query varchar2(32767) := 'select ctlchar ';
kpiNameQuery varchar2(600);
isWg boolean := true;
begin
IF isWG then
kpiNameQuery := 'select distinct KPI_NAME from weeklykpi where kpi_name in (select kpi_wg from auxillary.kpi_types) order by 1';
Else
kpiNameQuery := 'select distinct KPI_NAME from weeklykpi where kpi_name in (select kpi_wg1 from auxillary.kpi_types) order by 1';
End IF;
for KPI_NAME in kpiNameQuery
loop
sql_query := sql_query || ' , min(case when KPI_NAME = '''||x.KPI_NAME||''' then KPI_VALUE end) as '||x.KPI_NAME;
dbms_output.put_line(sql_query);
end loop;
end;
You can achieve similar functionality with the following using cursor
declare
type t_cursor is ref cursor;
c_cursor t_cursor;
l_sql varchar2(512);
l_var number;
begin
l_sql := 'select count(*) from emp'; -- do dynamic check before here for
-- correct sql
open c_cursor for l_sql;
loop
fetch c_cursor
into l_var;
exit When c_cursor%notfound;
DBMS_OUTPUT.put_line ('val '||l_var);
end loop;
close c_cursor;
end;
Unfotunately no, the doc states:
If the dynamic SQL statement is a SELECT statement that returns multiple rows, native dynamic SQL gives you these choices:
Use the EXECUTE IMMEDIATE statement with the BULK COLLECT INTO clause.
Use the OPEN FOR, FETCH, and CLOSE statements.
So you will have to use a REF cursor (or EXECUTE IMMEDIATE and loop over the results).
Incidentally, in your case you could go for static SQL and have comparable performance:
BEGIN
FOR cc IN (SELECT DISTINCT KPI_NAME
FROM weeklykpi
WHERE kpi_name IN (SELECT CASE WHEN l_variable = 1
THEN kpi_wg
ELSE kpi_wg1
END
FROM auxillary.kpi_types) LOOP
ORDER BY 1
-- do something
END LOOP;
END;
You'll have to use some other type than boolean though since it's unknown to SQL.

Resources