How to show the full result of the query in SQL Developer? - sql

I want to see the query used to create the table DOCTORS in SQL Developer with
SELECT dbms_metadata.get_ddl('TABLE', 'DOCTORS')
FROM dual;
Then it shows only part of the query.
DBMS_METADATA.GET_DDL('TABLE','DOCTORS')
--------------------------------------------------------------------------------
CREATE TABLE "C##AKIRA"."DOCTORS"
( "CODED" NUMBER(2,0),
"NAMED" VARCHA
I suspect this is due to some displaying setting. Could you please elaborate on how to show the full result?
-- Drop tables if they already exist
BEGIN
EXECUTE IMMEDIATE 'DROP TABLE works_in';
EXCEPTION
WHEN OTHERS THEN
IF SQLCODE != -942 THEN
RAISE;
END IF;
END;
/
BEGIN
EXECUTE IMMEDIATE 'DROP TABLE depends';
EXCEPTION
WHEN OTHERS THEN
IF SQLCODE != -942 THEN
RAISE;
END IF;
END;
/
BEGIN
EXECUTE IMMEDIATE 'DROP TABLE wards';
EXCEPTION
WHEN OTHERS THEN
IF SQLCODE != -942 THEN
RAISE;
END IF;
END;
/
BEGIN
EXECUTE IMMEDIATE 'DROP TABLE doctors';
EXCEPTION
WHEN OTHERS THEN
IF SQLCODE != -942 THEN
RAISE;
END IF;
END;
/
-- Create the doctors database
CREATE TABLE doctors (
coded NUMBER(2),
named VARCHAR2(15),
speciald NUMBER(2),
PRIMARY KEY (coded)
);
CREATE TABLE wards (
codew NUMBER(2),
namew VARCHAR2(15),
coded NUMBER(2),
PRIMARY KEY(codew),
FOREIGN KEY (coded) REFERENCES doctors (coded)
);
CREATE TABLE works_in (
coded NUMBER(2),
codew NUMBER(2),
datewi DATE,
hourcount NUMBER(2),
PRIMARY KEY (coded, codew, datewi),
FOREIGN KEY (coded) REFERENCES doctors (coded),
FOREIGN KEY (codew) REFERENCES wards (codew)
);
CREATE TABLE depends (
codew_parent NUMBER(2),
codew_child NUMBER(2),
PRIMARY KEY (codew_parent, codew_child),
FOREIGN KEY (codew_parent) REFERENCES wards (codew),
FOREIGN KEY (codew_child) REFERENCES wards (codew)
);
-- Show the schema of a table
SELECT dbms_metadata.get_ddl('TABLE', 'DOCTORS')
FROM dual;

try putting
set long 1000000 longc 100000 pages 10000
before the select dbms_metadata....
It tells sqldev (and sqlplus/sqlcl also) to fetch 1MB of data and not put headers until after 10000 lines

Related

Found the symbol "CREATE" instead of

CREATE OR REPLACE PROCEDURE P_DUP_DEL_CREATE_TAB IS
BEGIN
CREATE OR REPLACE TABLE T_DUPLICATE_TABLE (
F_NUMBER NUMBER(2),
S_NUMBER NUMBER(1),
CONSTRAINT ID PRIMARY KEY (F_NUMBER, S_NUMBER)
);
END P_DUP_DEL_CREATE_TAB;
I don't know why it gives me this error:
Error(3,3): PLS-00103: Found the symbol "CREATE" instead of one of the following: ( begin case declare exit for goto if ...
I tried using the backslash, but it doesn't solve the problem, any help?
You cannot use DDL statements in PL/SQL. You need to use EXECUTE IMMEDIATE and cannot use CREATE OR REPLACE:
CREATE OR REPLACE PROCEDURE P_DUP_DEL_CREATE_TAB
IS
TABLE_DOES_NOT_EXIST EXCEPTION;
PRAGMA EXCEPTION_INIT(TABLE_DOES_NOT_EXIST, -942);
BEGIN
EXECUTE IMMEDIATE 'TRUNCATE TABLE T_DUPLICATE_TABLE';
EXCEPTION
WHEN TABLE_DOES_NOT_EXIST THEN
EXECUTE IMMEDIATE 'CREATE TABLE T_DUPLICATE_TABLE (
F_NUMBER NUMBER(2),
S_NUMBER NUMBER(1),
CONSTRAINT ID PRIMARY KEY (F_NUMBER, S_NUMBER)
)';
END P_DUP_DEL_CREATE_TAB;
/
db<>fiddle here

ORA-04091: table name is mutating - when trigger from child table wants to update parent table

I have 2 simple tables:
CREATE TABLE ORDERS
( ORDER_KEY number(10) NOT NULL,
ORDER_NR varchar2(50) NOT NULL,
LAST_UPDATE DATE,
CONSTRAINT ORDERS_PK PRIMARY KEY (ORDER_KEY)
);
CREATE TABLE ORDER_POSITIONS
( ORDER_POS_KEY number(10) NOT NULL,
ORDER_POS_NR number(10),
ORDER_POS_DESCRIPTION varchar2(50),
ORDER_KEY NUMBER(10) NOT NULL,
CONSTRAINT ORDER_POSITIONS_PK PRIMARY KEY (ORDER_POS_KEY),
CONSTRAINT ORDERS_FK
FOREIGN KEY (ORDER_KEY)
REFERENCES ORDERS(ORDER_KEY)
ON DELETE CASCADE
);
On the table ORDER_POSITIONS I created a trigger which should update the column LAST_UPDATE whenever a position is deleted.
CREATE OR REPLACE TRIGGER TGAUDIT_ORDER_POS
AFTER DELETE
ON ORDER_POSITIONS
FOR EACH ROW
DECLARE
BEGIN
UPDATE ORDERS O SET O.LAST_UPDATE = SYSDATE WHERE O.ORDER_KEY = :OLD.ORDER_KEY;
END;
If I delete a position from the table ORDER_POSITION, everything is working fine (the column LAST_UPDATE is updated).
However, if I want to delete an order, all its positions are gonna be deleted, too (via CASCADE DELETE). At this moment also the trigger on the table ORDER_POSITIONS is being raised and it wants to update the column of the table which is currently being deleted - ORDERS. Obviously I get here the error : ORA-04091 Table ORDERS is mutating.
Is there a way to get it solved?
I solved it finally using a compound trigger:
CREATE OR REPLACE TRIGGER TGAUDIT_ORDER_POS
FOR DELETE ON ORDER_POSITIONS
COMPOUND TRIGGER
TYPE parent_key_type IS TABLE OF ORDERS.ORDER_KEY%TYPE;
parent_keys parent_key_type := parent_key_type();
AFTER EACH ROW IS BEGIN
IF DELETING THEN
BEGIN
parent_keys.extend;
parent_keys(parent_keys.last) := :old.ORDER_KEY;
END;
END IF;
END AFTER EACH ROW;
AFTER STATEMENT IS BEGIN
FOR i IN 1..parent_keys.count LOOP
UPDATE DEVART_TEST.ORDERS O SET O.LAST_UPDATE = SYSDATE WHERE O.ORDER_KEY = parent_keys(i);
END LOOP;
END AFTER STATEMENT;
END;
UPDATE: Another option would be to catch this specific exception within the regular trigger.
CREATE OR REPLACE TRIGGER TGAUDIT_ORDER_POS
AFTER DELETE
ON ORDER_POSITIONS
FOR EACH ROW
DECLARE
TABLE_MUTATING EXCEPTION;
PRAGMA EXCEPTION_INIT(TABLE_MUTATING, -4091 );
BEGIN
UPDATE ORDERS O SET O.LAST_UPDATE = SYSDATE WHERE O.ORDER_KEY = :OLD.ORDER_KEY;
EXCEPTION
WHEN TABLE_MUTATING THEN
NULL; -- suppress
END;
I would recreate the foreign-key constraint without the ON DELETE CASCADE clause and delete all order positions before deleting an order. That way you avoid the mutating table error by not having two tables mutating at the same time.

Change/replace the value of a variable dynamically- oracle

I have set of sql statements (create table, views, sequences), Where my schema name changes all the time and rest of the sql be the same.
Even in schema name a part of it has to change, for example:
I have a schema name ABC_XYZ, i would like to change this schema name to ABC_DEF_XYZ.
For this i tried to insert a variable in the schema name like ABC_&var1_XYZ. If i pass the variable in the schema name as shown here (ABC_&var1_XYZ) and pass the value to the variable, It ask me to declare the vaue of the variable.
I have given the error and the code i use below:
Error report -
ORA-06550: line 5, column 52:
PLS-00201: identifier 'REL4' must be declared
ORA-06550: line 5, column 1:
PL/SQL: Statement ignored
ORA-06550: line 7, column 51:
PLS-00201: identifier 'REL4' must be declared
here is my create statement:
set echo off
set verify off
undefine mySchemaPart
declare
vSQL varchar2(32767);
begin
vSQL:= 'begin EXECUTE IMMEDIATE alter table ABC_'||&&mySchemaPart||'_OWNER.TEST drop constraint EMPLOYEE_ID_FK; EXCEPTION when others then if (SQLCODE != -02443 and SQLCODE != -942) then RAISE; end if; end';
execute immediate vSQL;
vSQL:= 'begin EXECUTE IMMEDIATE drop table ABC_'||&mySchemaPart||'_OWNER.TEST cascade constraints PURGE; EXCEPTION when others then if SQLCODE != -942 then RAISE; end if; end';
execute immediate vSQL;
vSQL:= 'create table ABC_'||&mySchemaPart||'OWNER.TEST
(
EMPLOYEE_ID NUMBER(19) not null,
LAST_UPDT_DT DATE not null,
)';
execute immediate vSQL;
vSQL:= 'CREATE OR REPLACE SYNONYM ABC_USER.TEST FOR ABC_'||&mySchemaPart||'OWNER.TEST';
execute immediate vSQL;
vSQL:= 'begin EXECUTE IMMEDIATE alter table ABC_'||&mySchemaPart||'OWNER.TEST
add constraint EMPLOYEE_ID_FK foreign key (EMPLOYEE_ID)
references ABC_OWNER.GDSD (EMPLOYEE_ID); EXCEPTION when others then if (SQLCODE != -02443 and SQLCODE != -02275) then RAISE; end if; end';
execute immediate vSQL;
end;
/
Is there any other way i can try to insert my value in this schema.
You can use dynamic SQL to handle a varying schema in your DDL; for example:
accept mySchemaPart PROMPT "Schema part: "
declare
vMySchema varchar2(30) := 'ABC_' || '&mySchemaPart' || '_XYZ';
vSQL varchar2(32767);
begin
vSQL := 'create table ' || vMySchema || '.tableName (...)';
execute immediate vSQL;
end;
/
Pass it as 'ABC_||'&var1||'_XYZ'
An example of insert statement;
insert into test (a)
select 'ABC_'||&var1||'_XYZ' from dual ;
On execution it will ask for prompt.
As a block you can use this:
declare
var varchar2(100);
begin
var:='create table ABC_'||&var1||'_XYZ.tablnam(a number)'; --add your columns
dbms_output.put_line(var);
execute immediate var;
end;
As per #bin request his/her statments:
declare
var varchar2(500);
begin
var:='create table ABC_'||&var||'_OWNER.TEST(EMPLOYEE_ID NUMBER(19) not null, LAST_UPDT_DT DATE not null )';
--Table Created
dbms_output.put_line(var);
execute immediate var;
var:='alter table ABC_'||&var1||'_OWNER.TEST add constraint EMPLOYEE_ID_FK foreign key (EMPLOYEE_ID) references ABC_OWNER.GDSD(EMPLOYEE_ID)';
--Constraint Added
dbms_output.put_line(var);
execute immediate var;
var:='CREATE OR REPLACE SYNONYM ABC_USER.TEST FOR ABC_'||&var1||'_OWNER.TEST';
--Synonym Created
dbms_output.put_line(var);
execute immediate var;
var:='alter table ABC_'||&var1||'_OWNER.TEST drop constraint EMPLOYEE_ID_FK';
--Constraint Dropped
dbms_output.put_line(var);
execute immediate var;
var:='drop table ABC_'||&var1||'_OWNER.TEST cascade constraints PURGE';
--Table Dropped
dbms_output.put_line(var);
execute immediate var;
Exception
WHEN others then
dbms_output.put_line('Error--'||sqlerrm||'-'||sqlcode);
end;
Output:
SQL> declare
var varchar2(100);
begin
var:='create table ABC_'||&var1||'OWNER.TEST(EMPLOYEE_ID NUMBER(19) not null, LAST_UPDT_DT DATE not null )';
'
'
'
dbms_output.put_line(var);
execute immediate var;
end;
Enter value for var1: 'REL4'
create table ABC_REL4_OWNER.TEST(EMPLOYEE_ID NUMBER(19) not null, LAST_UPDT_DT DATE not null )
Table created.
alter table ABC_REL4_OWNER.TEST add constraint EMPLOYEE_ID_FK foreign key (EMPLOYEE_ID) references ABC_OWNER.GDSD(EMPLOYEE_ID)
Table altered.
CREATE OR REPLACE SYNONYM ABC_USER.TEST FOR ABC_REL4_OWNER.TEST
Synonym created.
alter table ABC_REL4_OWNER.TEST drop constraint EMPLOYEE_ID_FK
Table altered.
drop table ABC_REL4_OWNER.TEST cascade constraints PURGE
Table dropped.

trigger to override the message to error(ORA-02292)

I want override the message that generate error (ORA-02292).
It is message like that
ORA-02292: integrity constraint (IVANKA.FK_SUPPLIER) violated - child record found
I want a trigger to override the above message to his example on this (MY override :))
I tried do like that
for first create table
CREATE TABLE supplier
( supplier_id numeric(10) not null,
supplier_name varchar2(50) not null,
contact_name varchar2(50),
CONSTRAINT supplier_pk PRIMARY KEY (supplier_id)
);
CREATE TABLE products
( product_id numeric(10) not null,
supplier_id numeric(10) not null,
CONSTRAINT fk_supplier
FOREIGN KEY (supplier_id)
REFERENCES supplier (supplier_id)
);
then insert data
INSERT INTO supplier
(supplier_id, supplier_name, contact_name)
VALUES (1000, 'Microsoft', 'Bill Gates');
INSERT INTO products
(product_id, supplier_id)
VALUES (50000, 1000);
then do trigger
create or replace trigger sup_z
after delete on supplier
for each row
declare
v_error_constraint exception;
pragma exception_init(v_error_constraint, -2292);
begin
null;
exception
When v_error_constraint then
raise_application_error(-20001,
'My ovvervide:)');
End;
then do delete to generate message
DELETE from supplier
WHERE supplier_id = 1000
but I see not my message in trigger I see
ORA-02292: integrity constraint (IVANKA.FK_SUPPLIER) violated - child record found
Can you help me? What am I doing wrong?
Your trigger is fired after the DELETE has been done, so it will never fire if the DELETE gives an error.
You could use a BEFORE trigger to avoid the DELETE, if you find some child records; for example:
create or replace trigger sup_z
before delete on supplier
for each row
declare
vNumberOfChild number;
begin
select count(1)
into vNumberOfChild
from products
where supplier_id = :old.supplier_id;
--
if vNumberOfChild > 0 then
raise_application_error(-20001, 'My ovveride:)');
end if;
End;
Another way could be defining a procedure to handle the delete:
SQL> create or replace procedure deleteSupplier(p_id in numeric) is
2 vNumberOfChild number;
3 begin
4 select count(1)
5 into vNumberOfChild
6 from products
7 where supplier_id = p_id;
8 --
9 if vNumberOfChild > 0 then
10 dbms_output.put_line('My ovveride');
11 else
12 delete supplier
13 where supplier_id = p_id;
14 end if;
15 end;
16 /
Procedure created.
SQL> set serveroutput on
SQL> exec deleteSupplier(1000);
My ovveride
PL/SQL procedure successfully completed.
This avoids running the delete checking the data before, so you need no triggers.
Check this out (Display custom message when constraint is violated PL/SQL). I think you want something similar.
When all you need is just the message to be printed, why do we need a trigger in the first place? Shouldn't we be handling this just with an exception alone?
declare
v_error_constraint exception;
pragma exception_init(v_error_constraint, -2292);
begin
DELETE from supplier
WHERE supplier_id = 1000;
exception
When v_error_constraint then
raise_application_error(-20001,
'My ovvervide:)');
End;

SQL trigger to limit the number of users

I'm still learning how to use SQL, and I need some help creating this database.
I've created the following tables:
create table Worker
(Num_Worker number(20) PRIMARY KEY,
Name varchar2(30),
ID number(8),
Password varchar2(20));
create table Area
(Code_Area number(10) PRIMARY KEY,
Name varchar2(30),
Current_workers number(2)
Max_workers number(2));
create table Timetable
(ID_Timetable number(10) PRIMARY KEY,
Time_Entrance date,
Time_Exit date,
Code_Area number(10),
Num_Worker number(20),
Foreign Key (Num_Worker) references Worker(Num_Worker),
Foreign Key (Code_Area) references Area(Code_Area));
Supposedly, each worker can choose a area to work at, but each area has a limit or workers at the same time.
What would happen is a worker would create a new timetable, but before that timetable is created it should check the area that he chose to check if the "Current_workers" is the same value as "Max_workers", and if it is it shouldn't let it happen.
I've been trying to create a trigger for that, but I've had no luck in finding the correct syntax for it, and I'm not sure how to do it either, or if there's a better way to do it than with a trigger.
This is all I've done so far:
create trigger limit_worker_per_zone
before insert
on Timetable
for each row
as
BEGIN
if (select Current_Workers from Area) >= (select Max_workers from Area) <-Not sure...
BEGIN
???
END
END
I'd really appreciate if you can help me in this. I'll still be looking for more info myself meanwhile, but the more help the better.
CREATE TRIGGER limit_worker_per_zone
BEFORE INSERT
ON Timetable
FOR EACH ROW
DECLARE
v_total NUMBER;
BEGIN
BEGIN
SELECT max_workers - current_workers
INTO v_total
FROM Area
WHERE Code_Area = :NEW.Code_Area;
exception when no_data_found then
v_total := 1;
END;
IF v_total <= 0 THEN
raise_application_error(990000, 'workers full for this area');
END IF;
END limit_worker_per_zone;
Try this as a starting point:
CREATE OR REPLACE TRIGGER LIMIT_WORKER_PER_ZONE
BEFORE INSERT ON TIMETABLE
FOR EACH ROW
AS
nCurrent_workers NUMBER;
nMax_workers NUMBER;
BEGIN
SELECT CURRENT_WORKERS,
MAX_WORKERS
INTO nCurrent_workers,
nMax_workers
FROM AREA
WHERE CODE_AREA = :NEW.CODE_AREA;
IF nCurrent_workers = nMax_workers THEN
NULL; -- add code here to do the appropriate thing when the area is already full
ELSE
NULL; -- add code here to to the appropriate thing if the area is not full
END IF;
END LIMIT_WORKER_PER_ZONE;
I'll leave it to you to flesh this out.
Share and enjoy.