I am getting errors trying to run SQL code designed to determine an employee_id - sqlplus

I am trying to do an if statement to determine the employee_id but I keep getting errors every time I run the program. Here is a transcript of me interacting with the database:
`enter code here`SQL> SET SERVEROUT ON FORMAT TRUNCATED
`enter code here`SQL> DECLARE
`enter code here` 2
`enter code here`3 EMP_REC HR.EMPLOYEES%ROWTYPE;
`enter code here`4 BEGIN
`enter code here`5 DBMS_OUTPUT.PUT_LINE ('---------------------------------------');
`enter code here`6 FOR EMP_REC
`enter code here`7 (SELECT *
`enter code here`8 FROM HR.EMPLOYEES
`enter code here`9 WHERE EMPLOYEE_ID = 5)
`enter code here`10 LOOP
`enter code here`11 IF
`enter code here`12 IF (EMP_REC.EMPLOYEE_ID = 5) THEN
`enter code here`13 DBMS_OUTPUT.PUT_LINE ('EMPLOYEE_ID: ' || EMP_REC.EMPLOYEE_ID) ;
`enter code here` 14 DBMS_OUTPUT.PUT_LINE ('FIRST_NAME: ' || EMP_REC.FIRST_NAME) ;
`enter code here` 15 DBMS_OUTPUT.PUT_LINE ('LAST_NAME: ' || EMP_REC.LAST_NAME) ;
`enter code here` 16 DBMS_OUTPUT.PUT_LINE ('SALARY: ' || TO_CHAR (EMP_REC.SALARY, '$999,999'));
`enter code here` 17 DBMS_OUTPUT.PUT_LINE ('---------------------------------------');
`enter code here` 18 END LOOP;
`enter code here`19 END IF;
`enter code here`20 EXCEPTION
`enter code here`21 WHEN NO_DATA_FOUND THEN
`enter code here`22 DBMS_OUTPUT.PUT_LINE ('NO DATA FOUND.');
`enter code here`23
`enter code here`24 END;
`enter code here`25 /
and here are the errors which are being reported:
(SELECT *
*
ERROR at line 7:
ORA-06550: line 7, column 1:
PLS-00103: Encountered the symbol "(" when expecting one of the following:
in
The symbol "in" was substituted for "(" to continue.
ORA-06550: line 12, column 1:
PLS-00103: Encountered the symbol "IF" when expecting one of the following:
( - + case mod new not null <an identifier>
<a double-quoted delimited-identifier> <a bind variable>
continue avg count current exists max min prior sql
ORA-06550: line 18, column 5:
PLS-00103: Encountered the symbol "LOOP" when expecting one of the following:
if
You can use it to determine the Department they work for, like we did in the past with a CASE.
You can use it to print a message if they make over a certain amount of money.
Maybe they are due a raise if they were hired before a certain date.

Related

for loop with dynamic table name and execute immediate

in my Procedure there is the following code line
for i in (select schema_name, table_name, restricted_columns
from GRANTED_TABLES_FOR_ROLE
where restricted_columns = 0) loop
execute immediate 'grant select on ' || i.schema_name || '.' || i.table_name || ' to ROLE_NAME';
end loop;
because i want to create the table "GRANTED_TABLES_FOR_ROLE" earlier in my procudere i can't create the procedure without the "GRANTED_TABLES_FOR_ROLE" existing.
is there any way to make the code above dynamic so i can set a variable for the table "GRANTED_TABLES_FOR_ROLE"?
how i can achieve this?
thanks for your help!
I believe this is a case where you will need to use a dynamic cursor:
DECLARE
TYPE trec IS RECORD
(
schema_name VARCHAR2 (30)
, table_name VARCHAR2 (30)
, restricted_columns VARCHAR2 (30)
);
l_rec trec;
l_sqlstment VARCHAR2 (500)
:= q'[SELECT schema_name, table_name, restricted_columns
FROM <<tablename>>
WHERE restricted_columns = 0 ]';
l_cursor SYS_REFCURSOR;
BEGIN
l_sqlstment :=
REPLACE (l_sqlstment, '<<tablename>>', 'granted_tables_for_role');
OPEN l_cursor FOR l_sqlstatement;
LOOP
FETCH l_cursor INTO l_rec;
EXIT WHEN l_cursor%NOTFOUND;
dbms_outout.put_line (l_rec.schema_name);
dbms_outout.put_line (l_rec.table_name);
dbms_outout.put_line (l_rec.restricted_columns);
EXECUTE IMMEDIATE 'grant select on '
|| l_rec.schema_name
|| '.'
|| l_rec.table_name
|| ' to ROLE_NAME';
END LOOP;
END;

Variable Assignment Issue for Multiple dynamic SQL in DB2 Iseries

We are using DB2 Iseries V7R3 on AS400 system.
In one of the stored procedure, we are preparing dynamic SQL queries. Each SQL query is assigned to different variables. When we execute the stored procedure sometimes it fails but when retry with same parameters it works.
Upon putting logs in the stored procedure, we have observed that during the failed cases value used for variable 2 is from variable 1.
Attached is the stored procedure and screenshot of the logs.
Appreciate any help on this, running out of the thinking options for this.
However, sometimes it uses select * for variable1 as well. After retry it works ok.
create stored procedure (
)DYNAMIC RESULT SETS 1
LANGUAGE SQL
SPECIFIC SYMDTA.PRC_RETRIEVE_CLAIM_LIST
NOT DETERMINISTIC
MODIFIES SQL DATA
CALLED ON NULL INPUT
COMMIT ON RETURN YES
CONCURRENT ACCESS RESOLUTION USE CURRENTLY COMMITTED
SET OPTION ALWBLK = *ALLREAD ,
ALWCPYDTA = *OPTIMIZE ,
COMMIT = *NONE ,
DECRESULT = (31, 31, 00) ,
DYNDFTCOL = *NO ,
DYNUSRPRF = *USER ,
SRTSEQ = *HEX
BEGIN
DECLARE DATACLAIM CLOB ( 1048576 ) DEFAULT ' ' ;
DECLARE GCLAIMCOUNT CLOB ( 1048576 ) DEFAULT ' ' ;
DECLARE CR_CLAIM_LIST_STMT CURSOR WITH HOLD FOR CLM_DATA_STMT ;
DECLARE CR_CLAIM_COUNT_STMT CURSOR WITH HOLD FOR CLM_COUNT_STMT ;
SET DATACLAIM = 'SELECT * FROM table ';
SET GCLAIMCOUNT = 'select count(*) from table';
INSERT INTO DEBUGGING_DYNAMIC_QUERIES VALUES ( POLICY_NO , DATACLAIM , CURRENT TIMESTAMP , 'DATACLAIM' ) ;
INSERT INTO DEBUGGING_DYNAMIC_QUERIES VALUES ( GCLAIMCOUNT , CURRENT TIMESTAMP , 'GCLAIMCOUNT' ) ;
PREPARE CLM_DATA_STMT FROM DATACLAIM ;
OPEN CR_CLAIM_LIST_STMT ;
PREPARE CLM_COUNT_STMT FROM GCLAIMCOUNT ;
OPEN CR_CLAIM_COUNT_STMT ;
FETCH CR_CLAIM_COUNT_STMT INTO TOTAL_RECORDS_G4 ;
CLOSE CR_CLAIM_COUNT_STMT ;
Output the debug table :-
Wrong :-
DATACLAIM = "select * " - 2020-01-01 11:00 AM
GCLAIMCOUNT = "Select * " - 2020-01-01 11:01 AM
After retry :-
DATACLAIM = "select * " - 2020-01-01 12:00 pm
GCLAIMCOUNT = "Select count(*) " - 2020-01-01 12:01 Pm

Stored procedure not compiling with 'Set'

I have a Stored procedure which I am not able to compile.
CREATE PROCEDURE FINGOODSCH(IN STRDATE DATE,
IN prodln Char(5))
LANGUAGE SQL
RESULT SETS 1
SET OPTION DBGVIEW =*SOURCE
BEGIN
Declare IN_DATE NUMERIC(7,0);
SET IN_DATE = 0;
/* SET IN_DATE = (DECIMAL(CHAR(SUBSTR(CHAR(STRDATE),1,4); */
/* SUBSTR(CHAR(STRDATE),6,2) CONCAT */
/* SUBSTR(CHAR(STRDATE),9,2))) - 19000000) ; */
Declare FinGoodSCH Cursor for
Select TRIM(ORDNO) as OrderNumber,
( '20' || SUBSTR(CHAR(ODUDT),2,2) || '-' ||
SUBSTR(CHAR(ODUDT),4,2) || '-' ||
SUBSTR(CHAR(ODUDT),6,2)) as OrderDueDate,
TRIM(FITEM) as ModelNumber,
TRIM(DPTNO) as ProductionLine
From ORMAST
Where
DPTNO = prodln
OPEN FinGoodSCH ;
END
THe issue is withthe statement 'SET IN_DATE = 0; (I know I can use Default to set it to 0, but thats not what I am looking for)'. If I remove this statement, it will compile. Compilation error is:
SQL0104 30 3 Position 33 Token FINGOODSCH was not valid. Valid
tokens: GLOBAL.
Also, I tried declaring it with decimal but it did not work
You have to do the declarations in SQL before any executable code....
CREATE PROCEDURE FINGOODSCH(IN STRDATE DATE,
IN prodln Char(5))
LANGUAGE SQL
RESULT SETS 1
SET OPTION DBGVIEW =*SOURCE
BEGIN
Declare IN_DATE NUMERIC(7,0);
Declare FinGoodSCH Cursor for
Select TRIM(ORDNO) as OrderNumber,
( '20' || SUBSTR(CHAR(ODUDT),2,2) || '-' ||
SUBSTR(CHAR(ODUDT),4,2) || '-' ||
SUBSTR(CHAR(ODUDT),6,2)) as OrderDueDate,
TRIM(FITEM) as ModelNumber,
TRIM(DPTNO) as ProductionLine
From ORMAST
Where
DPTNO = prodln;
-- Executable code starts here....
SET IN_DATE = (DECIMAL(CHAR(SUBSTR(CHAR(STRDATE),1,4);
SUBSTR(CHAR(STRDATE),6,2) CONCAT
SUBSTR(CHAR(STRDATE),9,2))) - 19000000) ;
OPEN FinGoodSCH ;
END
Note that if you happened to want to use IN_DATE in your cursor, you'd still do it like the above. The value of any variables used in the DECLARE CURSOR statement are not evaluated until the cursor is opened in DB2.

Stored procedere: flexible param for operator on 'IF #recordCount <= #Menge'

I hope someone can me help again, regarding to my solved stored procedure problem
Is there any chance to make the operator ">" flexible?
Right now my stored procedure works very fine and I will get an eMail when the record count is bigger than the param Menge.
The code is this:
#Menge as int = 0,
#recordCount as int = 0,
set #MySQL = 'select #recordCount=count(2) from ' + #MyTable + ' where ' + #MyWhere
exec sp_execute #MySQL, N'#recordCount int OUTPUT', #recordCount=#recordCount OUTPUT
IF #recordCount > #Menge
begin
...
EXEC msdb.dbo.sp_send_dbmail
Now I want to make > flexible to get an e-mail when the record count is smaller than menge
I tried to declare the param but I don't know how to insert it into the if #recordcount > #Menge line :(
#OpInd as char(1) = null
I would call the stored procedure with
exec sp_eMail_Test3
#Menge = 0,
#eMail_TO = 'testuser#test.xx' ,
#eMail_Subject = 'test3 ',
#eMail_Body = 'Hallo, das ist ein Test',
#MyTable ='test' ,
#MyWhere = 'not [sys_completed] is null'
#OpInd = '<'
If I try IF #recordCount + #OpInd + #Menge then I get the error
An expression of non-boolean type specified in a context where a condition is expected, near 'begin'.
Hopefully you understand my Target and can help me.
If necessary I need to build a 2nd stored procedure :( one for "<" and one for ">"
Best regards Ralf
Just change your operand to <>
IF #recordCount <> #Menge
begin
...
EXEC msdb.dbo.sp_send_dbmail
There are only 3 possible operands you want to deal with. >, <, and =. Since you want an email if it's > or if it's < then just send the email when it's not =.
Another way would to repeat your code.
IF (#recordCount > #Menge or #recordCount < #Menge)
begin
...
EXEC msdb.dbo.sp_send_dbmail
If you are trying to make it either > or < then you can use DynamicSQL. Something like...
declare #sql varchar(max)
set #sql =
'IF ' + cast(#recordCount as varchar(16)) + ' ' + #OpInd + ' ' + cast(#Menge as varchar(16)) + '
begin
...
EXEC msdb.dbo.sp_send_dbmail'
EXEC(#sql)

Error handling in Teradata Stored Procedure

I am trying to develop a stored procedure within TERADATA to handle and manage exceptions.
The stored procedure should raise the error to the caller, which is an SSIS Package.
I am trying to illustrate this by creating a stored procedure for illustration only.
I have these tables:
Table_A:
- ID INT
- ITEM_NUM INT
- DESC VARCHAR(20)
- CREATE_DTTM VARCHAR(2O)
Table_B:
- ID INT
- ITEM_NUM INT
- DESC VARCHAR(20)
- CREATE_DTTM VARCHAR(2O)
I have two tables that will be inserting data from two SELECT statements.
REPLACE PROCEDURE csTest2()
SQL SECURITY OWNER
BEGIN
DECLARE varErrorMessage char(256);
DECLARE varSQLState char(5);
DECLARE varReturnCode char(5);
DECLARE varRollbackNeededInd char(1); /* transaction mgt */
SET varRollbackNeededInd = 'N';
SET varReturnCode = '00000';
SET varErrorMessage = '';
BEGIN TRANSACTION;
-- USING A SINGLE HANDLER WITH MULTIPLE STATEMENTS
-- PLANING TO CHANGE ERROR MESSAGE IN EACH STATEMENT.
ins6: BEGIN
DECLARE EXIT HANDLER FOR SQLEXCEPTION
H99:Begin
set varSQLState = SQLSTATE;
set varErrorMessage= 'This message should not be displayed'; --
end H99;
-- IMAGINE THAT I AM GETTING THE VALUES AS INPUT PARAMERS IN THE PROCEDURE
INSERT INTO "Table_A"
(ID , ITEM_NUM, DESC, CREATE_DTTM)
SELECT 1, '222', 'SOME DESC',CURRENT_TIMESTAMP;
H98:Begin
set varSQLState = SQLSTATE;
set varErrorMessage= 'This message is displayed, ITEM_NUM invalid characters';
end H98;
-- NOW I AM DOING A SECOND INSERT TO table b WITH INVALID DATA
-- THE VALUE FOR THE ITEM NUMBER CONTAINS ALPHANUMERICE CHARACTERS
INSERT INTO "Table_b"
(ID , ITEM_NUM, DESC, CREATE_DTTM)
SELECT 1, '333F', 'SOME DESC',CURRENT_TIMESTAMP;
END ins6;
EndTrans: BEGIN
IF varSQLState <> '0' THEN
SET varRollbackNeededInd = 'Y';
SET varReturnCode = '9999';
END IF;
IF varRollbackNeededInd = 'Y' THEN
ROLLBACK; -- ROLLBACK AND SEND ERROR TO CALLER
SIGNAL SQLSTATE 'U0123' SET MESSAGE_TEXT = 'SQlState is - ' || varSQLSTATE || ' - and error is - ' || varErrorMessage;
ELSE
END TRANSACTION; -- COMMIT TRANSACTION
END IF;
END EndTrans;
END;
The problem that I am facing with the above stored procedure is that error message that I get is not the one that I am expecting. Since error is intentionally created in my second statement I am expecting to get: This message is displayed, ITEM_NUM invalid characters but I am getting This message should not be displayed
Now if I modify the PROCEDURE to have multiple handlers, one for each statement, I do get the correct error message, but now since I am intentionally generating the error in the first statement it does not terminate the procedure, it handles the error and sets the proper message but continues to process the next statement which I am not expecting to do this, so how can I terminate this procedure?
REPLACE PROCEDURE csTest2()
SQL SECURITY OWNER
BEGIN
DECLARE varErrorMessage char(256);
DECLARE varSQLState char(5);
DECLARE varReturnCode char(5);
DECLARE varRollbackNeededInd char(1); /* transaction mgt */
SET varRollbackNeededInd = 'N';
SET varReturnCode = '00000';
SET varErrorMessage = '';
BEGIN TRANSACTION;
ins6: BEGIN
DECLARE EXIT HANDLER FOR SQLEXCEPTION
H99:Begin
set varSQLState = SQLSTATE;
set varErrorMessage= 'Error is displayed in this case because ITEM_NUM';
-- ERROR IS PRESENT IN THIS STATEMENT AND SHOULD TERMINATE THE PROCEDURE.
INSERT INTO "Table_A"
(ID , ITEM_NUM, DESC, CREATE_DTTM)
SELECT 1, '222F', 'SOME DESC',CURRENT_TIMESTAMP;
END ins6;
ins7: BEGIN
H98:Begin
set varSQLState = SQLSTATE;
set varErrorMessage= 'no error is displayed in this case';
end H98;
-- NO ERROR IS EXPECTED, BUT IT SHOULD NOT REACH HERE SINCE WE HAD ERROR ON FIRST STATEMENT.
INSERT INTO "Table_b"
(ID , ITEM_NUM, DESC, CREATE_DTTM)
SELECT 1, '333', 'SOME DESC',CURRENT_TIMESTAMP;
END ins7;
EndTrans: BEGIN
IF varSQLState <> '0' THEN
SET varRollbackNeededInd = 'Y';
SET varReturnCode = '9999';
END IF;
IF varRollbackNeededInd = 'Y' THEN
ROLLBACK; -- ROLLBACK AND SEND ERROR TO CALLER
SIGNAL SQLSTATE 'U0123' SET MESSAGE_TEXT = 'SQlState is - ' || varSQLSTATE || ' - and error is - ' || varErrorMessage;
ELSE
END TRANSACTION; -- COMMIT TRANSACTION
END IF;
END EndTrans;
END;

Resources