Problems creating a trigger in Oracle 11g - triggers

I get a weird error while trying to create a trigger in my Oracle 11g database using SQL Developer. Here is what I did:
My table:
CREATE TABLE COUNTRY_CODE(
ID NUMBER(19,0) PRIMARY KEY NOT NULL,
Code VARCHAR2(2) NOT NULL,
Description VARCHAR2(50),
created TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
created_by VARCHAR2(40) DEFAULT USER,
last_updated TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
last_updated_by VARCHAR2(40) DEFAULT USER,
archived CHAR(1) DEFAULT '0' NOT NULL );
The Sequence:
CREATE SEQUENCE COUNTRY_CODE_ID_SEQ START WITH 1 INCREMENT BY 1;
The trigger:
CREATE OR REPLACE TRIGGER COUNTRY_CODE_TRIGGER
BEFORE INSERT ON COUNTRY_CODE
FOR EACH ROW
DECLARE
max_id number;
cur_seq number;
BEGIN
IF :new.id IS NULL THEN
SELECT COUNTRY_CODE_ID_SEQ.nextval
INTO :new.id
FROM dual;
ELSE
SELECT GREATEST(NVL(MAX(id),0), :new.id)
INTO max_id
FROM COUNTRY_CODE;
SELECT COUNTRY_CODE_ID_SEQ.nextval
INTO cur_seq
FROM dual;
WHILE cur_seq < max_id
LOOP
SELECT COUNTRY_CODE_ID_SEQ.nextval
INTO cur_seq
FROM dual;
END LOOP;
END IF;
END;
Creating the table and the sequence works very well, but when I try to create my trigger, I get this error:
Error report:
ORA-00603: ORACLE server session terminated by fatal error
ORA-00600: internal error code, arguments: [kqlidchg0], [], [], [], [], [], [], [], [], [], [], []
ORA-00604: error occurred at recursive SQL level 1
ORA-00001: unique constraint (SYS.I_PLSCOPE_SIG_IDENTIFIER$) violated
00603. 00000 - "ORACLE server session terminated by fatal error"
*Cause: An ORACLE server session is in an unrecoverable state.
*Action: Login to ORACLE again so a new server session will be created
Does anyone know about this error?
Thanks

I finally found the answer to my problem:
Add this:
ALTER SESSION SET PLSCOPE_SETTINGS = 'IDENTIFIERS:NONE';
Or in Oracle SQL Developer:
Go to Tools | Preferences
Select Database | PL/SQL Compiler
Change the PLScope identifiers from All to None
Click on Ok
This fixes the issue...

There may be a solution for this here.

I have no other solution (and don't have the reputation to merely comment), but here is some information that might help get someone on the right track to solving this problem while still using PL/Scope.
I just had a similar issue, and looking into the PL/Scope feature helped me understand where the problem might come in. For my issue, I tried to create a trigger and the same exact error came up. I changed the body of the trigger to no avail, but changing the name worked fine.
It seems the the PL/Scope was holding onto information about the first instantiated trigger, before dropping it. A query on the triggers revealed my trigger was surely dropped, but a query on the (PL/Scope) identifiers ("all_identifiers") showed it was still there.
Some information on PL/Scope is here:
http://www.oracle.com/technetwork/testcontent/o67asktom-101004.html
Chapter 8 here (11g documentation) has more information:
http://docs.oracle.com/cd/B28359_01/appdev.111/b28424.pdf

Related

IF statement is not accepted in MySQL trigger, issuing Code 1064 but no reference into the statement

I'm using MariaDB (10.3.29-MariaDB-0+deb10u1) and DbVisualizer (Pro 12.1.1 [Build #3237]) as an IDE.
I want to manage the primary key of a table by having MariaDB set the key to a UUID, I started with this
CREATE TRIGGER before_pkey_maintenance
BEFORE INSERT ON maintenance
FOR EACH ROW
SET NEW.pkey = uuid();
which worked perfectly, except that I started providing my own UUIDs, which the trigger over-wrote, of course. I tried the following to create a UUID only if one was not provided:
CREATE TRIGGER before_pkey_maintenance
BEFORE INSERT ON maintenance
FOR EACH ROW
IF NEW.pkey IS NULL THEN
SET NEW.pkey = uuid();
END IF;
The problem is, when I execute the create, I get the following error:
[Code: 1064, SQL State: 42000] (conn=1002) You have an error in your SQL syntax;
check the manual that corresponds to your MariaDB server version for the right syntax
to use near '' at line 5 [Script position: 132 - 168]
Error 1064 is documented (https://riptutorial.com/mysql/example/2995/error-code-1064--syntax-error) as not correctly using back-ticks, which I can deal with ... except that the message is referring to "syntax to use near '' at line 5", the empty string in the message is less than helpful.
I found found MySQL Trigger with IF statement returning #1064, which adds the use of "delimiter" and tried "|", "//", and "$$" as delimiters. I've tried MANY variations, all similar to the following:
delimiter $$
CREATE TRIGGER before_pkey_maintenance
BEFORE INSERT ON maintenance
FOR EACH ROW
IF NEW.pkey IS null THEN
SET NEW.pkey = uuid();
END IF;
END
$$
delimiter ;
... but none of them worked.
I've looked through DbVisualizer's docs and found nothing that indicates it performs "magic" behind the scenes, but I suspect that if any of the above is correct that DbVis is executing these separately.
Basically You have nor error. Copy the code from the example and use it and you will get any error anymore, you might have some kind of invisible character so delete every thing. and use theis code
CREATE tABLE maintenance (pkey VARCHAR(36))
CREATE TRIGGER before_pkey_maintenance
BEFORE INSERT ON maintenance
FOR EACH ROW
IF NEW.pkey IS null THEN
SET NEW.pkey = uuid();
END IF;
END
INSERT INTO maintenance VALUES (NULL)
✓
SELECT * FROM maintenance
| pkey |
| :----------------------------------- |
| c973e92c-3a6f-11ec-93bc-00163e55bd17 |
db<>fiddle here
here is a Version with DELIMITER
delimiter $$
CREATE TRIGGER before_pkey_maintenance
BEFORE INSERT ON maintenance
FOR EACH ROW
IF NEW.pkey IS null THEN
SET NEW.pkey = uuid();
END IF;
END
$$
delimiter ;
I found this https://mariadb.com/kb/en/trigger-keeps-creating-error/, which led to my solution:
CREATE TRIGGER before_pkey_maintenance
BEFORE INSERT ON maintenance
FOR EACH ROW
SET new.pkey = IF (NEW.pkey is null or NEW.pkey = '', uuid(), NEW.pkey);
Even though this works for this situation, it is not a complete answer because it is not suitable if the trigger needs to execute more complex code.
This is, in fact, a "feature" of dbvisualizer.
The page https://confluence.dbvis.com/display/UG121/Executing+Complex+Statements
describes how to deal with it, the key point is added an '#' to the delimiter statement and the semicolon:
#delimiter $$;
CREATE TRIGGER before_pkey_maintenance
BEFORE INSERT ON maintenance
FOR EACH ROW
IF NEW.pkey IS null THEN
SET NEW.pkey = uuid();
END IF;
$$
#delimiter ;
The DbVis page basically states that it is a level of abstraction above SQL and needs the extended syntax so that it can delimit parts of a more complex script.

Not able to drop schema in DB2 Using ADMIN_DROP_SCHEMA Stored Procedure

I found at several places to be able to drop a schema in DB2 along with all of its contents (indexes, SPs, triggers, sequences etc) using
CALL SYSPROC.ADMIN_DROP_SCHEMA('schema_name', NULL, 'ERRORSCHEMA', 'ERRORTAB');
However, I am getting the following error while using this command:
1) [Code: -469, SQL State: 42886] The parameter mode OUT or INOUT is not valid for a parameter in the routine named "ADMIN_DROP_SCHEMA" with specific name "ADMIN_DROP_SCHEMA" (parameter number "3", name "ERRORTABSCHEMA").. SQLCODE=-469, SQLSTATE=42886, DRIVER=4.22.29
2) [Code: -727, SQL State: 56098] An error occurred during implicit system action type "2". Information returned for the error includes SQLCODE "-469", SQLSTATE "42886" and message tokens "ADMIN_DROP_SCHEMA|ADMIN_DROP_SCHEMA|3|ERRORTABSCHEMA".. SQLCODE=-727, SQLSTATE=56098, DRIVER=4.22.29
Can anyone help me suggest what's wrong here? I tried to look at several places but didn't get any idea. It doesn't seem it's an authorization issue. Using DB2 version 11.5.
You are using the ADMIN_DROP_SCHEMA procedure parameters incorrectly, assuming you are CALLing the procedure from SQL and not the CLP.
The third and fourth parameters cannot be a literal (despite the documentation giving such an example), instead they must be host-variables (because the the procedure requires them to be input/output parameters).
If the stored-procedure completes without errors it sets these parameters to NULL. so your code should check for this.
If the stored-procedure detects errors, it creates and adds rows to the specified table and leaves the values of these parameters unchanged, and you must then query that table to list the error(s). You should drop this table before calling the stored procedure otherwise the procedure will fail with -601.
Example:
--#SET TERMINATOR #
drop table errschema.errtable#
set serveroutput on#
begin
declare v_errschema varchar(20) default 'ERRSCHEMA';
declare v_errtab varchar(20) default 'ERRTABLE';
CALL SYSPROC.ADMIN_DROP_SCHEMA('SOMESCHEMA', NULL, v_errschema, v_errtab);
if v_errschema is null and v_errtab is null
then
call dbms_output.put_line('The admin_drop_schema reported success');
else
call dbms_output.put_line('admin_drop_schema failed and created/populated table '||rtrim(v_errschema)||'.'||rtrim(v_errtab) );
end if;
end#
You can use global variables if you would like to use ADMIN_DROP_SCHEMA outside of compound SQL
E.g.
CREATE OR REPLACE VARIABLE ERROR_SCHEMA VARCHAR(128) DEFAULT 'SYSTOOLS';
CREATE OR REPLACE VARIABLE ERROR_TAB VARCHAR(128) DEFAULT 'ADS_ERRORS';
DROP TABLE IF EXISTS SYSTOOLS.ADS_ERRORS;
CALL ADMIN_DROP_SCHEMA('MY_SCHEMA', NULL, ERROR_SCHEMA, ERROR_TAB);

PostgreSQL: Creating a Trigger that tries to do work on a non existing table

as we start to migrate our Application from using Oracle to PostgreSQL we ran into the following problem:
A lot of our Oracle scripts create triggers that work on Oracle specific tables which dont exist in PostgreSQL. When running these scripts on the PG database they will not throw an error.
Only when the trigger is triggered an error is thrown.
Example code:
-- Invalid query under PostgreSQL
select * from v$mystat;
-- Create a view with the invalid query does not work (as expected)
create or replace view Invalid_View as
select * from v$mystat;
-- Create a test table
create table aaa_test_table (test timestamp);
-- Create a trigger with the invalid query does(!) work (not as expected)
create or replace trigger Invalid_Trigger
before insert
on aaa_test_table
begin
select * from v$mystat;
end;
-- Insert fails if the trigger exists
insert into aaa_test_table (test) values(sysdate);
-- Select from the test table
select * from aaa_test_table
order by test desc;
Is there a way to change this behavior to throw an error on trigger creation instead?
Kind Regards,
Hammerfels
Edit:
I was made aware, that we actually dont use basic PostgreSQL but EDB instead.
That would probably explain why the syntax for create trigger seems wrong.
I'm sorry for the confusion.
It will trigger an error, unless you have configured Postgres to postpone validation when creating functions.
Try issuing this before creating the trigger:
set check_function_bodies = on;
Creating the trigger should show
ERROR: syntax error at or near "trigger"
LINE 1: create or replace trigger Invalid_Trigger

postgresql error: 'schema "" does not exist' on temporary table

I'm finding that this rather simple postgresql 9.6 function
CREATE OR REPLACE FUNCTION public.trying_to_index_me()
RETURNS VOID AS
$BODY$
BEGIN
CREATE TABLE public.table_to_index (
id INTEGER NOT NULL,
this_id UUID NOT NULL,
that_id smallint NOT NULL,
CONSTRAINT idx_table_to_index_unique
UNIQUE (id,this_id,that_id)
);
CREATE INDEX idx_table_to_index_thisthat ON public.table_to_index(this_id,that_id);
DROP TABLE public.table_to_index;
END;
$BODY$ LANGUAGE plpgsql;
--SELECT public.trying_to_index_me();
is resulting in a schema "" does not exist error. The exact error is:
ERROR: schema "" does not exist
SQL state: 3F000
Context: SQL statement "CREATE INDEX idx_table_to_index_thisthat
ON public.table_to_index(this_id,that_id)"
PL/pgSQL function trying_to_index_me() line 10 at SQL statement
and occurs reliably on the second and subsequent executions. Cut/Pasting the above SQL chunk reproduces the error...for me. Quite interested if that's not the case for you. I have the following clues:
The schema detected in the error message varies. Mostly it is reported as "", but others like "0MA{Start of Text} " or some snippet of sql statement/comment from a previous statement in the transaction. Sounds memory pointer related.
It will error consistently once its in.
I find that if I CREATE OR REPLACE the function, I'll get one execution and then the errored state will occur again.
I find that if I open a new pgadminIII window (without dropping or recreating), I'll get the same one execution and then the errored state will occur again...regardless of if it was errored in a different window. Sounds connection related.
I find that commenting out the creation of either idx_temp_data_to_index_thisthat or idx_temp_data_to_index_unique resolves the issue.
Occurs in both "PostgreSQL 9.5.3 on x86_64-pc-linux-gnu, compiled by gcc (GCC) 4.4.7 20120313 (Red Hat 4.4.7-16), 64-bit" and in the 9.6 implementation.
If the above function is executed from another function, the CREATE OR REPLACE FUNCTION 1-time resolve above does not work on the parent function, only when replacing the child function. And doesn't matter if that occurs in a separate pgadmin window. PSounds like neither the client or the transaction.
Truly appreciate your thoughts.
I think a comma is missing after that_id smallint NOT NULL
CREATE OR REPLACE FUNCTION trying_to_index_me()
RETURNS VOID AS
$BODY$
BEGIN
CREATE Temporary TABLE temp_data_to_index (
id INTEGER NOT NULL,
this_id UUID NOT NULL,
that_id smallint NOT NULL,
CONSTRAINT idx_temp_data_to_index_unique
UNIQUE (id,this_id,that_id)
);
CREATE INDEX idx_temp_data_to_index_thisthat ON temp_data_to_index(this_id,that_id);
DROP TABLE temp_data_to_index;
END;
$BODY$ LANGUAGE plpgsql VOLATILE COST 100;
This appears to have been caused by the citus data extension. The error is caused by corrupted memory that occurs once the default stack of 2M is exceeded. It doesn't show up in the logs, and never makes it to the "stack depth limit exceeded" exception that would have been thrown.
That's all speculative finger pointing.
Uninstalling citus extension resolved the issue for me.

PLS-00357 sequence.nextval not allowed

I'm trying to create a trigger and am getting the error "[Error] PLS-00357: PLS-00357: Table, View Or Sequence reference 'table_data_seq.nextval' not allowed in this context"
I have read a lot of information on the error and cannot find the difference between the PL/SQL that people say works and mine. Below is my code for creating the trigger ( keeping it as basic as possible to get it working ):
create or replace trigger tr_tabData
before insert on table_data
for each row
DECLARE
seq_value int;
begin
select table_data_sq.nextval into seq_value from dual;
end;
Oracle version is 10.2.0.5
As requested here it the script for the sequence:
DROP SEQUENCE DATA_ADMIN.TABLE_DATA_SQ;
CREATE SEQUENCE DATA_ADMIN.TABLE_DATA_SQ
START WITH 1000
MAXVALUE 999999999999999999999999999
MINVALUE 1
NOCYCLE
CACHE 20
NOORDER;
This is not possible before 11g. You can use sequence_name.NEXTVAL in regular assignments from 11g not before that, and that by the following:
select TABLE_DATA_SQ.NEXTVAL into :NEW.YourID from dual;
It turned out that this was a bug with the TOAD version and my Oracle database version. The same code in SQL*Plus and SQL Developer worked as expected.