0440 Procedures in MonetDB

Procedures

A SQL Stored Procedure is a named set of SQL statements that are frequently executed together. When we want to execute those statements, we only need to specify the procedure name and the argument values.

Procedures are very similar to functions, but they differ in purpose and usage.

1) The purpose of functions is to perform calculations and return values. The purpose of procedures is to change database objects. This means that DML statements should be used within procedures, not within functions.

2) Functions are used in statements. They can be used in SELECT, WHERE, GROUP BY, and HAVING. Procedures are self-contained and independent from other statements. They are executed with the "CALL" statement.

DDL Statements in Procedures

CREATE OR REPLACE PROCEDURE procDDL()
BEGIN
    CREATE TABLE Tab1 ( Number INT );
    ALTER TABLE Tab1 ADD COLUMN Letter CHAR;
END;
We can not use DDL statements within a procedure.

CREATE OR REPLACE PROCEDURE procDDL() BEGIN
    CREATE TABLE Tab1 ( Number INT );
END;
It is possible to use "CREATE TABLE" statement
inside of procedure.

But when we try to read from our new table (after we called a procedure), we get nothing:
SELECT * FROM Tab1;

I will now try to create a table inside of procedure, but this time I will specify schema. We will get an interesting message.

CREATE OR REPLACE PROCEDURE procDDL()
BEGIN
    CREATE TABLE voc.Tab1 ( Number INT );
END;
It seems that CREATE TABLE is the same as DECLARE TABLE. We were not using DDL statement, we were just definining a table variable.

Now we know that DDL statements can not be used in Functions and Procedures at all.

Sample Table

CREATE TABLE procTab ( Number INT );
SELECT * FROM procTab;

DML Statements in Procedures

CREATE OR REPLACE PROCEDURE procDML()
BEGIN
    INSERT INTO procTab ( Number ) VALUES ( 1 );
END;
CALL procDML();
  --we call the procedure
SELECT * FROM procTab;

DML statements will work normally inside of procedures.

CREATE OR REPLACE PROCEDURE procDML()
BEGIN
    SELECT * FROM Tab1;
END;
SELECT statement is not allowed in procedures. Procedures don't return values.

Variables and Arguments in Procedures

CREATE OR REPLACE PROCEDURE procVar()
BEGIN
    DECLARE Var1 INTEGER;
    SET Var1 = 2;
    UPDATE procTab SET Number = Var1 WHERE Number = 1;

END;
We can use variables in procedures.  
CALL procVar();
SELECT * FROM procTab;

CREATE PROCEDURE procArg(Arg1 INT)
BEGIN
    UPDATE procTab SET Number = Arg1 WHERE Number = 2;
END;
Procedures can accept arguments.

CALL procArg(3); SELECT * FROM procTab;

CREATE PROCEDURE procArg(Arg1 INT, Arg2 INT)
BEGIN
    UPDATE procTab SET Number = Arg1 + Arg2 WHERE Number = 3;
END;
We can overload procedures, just like functions.
CALL procArg( 2, 2 );
SELECT * FROM procTab;

When deleting overloaded procedure we have to use the full signature.
DROP PROCEDURE procArg( INT );
DROP PROCEDURE procArg( INT, INT );
DROP ALL PROCEDURE procARG;If we use ALL keyword, then we can delete all of the overloaded functions that share the same name, at once.

Transactions in Procedures

CREATE OR REPLACE PROCEDURE procTrans()
BEGIN
    START TRANSACTION;
    UPDATE procTab SET Number = 5 WHERE Number = 4;         COMMIT;
END;
Because we can not use DDL statemens inside of procedures, then it is not possible to use transaction statements.

CREATE OR REPLACE PROCEDURE procTrans()
BEGIN ATOMIC
    UPDATE procTab SET Number = 5 WHERE Number = 4;
END;
Just like with functions, we have to use ATOMIC keyword
after BEGIN to make procedure one big transaction.

Flow Controls in Procedures

Inside procedures we can use
flow control statements like
CASE, WHILE and IF.  
CREATE OR REPLACE PROCEDURE procCASE(Arg1 CHAR)
BEGIN ATOMIC
     DECLARE Res INT;
     CASE
          WHEN Arg1 = 'A' THEN SET Res = 6;
          ELSE SET Res = 7;
     END CASE;
     UPDATE procTab SET Number = Res;
END;
CALL procCASE( 'A' );
SELECT * FROM procTab;


System Tables

We can read about procedures from sys.functions system table. Procedures are of the type "2". User created procedures have "false" in the system column.
SELECT * FROM sys.functions WHERE name = 'proctrans';

Data about procedures argument can be found in the system table sys.args.
SELECT * FROM sys.args WHERE func_id = 15148;

Nesting Functions and Procedures

We will try to call this function from one other function:
CREATE OR REPLACE FUNCTION funcReturnOne()
RETURNS INTEGER BEGIN
     RETURN 1;
END;
This is a function calling a function.
CREATE OR REPLACE FUNCTION funcReturnSum()
RETURNS INTEGER BEGIN
     RETURN funcReturnOne() + 2;
END;
This will work, we can chain functions.

SELECT funcReturnSum();

CREATE OR REPLACE FUNCTION funcProc()
RETURNS INTEGER
BEGIN
     CALL procCASE( 'B' );
     RETURN 1;
END;
This time, we will call procedure from a function. This function will work as expected.
SELECT funcProc();
Procedure "procCASE" will also do its job. It will change the value in "procTab" table.
SELECT * FROM procTab;

It is also possible to nest procedures. This will be inner procedure:
CREATE PROCEDURE procInner()
BEGIN
    UPDATE procTab SET Number = 8 WHERE Number = 7;
END;
This outer procedure will just call inner procedure:
CREATE PROCEDURE procOuter()
BEGIN
    CALL procInner();
END;

CALL procOuter();
Outer procedure will call inner procedure, and inner procedure will update the table.
SELECT * FROM procTab;

Deleting a Procedure

DROP PROCEDURE IF EXISTS procDDL();If we use "IF EXISTS", then deleting of a procedure will never return an error.
If we try to delete not existing procedure, there will be no error, if we use "IF EXISTS".
DROP PROCEDURE IF EXISTS procZZZ();

Function funcProc() is depentand on the procedure "procCASE". That means that we can not delete "procCASE" procedure.DROP PROCEDURE procCASE;
DROP PROCEDURE procCASE CASCADE;We can use CASCADE keyword to delete procedure and all of the depending objects. Now our procedure is deleted.

Leave a Comment

Your email address will not be published. Required fields are marked *