I am trying to create a stored procedure in informix database, but when I try to run the create procedure code the following error appears on the very first line:
Error: A syntax error has occurred.
SQLState: 42000
ErrorCode: -201
Position: 167
Error occurred in:
create procedure test(p_from_date date, p_to_date date, p_department_id like department.id, p_username LVARCHAR(100)) returning decimal
DEFINE v_report LVARCHAR(32100)
this is my code:
create procedure test(p_from_date date, p_to_date date, p_department_id like department.id, p_username LVARCHAR(100)) returning decimal
DEFINE v_report LVARCHAR(32100);
DEFINE v_report_result_id LIKE report_result.id;
DEFINE v_amount, v_bank_amount, v_nap_amount, v_pos_amount DECIMAL(16);
DEFINE v_f_report_result SMALLINT;
DEFINE v_order_number LIKE report_result.order_number;
DEFINE v_payment_canal, v_type LVARCHAR(20);
DEFINE v_department_name like department.name;
DEFINE v_rownum integer;
DEFINE v_current_time VARCHAR(30);
.
.<rest of the code>
.
return v_report_result_id;
END PROCEDURE;
I found out what the problem was.
The statement separator needed to be changed from ; to whatever else that is not used inside the code (I changed it to #).
Because on the first ; character that the interpreter will find in the code (which was on the first line) was interpreted like end of whole code (whole procedure creation).
I am using SQurreL and changed statement separator like this: session > session properties > SQL > statement separator.
I hope this will help everyone else who gets in the same problem as me.
I've got an insert/update trigger set up which prevents an employee from existing in two tables at the same time. It works fine with catching illegal insertions/updates but i'm also getting another error report when testing the trigger with illegal insertions/updates.
Here's my code:
CREATE OR REPLACE TRIGGER check_foobar
BEFORE INSERT OR UPDATE OF VarX ON FOOBAR
FOR EACH ROW
DECLARE
counter NUMBER(38);
BEGIN
SELECT count(*)
INTO counter
FROM BARFOO
WHERE VarX = :NEW.VarX
GROUP BY VarX;
IF counter > 0 THEN
RAISE_APPLICATION_ERROR(-20001, 'This is an illegal insertion/update');
END IF;
EXCEPTION WHEN NO_DATA_FOUND THEN DBMS_OUTPUT.PUT_LINE('TEST');
END;
/
And the errors ORA-06512 and ORA-04088 i'm not sure of:
SQL> INSERT INTO DRIVER VALUES(2, 10345, 'AVAILABLE');
Error starting at line : 26 File #test.sql
In command -
INSERT INTO FOOBAR VALUES(2)
Error report -
ORA-20001: This is an illegal insertion/update
ORA-06512: at "HR.CHECK_FOOBAR", line 11
ORA-04088: error during execution of trigger 'HR.CHECK_FOOBAR'
When i add an exception handler for the select statement my trigger stops working properly and the illegal insertion isn't prevented. But the execution error is prevented.
UPDATE: I've added a group by and an exception to the trigger, so now the trigger still works with an exception handler but the errors ORA-06512 and ORA-04088 are still coming up with the illegal insertion/update.
Line 11 mentioned in the error is
GROUP BY VarX;
Any advice would be much appreciated.
There is no problem here, it is working as expected.
Error starting at line : 26 File #test.sql
In command -
INSERT INTO FOOBAR VALUES(2)
This is referring to the line in your script where you have the INSERT statement. It's telling you an exception was raised at this point.
Error report -
This is showing the error stack:
ORA-20001: This is an illegal insertion/update
This is the actual exception that was raised.
ORA-06512: at "HR.CHECK_FOOBAR", line 11
ORA-04088: error during execution of trigger 'HR.CHECK_FOOBAR'
These are additional messages just to tell you where the exception was originally raised, in this case, in your trigger on line 11, where the RAISE_APPLICATION_ERROR is, as you might expect. Note that line numbers for triggers refer to the executable portion of the trigger, so in your case the DECLARE is line 1.
The ORA-04088 error means that the trigger has an un-handled exception. You are raising a application error but then not handling it. You need to handle this exception as per below.
CREATE OR REPLACE TRIGGER check_foobar
BEFORE INSERT OR UPDATE OF VarX ON FOOBAR
FOR EACH ROW
DECLARE
counter NUMBER(38);
BEGIN
SELECT count(*)
INTO counter
FROM BARFOO
WHERE VarX = :NEW.VarX
GROUP BY VarX;
IF counter > 0 THEN
RAISE_APPLICATION_ERROR(-20001, 'This is an illegal insertion/update');
END IF;
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('TEST');
WHEN OTHERS THEN
IF SQLCODE = -20001 THEN
-- do some logging
RAISE;
ELSE
-- do some logging and any other actions you feel are needed. Then depending on needs you can raise or not.
END IF;
END;
/
I have a procedure in oracle database, which looks like
create or replace PACKAGE MY_PACKAGE AS
TYPE MY_RECORD IS RECORD
(
first_name abc.first_name%TYPE,
middle_name abc.middle_name%TYPE,
last_name abc.last_name%TYPE
);
TYPE MY_RECORD_REF IS REF CURSOR RETURN MY_RECORD;
PROCEDURE getDetails(
last_name IN OUT VARCHAR2,
V_MY_RECORD_REF OUT MY_RECORD_REF);
END MY_PACKAGE;
I want to call the stored procedure to get the data and display them but unable to do so.
Can someone help?
Thanks in advance.
The record is there to give you a definition of the result set. Use the packaged types to define local variables which you use when calling the procedure.
declare
l_result_Set MY_PACKAGE.MY_RECORD_REF;
l_record MY_PACKAGE.MY_RECORD;
l_name abc.last_name%TYPE ;
begin
-- get the results
MY_PACKAGE.getDetails(
l_name
, l_result_Set );
-- now read them
loop
fetch l_result_Set into l_record;
exit when l_result_Set%notfound;
-- do stuff here
end loop;
end;
"do you know how to do the same in java? "
A Ref Cursor is a JDBC Result Set. Andrej Koelewijn has a brief example in this blog post. Note the use of the Oracle library data type OracleTypes.CURSOR. The full sweep of ResultSet is covered in the JDBC Deve guide. Find out more.
I am getting no data found error while looping over an array. The execute immediate has data, but the forall loop is giving no data found error and not able to iterate over the collection.
Please find the code below. code_arr.FIRST seems to have some issue. Table has data and executing sql gives data on editor. Could you please help.
create or replace PACKAGE TEST AS
FUNCTION TEST RETURN NUMBER;
END;
create or replace PACKAGE BODY TEST AS
FUNCTION TEST RETURN NUMBER
IS
TYPE typ_varchar IS TABLE OF VARCHAR2 (1000) INDEX BY BINARY_INTEGER;
lv_statement VARCHAR2 (1000);
code_arr typ_varchar;
var1 varchar(1000);
BEGIN
lv_statement := 'SELECT lnm.code FROM employee lnm';
EXECUTE IMMEDIATE lv_statement BULK COLLECT
INTO code_arr;
FORALL ix1 IN code_arr.FIRST .. code_arr.LAST SAVE EXCEPTIONS
SELECT code_arr(ix1) into var1 FROM DUAL;
RETURN 1;
END;
END;
Thanks in advance for your help.
Mathew
FORALL is meant for bulk DML and not for looping through data. The syntax diagram shows this:
To be pedantic, SELECT is a form of DML, although it's usually considered separate from commands that modify objects. That might be why the original code sort of works but throws an error at run time instead of at compile time.
If all you need to do is loop through data, just use a cursor for loop like this. Oracle automatically uses bulk collect for these types of loops:
begin
for employees in
(
SELECT lnm.code FROM employee lnm
) loop
--Do something here.
null;
end loop;
end;
/
Hi I am using postgresql 8.1.22, I am trying to setup postgresql auditing using the following function.
CREATE OR REPLACE FUNCTION audit.if_modified_func() RETURNS TRIGGER AS $body$
DECLARE
v_old_data TEXT;
v_new_data TEXT;
BEGIN
/* If this actually for real auditing (where you need to log EVERY action),
then you would need to use something like dblink or plperl that could log outside the transaction,
regardless of whether the transaction committed or rolled back.
*/
/* This dance with casting the NEW and OLD values to a ROW is not necessary in pg 9.0+ */
IF (TG_OP = 'UPDATE') THEN
v_old_data := ROW(OLD.*);
v_new_data := ROW(NEW.*);
INSERT INTO audit.logged_actions (schema_name,table_name,user_name,action,original_data,new_data,query)
VALUES (TG_TABLE_SCHEMA::TEXT,TG_TABLE_NAME::TEXT,session_user::TEXT,substring(TG_OP,1,1),v_old_data,v_new_data, current_query());
RETURN NEW;
ELSIF (TG_OP = 'DELETE') THEN
v_old_data := ROW(OLD.*);
INSERT INTO audit.logged_actions (schema_name,table_name,user_name,action,original_data,query)
VALUES (TG_TABLE_SCHEMA::TEXT,TG_TABLE_NAME::TEXT,session_user::TEXT,substring(TG_OP,1,1),v_old_data, current_query());
RETURN OLD;
ELSIF (TG_OP = 'INSERT') THEN
v_new_data := ROW(NEW.*);
INSERT INTO audit.logged_actions (schema_name,table_name,user_name,action,new_data,query)
VALUES (TG_TABLE_SCHEMA::TEXT,TG_TABLE_NAME::TEXT,session_user::TEXT,substring(TG_OP,1,1),v_new_data, current_query());
RETURN NEW;
ELSE
RAISE WARNING '[AUDIT.IF_MODIFIED_FUNC] - Other action occurred: %, at %',TG_OP,now();
RETURN NULL;
END IF;
EXCEPTION
WHEN data_exception THEN
RAISE WARNING '[AUDIT.IF_MODIFIED_FUNC] - UDF ERROR [DATA EXCEPTION] - SQLSTATE: %, SQLERRM: %',SQLSTATE,SQLERRM;
RETURN NULL;
WHEN unique_violation THEN
RAISE WARNING '[AUDIT.IF_MODIFIED_FUNC] - UDF ERROR [UNIQUE] - SQLSTATE: %, SQLERRM: %',SQLSTATE,SQLERRM;
RETURN NULL;
WHEN OTHERS THEN
RAISE WARNING '[AUDIT.IF_MODIFIED_FUNC] - UDF ERROR [OTHER] - SQLSTATE: %, SQLERRM: %',SQLSTATE,SQLERRM;
RETURN NULL;
END;
$body$
LANGUAGE plpgsql
SECURITY DEFINER
But if you observe in the above function current_query() is not coming with the mentioned language plpgsql. It throws some error. When I googled I found that in order to use current_query() function PL/CTL language must be installed. I tried to install as mentioned below. It throws an error. So kindly help me how to install PL/CTL language into my database so that current_query() function should work
-bash-3.2$ createlang -d dbname pltcl
createlang: language installation failed: ERROR: could not access file "$libdir/pltcl": No such file or directory
Okay as you suggested I created that current_query() function,but this time I got some thing like this , What i did is ,
CREATE TABLE phonebook(phone VARCHAR(32), firstname VARCHAR(32), lastname VARCHAR(32), address VARCHAR(64));
CREATE TRIGGER phonebook_auditt AFTER INSERT OR UPDATE OR DELETE ON phonebook
FOR EACH ROW EXECUTE PROCEDURE audit.if_modified_func();
INSERT INTO phonebook(phone, firstname, lastname, address) VALUES('9966888200', 'John', 'Doe', 'North America');
for testing the function i created a table named phonebook and created a trigger so that the function mentioned above audit.if_modified_func() will be executed after any insert or update or delete.the row is getting inserted but I am getting a error reg the audit.if_modified_func() function .the error is as follows
WARNING: [AUDIT.IF_MODIFIED_FUNC] - UDF ERROR [OTHER] - SQLSTATE: 42703, SQLERRM: column "*" not found in data type phonebook
Query returned successfully: 1 rows affected, 10 ms execution time.
Kindly tell me what can i do to get rid of the above error.
Not sure where you found the information about current_query and pltcl. These are unrelated. The reason why you can't find pltcl is simply because you're using too old PostgreSQL. current_query() has been added to Pg in version 8.4.
Is there any particular reason why you're using such old version? It is no longer supported, and it lacks almost 8 years of added features!
If you have to use 8.1, you might want to define:
create function current_query() returns text as '
select current_query from pg_stat_activity where procpid = pg_backend_pid();
' language sql;
But it is much better idea just to upgrade.
As for edited and added second question - it's very likely that Pg 8.1 cannot use "row.*" construct. Find who wrote the original code with the "dance comments", and ask about it. Perhaps it was meant to work in newer Pgs.