DB2 trigger on update - db2

I have the table ORDERS with a lot of columns: (ORDERS_ID, MEMBER_ID, STATUS, ANY MORE....)
when in STATUS I will have the change in the new status 'M' I would save ORDERS_ID, MEMBER_ID, STATUS in another table XORDERSAUDIT.
I wrote this :
CREATE or replace TRIGGER Order_Status_Update_Trigger
AFTER UPDATE OF STATUS ON ORDERS
REFERENCING NEW AS N
FOR EACH ROW
WHEN (N.STATUS = 'M')
BEGIN ATOMIC
INSERT INTO XORDERSAUDIT
(ORDER_ID, USERS_ID, STATUS) VALUES (N.ORDERS_ID, N.MEMBER_ID, N.STATUS);
END;
and I have this error:
DB2 SQL Error: SQLCODE=-104, SQLSTATE=42601,
SQLERRMC=END-OF-STATEMENT;MEMBER_ID, N.STATUS);,
DRIVER=4.19.66 SQLState: 42601 ErrorCode: -104 Error occurred in:
I don't understand the error, I try to correct but encountered the same error, please help me.

Related

How to execute this Postgres SQL

This should be a simple SQL Server query, i am new to PostGres, i am not sure what is the error, if there is a documentation, please point, i will follow up on that too
declare
Vin VARCHAR(10) := 'WBY7Z4C5&J';
begin
SELECT false as isresultempty, v1.*, '' AS "message"
FROM pd.vehicle v1
WHERE v1.maskedvin = cast(Vin AS CHARACTER(10))
AND v1.modelyyyy = 2018
AND vinChangeCd <> 'D'
AND v1.circularnumber <> 'INTM';
end
I keep getting this error
SQL Error [42601]: ERROR: syntax error at or near "false"
Position: 61
Where: invalid type name "false as isresultempty"
update after changing this sql
SQL Error [42601]: ERROR: syntax error at or near "VARCHAR"
Position: 16

about SQLCODE -104 (error) during select in DB2

I have been trying to adapt a working "INSERT" into a SELECT statement and keep finding a error -104
a)Can someone please help me understand the reason why the "." on "where" clause (below) works when I run with an "insert" but gives me an error when using on a "select" clause?
b)How should the "INSERT" criteria be written correctly when using a SELECT?
Many thanks in advance for any assistance on this question
Insert:
INSERT INTO SISPD2.SIS_DAILY_RECALC
(CIN_NUM,PGM_DIV_FG,NON_CA_FG,PGM_EXCPT_FG,WTW_FG)
(SELECT C.CIN_NUM, C.PGM_DIV_FG, C.NON_CA_FG, C.PGM_EXCPT_FG,
C.WTW_FG
FROM SISPD2.SIS_INDV C
WHERE C.CIN_NUM NOT IN (SELECT CIN_NUM FROM SISPD2.SIS_DAILY_RECALC)
------------------------------------------------------------------------
Select :
SELECT C.CIN_NUM ||','||
C.PGM_DIV_FG ||','||
C.NON_CA_FG ||','||
C.PGM_EXCPT_FG ||','||
C.WTW_FG ||','||
WHERE (C.CIN_NUM NOT IN (SELECT A.CIN_NUM
FROM SISPD2.SIS_DAILY_RECALC A));
DSNT408I SQLCODE = -104, ERROR: ILLEGAL SYMBOL ".". SOME SYMBOLS THAT MIGHT
BE LEGAL ARE: , FROM INTO
DSNT418I SQLSTATE = 42601 SQLSTATE RETURN CODE
You shouldn't be concatenating a statement together unless you're building a dynamic statement you intend to PREPARE and EXECUTE
SELECT C.CIN_NUM
, C.PGM_DIV_FG
, C.NON_CA_FG
, C.PGM_EXCPT_FG
, C.WTW_FG
WHERE (C.CIN_NUM NOT IN (SELECT A.CIN_NUM
FROM SISPD2.SIS_DAILY_RECALC A));

Using IF Exists function in postgreSQL pgadmin3 (syntax error ,SQL state: 42601 Character: 1)

I am trying to execute an SQL statement in pgadmin3 that do the following:
If a student with a specific name and age already exists then get the student_id else insert a new record with the specified name and age and then get the created student_id
I have tried this code:
IF EXISTS (SELECT 1 FROM main.student WHERE studentname='hhh' and studentage=15)
BEGIN
SELECT student_id FROM main.student WHERE studentname='hhh' and studentage=15
END
ELSE
BEGIN
INSERT INTO main.student(studentname,studentage) VALUES('hhh',15)
END;
END IF;
But I am always getting this error:
syntax error at or near "IF"
SQL state: 42601
Character: 1
Can you please tell me what I am doing wrong. Also how can I get the student_id after the insert statement?
Actually your statement is not SQL. it is PL/PGSQL statement.
So obviously when you send this to Postgres as SQL query it will throw an exception.
If you are doing this from pgAdmin3 it has nice feature to run pl/psql scripts. use it
IF EXISTS (SELECT 1 FROM main.student WHERE studentname='hhh' and studentage=15) THEN
SELECT student_id FROM main.student WHERE studentname='hhh' and studentage=15;
ELSE
INSERT INTO main.student(studentname,studentage) VALUES('hhh',15);
END IF;
Some points you need to consider:
For IF statement, you need to use THEN
To run just one syntax, you don't need the BEGIN/END
Use ; at the end of each statement
Also if you are running an ad-hoc statement, you need to run it within DO command
DO
$do$
IF EXISTS (SELECT 1 FROM main.student WHERE studentname='hhh' and studentage=15) THEN
SELECT student_id FROM main.student WHERE studentname='hhh' and studentage=15;
ELSE
INSERT INTO main.student(studentname,studentage) VALUES('hhh',15);
END IF;
END
$do$
For the last part of your question, you can return the id you are inserting
INSERT INTO main.student(studentname,studentage) VALUES('hhh',15) RETURNING student_id

Firebird Error in Creating Trigger

Preparing query: CREATE TRIGGER autoincrementor_id FOR ID
ACTIVE BEFORE INSERT POSITION 0
AS
BEGIN
IF (NEW.OID IS NULL) THEN
NEW.OID = GEN_ID(MY_GEN_ID,1)
Error: *** IBPP::SQLException ***
Context: Statement::Prepare( CREATE TRIGGER autoincrementor_id FOR ID
ACTIVE BEFORE INSERT POSITION 0
AS
BEGIN
IF (NEW.OID IS NULL) THEN
NEW.OID = GEN_ID(MY_GEN_ID,1) )
Message: isc_dsql_prepare failed
SQL Message : -104
Invalid token
Engine Code : 335544569
Engine Message :
Dynamic SQL Error
SQL error code = -104
Unexpected end of command - line 6, column 33
I get this error while creating the trigger below:
CREATE TRIGGER autoincrementor_id FOR ID
ACTIVE BEFORE INSERT POSITION 0
AS
BEGIN
IF (NEW.OID IS NULL) THEN
NEW.OID = GEN_ID(MY_GEN_ID,1);
END
Where am I missing? I already have my table ID created with a primary id oid, that must be auto incremented. I also created my generator function MY_GEN_ID.
You have to set the statement terminator and use it to terminate the CREATE TRIGGER statement, ie
SET TERM ^;
CREATE TRIGGER autoincrementor_id FOR ID
... rest of the trigger's body
END^
SET TERM ;^

PostgreSQL Exception Handling

I am new to PostgreSQL. Could anybody please correct this query.
BEGIN TRANSACTION;
BEGIN;
CREATE TABLE "Logs"."Events"
(
EventId BIGSERIAL NOT NULL PRIMARY KEY,
PrimaryKeyId bigint NOT NULL,
EventDateTime date NOT NULL DEFAULT(now()),
Action varchar(12) NOT NULL,
UserId integer NOT NULL REFERENCES "Office"."Users"(UserId),
PrincipalUserId varchar(50) NOT NULL DEFAULT(user)
);
CREATE TABLE "Logs"."EventDetails"
(
EventDetailId BIGSERIAL NOT NULL PRIMARY KEY,
EventId bigint NOT NULL REFERENCES "Logs"."Events"(EventId),
Resource varchar(64) NOT NULL,
OldVal varchar(4000) NOT NULL,
NewVal varchar(4000) NOT NULL
);
COMMIT TRANSACTION;
RAISE NOTICE 'Task completed sucessfully.'
EXCEPTION;
ROLLBACK TRANSACTION;
RAISE ERROR #ErrorMessage, #LineNumber, #ErrorState --how to catch errors and display them????
END;
Questions:
How to print a message like 'PRINT' in T-SQL?
How to raise errors with exception information?
To catch the error message and its code:
do $$
begin
create table yyy(a int);
create table yyy(a int); -- this will cause an error
exception when others then
raise notice 'The transaction is in an uncommittable state. '
'Transaction was rolled back';
raise notice '% %', SQLERRM, SQLSTATE;
end; $$
language 'plpgsql';
Haven't found the line number yet
UPDATE April, 16, 2019
As suggested by Diego Scaravaggi, for Postgres 9.2 and up, use GET STACKED DIAGNOSTICS:
do language plpgsql $$
declare
v_state TEXT;
v_msg TEXT;
v_detail TEXT;
v_hint TEXT;
v_context TEXT;
begin
create table yyy(a int);
create table yyy(a int); -- this will cause an error
exception when others then
get stacked diagnostics
v_state = returned_sqlstate,
v_msg = message_text,
v_detail = pg_exception_detail,
v_hint = pg_exception_hint,
v_context = pg_exception_context;
raise notice E'Got exception:
state : %
message: %
detail : %
hint : %
context: %', v_state, v_msg, v_detail, v_hint, v_context;
raise notice E'Got exception:
SQLSTATE: %
SQLERRM: %', SQLSTATE, SQLERRM;
raise notice '%', message_text; -- invalid. message_text is contextual to GET STACKED DIAGNOSTICS only
end; $$;
Result:
NOTICE: Got exception:
state : 42P07
message: relation "yyy" already exists
detail :
hint :
context: SQL statement "create table yyy(a int)"
PL/pgSQL function inline_code_block line 11 at SQL statement
NOTICE: Got exception:
SQLSTATE: 42P07
SQLERRM: relation "yyy" already exists
ERROR: column "message_text" does not exist
LINE 1: SELECT message_text
^
QUERY: SELECT message_text
CONTEXT: PL/pgSQL function inline_code_block line 33 at RAISE
SQL state: 42703
Aside from GET STACKED DIAGNOSTICS is SQL standard-compliant, its diagnostics variables (e.g., message_text) are contextual to GSD only. So if you have a field named message_text in your table, there's no chance that GSD can interfere with your field's value.
Still no line number though.
Use the DO statement, a new option in version 9.0:
DO LANGUAGE plpgsql
$$
BEGIN
CREATE TABLE "Logs"."Events"
(
EventId BIGSERIAL NOT NULL PRIMARY KEY,
PrimaryKeyId bigint NOT NULL,
EventDateTime date NOT NULL DEFAULT(now()),
Action varchar(12) NOT NULL,
UserId integer NOT NULL REFERENCES "Office"."Users"(UserId),
PrincipalUserId varchar(50) NOT NULL DEFAULT(user)
);
CREATE TABLE "Logs"."EventDetails"
(
EventDetailId BIGSERIAL NOT NULL PRIMARY KEY,
EventId bigint NOT NULL REFERENCES "Logs"."Events"(EventId),
Resource varchar(64) NOT NULL,
OldVal varchar(4000) NOT NULL,
NewVal varchar(4000) NOT NULL
);
RAISE NOTICE 'Task completed sucessfully.';
END;
$$;
You could write this as a psql script, e.g.,
START TRANSACTION;
CREATE TABLE ...
CREATE TABLE ...
COMMIT;
\echo 'Task completed sucessfully.'
and run with
psql -f somefile.sql
Raising errors with parameters isn't possible in PostgreSQL directly. When porting such code, some people encode the necessary information in the error string and parse it out if necessary.
It all works a bit differently, so be prepared to relearn/rethink/rewrite a lot of things.
Just want to add my two cents on this old post:
In my opinion, almost all of relational database engines include a commit transaction execution automatically after execute a DDL command even when you have autocommit=false, So you don't need to start a transaction to avoid a potential truncated object creation because It is completely unnecessary.