当前位置:网站首页>Introduction to DB2 SQL pl

Introduction to DB2 SQL pl

2022-06-10 18:44:00 Blue black 2020

notes : If you're not familiar with Db2 The basic concept of stored procedure and HelloWorld Example , Please refer to my other document ( https://blog.csdn.net/duke_ding2/article/details/124873609 ).

Environmental Science

  • operating system :Ubuntu 20.04
  • Db2:11.5.0.0

SQL PL brief introduction

SQL Process language (SQL Procedural Language) yes SQL Language extension of , from “ Can be in SQL Statements and language elements that implement procedural logic in statements ” form , For example, declare variables 、 conditional 、 Variable assignment, etc .

SQL PL It is mainly used for SQL stored procedure . stay SQL Stored procedures can be used SQL PL The complete .

Let's start with a simple example . create a file test3.sql as follows :

create or replace procedure test3(in score int)
	language sql
begin
	if score < 60 then
		call dbms_output.put_line('Fail');
	elseif score >= 60 and score < 80 then
		call dbms_output.put_line('Pass');
	else
		call dbms_output.put_line('Outstanding');
	end if;
end@

set serveroutput on@

call test3(70)@

set serveroutput off@

Run script , as follows :

*  temp0523 db2 -[email protected] -f test3.sql
DB20000I  The SQL command completed successfully.

DB20000I  The SET SERVEROUTPUT command completed successfully.


  Return Status = 0

Pass

DB20000I  The SET SERVEROUTPUT command completed successfully.

In this case , Conditional judgment is used , According to score value , Output the corresponding result .

Inline SQL PL

Inline SQL PL yes SQL PL Subset , be used for inline Compound statement .

Compound statement

So called compound sentences , To put it bluntly, it means to use multiple sentences begin/end ( perhaps begin atomic/end ) wrap up .

Compound statements can be divided into two types :

  • Inline Compound statement : use begin atomic/end wrap up , seeing the name of a thing one thinks of its function , It's atomic . Can contain inline SQL PL( Mentioned earlier , yes SQL PL Subset );
  • Compiled Compound statement : use begin/end wrap up , Non atomicity . Can contain all of SQL PL;

Compound statements can be run independently , It can also be included in the database object definition ( Like stored procedures 、 function ) in .

create a file test1.sql as follows :

begin
	declare a, b varchar(100);

	set a = (select * from sysibm.sysdummy1);

	select * into a from sysibm.sysdummy1;
end@

Run script , as follows :

*  temp0523 db2 -[email protected] -f test1.sql 
DB20000I  The SQL command completed successfully.

create a file test2.sql as follows :

begin atomic
	declare a, b varchar(100);

	set a = (select * from sysibm.sysdummy1);

	-- select * into a from sysibm.sysdummy1;
end@

Run script , as follows :

*  temp0523 db2 -[email protected] -f test2.sql
DB20000I  The SQL command completed successfully.

Notice the commented code in this example , It's in inline Errors will be reported in compound statements , Is this because of the above mentioned ,inline SQL PL yes SQL PL Subset , So some functions are not supported ?

SQL routine

So-called SQL routine , It just contains SQL Statement and SQL PL Statement routines . Similar to the classification of routines ,SQL Routines can be divided into SQL stored procedure 、SQL function 、SQL Method . This article only covers SQL stored procedure .

About creating SQL Syntax of routines , Please refer to https://www.ibm.com/docs/en/db2/11.5?topic=statements-create-procedure-sql .

There is a specific example in this document :

   CREATE PROCEDURE MEDIAN_RESULT_SET (OUT medianSalary DOUBLE)
     RESULT SETS 1
     LANGUAGE SQL
   BEGIN
     DECLARE v_numRecords INT DEFAULT 1;
     DECLARE v_counter INT DEFAULT 0;

     DECLARE c1 CURSOR FOR
       SELECT CAST(salary AS DOUBLE)
         FROM staff
         ORDER BY salary;
     DECLARE c2 CURSOR WITH RETURN FOR
       SELECT name, job, CAST(salary AS INTEGER)
         FROM staff
         WHERE salary > medianSalary
         ORDER BY salary;

     DECLARE EXIT HANDLER FOR NOT FOUND
       SET medianSalary = 6666;

     SET medianSalary = 0;
     SELECT COUNT(*) INTO v_numRecords
       FROM STAFF;
     OPEN c1;
     WHILE v_counter < (v_numRecords / 2 + 1)
     DO
       FETCH c1 INTO medianSalary;
       SET v_counter = v_counter + 1;
     END WHILE;
     CLOSE c1;
     OPEN c2;
   END

Let's look at this example SQL The general structure of a stored procedure :

  • CREATE PROCEDURE MEDIAN_RESULT_SET : I usually use create or replace , So as not to make mistakes when running for many times ;
  • (OUT medianSalary DOUBLE) : parameter list , There is only one in this case out Parameters ;
  • RESULT SETS 1 : optional , Indicates how many result set, The default is 0;
  • LANGUAGE SQL : optional , Express SQL stored procedure , Is the default option ;
  • BEGIN ... END :SQL The core of a stored procedure is a compound statement . Mentioned earlier , Compound statements use begin/end ( perhaps begin atomic/end ) Contains multiple statements .

notes : In this example, only 2 An option , There are many other options , Please refer to official documents for specific usage .

If you are connected sample database , be staff The table and the data inside have been prepared , You can run the stored procedure directly , Take a look at the effect .

newly build test4.sql file , Modify the above content slightly :

  • add OR REPLACE , So as not to make mistakes when running for many times ;
  • add call MEDIAN_RESULT_SET(?) , Call the stored procedure ;
  • add @ Terminator ;

as follows :

   CREATE OR REPLACE PROCEDURE MEDIAN_RESULT_SET (OUT medianSalary DOUBLE)
     RESULT SETS 1
     LANGUAGE SQL
   BEGIN
     DECLARE v_numRecords INT DEFAULT 1;
     DECLARE v_counter INT DEFAULT 0;

     DECLARE c1 CURSOR FOR
       SELECT CAST(salary AS DOUBLE)
         FROM staff
         ORDER BY salary;
     DECLARE c2 CURSOR WITH RETURN FOR
       SELECT name, job, CAST(salary AS INTEGER)
         FROM staff
         WHERE salary > medianSalary
         ORDER BY salary;

     DECLARE EXIT HANDLER FOR NOT FOUND
       SET medianSalary = 6666;

     SET medianSalary = 0;
     SELECT COUNT(*) INTO v_numRecords
       FROM STAFF;
     OPEN c1;
     WHILE v_counter < (v_numRecords / 2 + 1)
     DO
       FETCH c1 INTO medianSalary;
       SET v_counter = v_counter + 1;
     END WHILE;
     CLOSE c1;
     OPEN c2;
   END@

   call MEDIAN_RESULT_SET(?)@

function test4.sql Script , as follows :

*  temp0523 db2 -[email protected] -f test4.sql 
DB20000I  The SQL command completed successfully.

  Value of output parameters
  --------------------------
  Parameter Name  : MEDIANSALARY
  Parameter Value : +7.68582000000000E+004

  Result set 1
  --------------

  NAME      JOB   3          
  --------- ----- -----------
  Marenghi  Mgr         77506
  O'Brien   Sales       78006
  Pernal    Sales       78171
  Plotz     Mgr         78352
  Wilson    Sales       78674
  Daniels   Mgr         79260
  Williams  Sales       79456
  Hanes     Mgr         80659
  Jones     Mgr         81234
  Molinare  Mgr         82959
  Lundquist Clerk       83369
  Smith     Sales       87654
  Lea       Mgr         88555
  Quill     Mgr         89818
  Lu        Mgr         90010
  Fraye     Mgr         91150
  Sanders   Mgr         98357

  17 record(s) selected.

  Return Status = 0

so :

  • adopt out Parameters medianSalary , The value of median salary is output : +7.68582000000000E+004staff There are 35 Bar record , Number... Sorted by salary 18 Bar record , It's the median wage );
  • Through cursor c2 , Output all records greater than the median salary , Including name, 、 Work 、 Wages ;

Let's focus on SQL The body of the stored procedure , That is to say begin/end ( perhaps begin atomic/end ) The part included .

In the body , It can also contain multiple compound statements . The format is as follows :

  label:  BEGIN 
    Variable declarations
    Condition declarations
    Cursor declarations
    Condition handler declarations
    Assignment, flow of control, SQL statements and other compound statements
  END label

A specific example on the official website ( https://www.ibm.com/docs/en/db2/11.5?topic=procedures-structure-sql ):

   CREATE PROCEDURE DEL_INV_FOR_PROD (IN prod INT, OUT err_buffer VARCHAR(128))
   LANGUAGE SQL
   DYNAMIC RESULT SETS 1
   BEGIN
     DECLARE SQLSTATE CHAR(5) DEFAULT '00000';
     DECLARE SQLCODE integer DEFAULT 0;
     DECLARE NO_TABLE CONDITION FOR SQLSTATE '42704';
     DECLARE cur1 CURSOR WITH RETURN TO CALLER  
                     FOR SELECT * FROM Inv;

     A: BEGIN ATOMIC
          DECLARE EXIT HANDLER FOR NO_TABLE
            BEGIN
               SET ERR_BUFFER='Table Inv does not exist';
            END;

          SET err_buffer = '';

          IF (prod < 200)
            DELETE FROM Inv WHERE product = prod;
          ELSE IF (prod < 400)
            UPDATE Inv SET quantity = 0 WHERE product = prod;
          ELSE
            UPDATE Inv SET quantity = NULL WHERE product = prod; 
          END IF;
        END A;

      B:  OPEN cur1;
   END

But this example seems to have a syntax error …… if There is no need for then Do you ?

atomic and not atomic

Create table first C1_SCHED

create table C1_SCHED(class_code varchar(100), day int)

notes : I don't know why , These examples in the document do not correspond to sample DB Table of , I had to create it myself .

establish test6.sql The documents are as follows :

  CREATE or replace PROCEDURE not_atomic_proc ()   
  LANGUAGE SQL   
  SPECIFIC not_atomic_proc
   nap:  BEGIN NOT ATOMIC            

   INSERT INTO c1_sched (class_code, day)
     VALUES ('R11:TAA', 1);           
  
   commit;

   SIGNAL SQLSTATE '70000';   
   
   INSERT INTO c1_sched (class_code, day)               
     VALUES ('R22:TBB', 1);    

   commit;

  END [email protected]

  call [email protected]

In this case , signal Used to trigger an error , I understand it is a bit similar to Java Medium throw .

function test6.sql Script files , as follows :

*  temp0523 db2 -[email protected] -f test6.sql
DB20000I  The SQL command completed successfully.

SQL0438N  Application raised error or warning with diagnostic text: "".  
SQLSTATE=70000

*  temp0523 echo $?
4

In this case , Two insert An error occurred between statements , Because it is not atomic , first insert Statements are not affected , Because it was explicit before the error occurred commit 了 . therefore , Although the stored procedure failed to run as a whole , But the first one insert The statement has succeeded .

Be careful : If you remove commit, When an error occurs , Although the first one insert Statement does not immediately rollback , But because there is no error handling , So after the final stored procedure fails , first insert Statement will also be rolled back .

establish test7.sql The documents are as follows :

  CREATE or replace PROCEDURE atomic_proc ()
  LANGUAGE SQL  
  SPECIFIC atomic_proc  
 
  ap:  BEGIN ATOMIC            

     INSERT INTO c1_sched (class_code, day)     
       VALUES ('R33:TCC', 1);           
 
     --commit;

     SIGNAL SQLSTATE '70000';       
   
     INSERT INTO c1_sched (class_code, day)               
       VALUES ('R44:TDD', 1);    

     -- commit;

  END [email protected]

  call [email protected]

function test7.sql Script files , as follows :

*  temp0523 db2 -[email protected] -f test7.sql
DB20000I  The SQL command completed successfully.

SQL0438N  Application raised error or warning with diagnostic text: "".  
SQLSTATE=70000

Because it is atomic , So when something goes wrong , first insert Statement immediately rolls back .

Be careful : stay inline ... is not allowed in compound statements SAVEPOINTCOMMITROLLBACK And so on .

Db2 Self contained examples

Please refer to IBM Official website https://www.ibm.com/docs/en/db2/11.5?topic=samples-sample-files .

In the installation Db2 when , In the installation directory ( such as /opt/ibm/db2/V11.5/ ) There is one samples Catalog , There are many examples . One of them sqlpl Catalog , Inside is SQL PL An example of .

These examples can run on sample Database . If not created during installation sample database , It can be used at any time db2sampl Command to create .

for example loop.db2 file :

-- skip lots of comment here
CREATE PROCEDURE loop_until_space(OUT counter INT)
LANGUAGE SQL
BEGIN
  DECLARE v_firstnme VARCHAR(12);
  DECLARE v_midinit CHAR(1);
  DECLARE v_lastname VARCHAR(15);
  DECLARE v_counter SMALLINT DEFAULT 0;

  DECLARE c1 CURSOR FOR 
    SELECT firstnme, midinit, lastname 
    FROM employee
    ORDER BY midinit DESC;
  DECLARE CONTINUE HANDLER FOR NOT FOUND
    SET counter = -1;

  -- initialize OUT parameter
  SET counter = 0;
  OPEN c1;
  fetch_loop:
  LOOP
    FETCH c1 INTO 
      v_firstnme, v_midinit, v_lastname;
    -- Use a local variable for the iterator variable
    -- because SQL procedures only allow you to assign 
    -- values to an OUT parameter
    SET v_counter = v_counter + 1;
    IF v_midinit = ' ' THEN
      LEAVE fetch_loop;
    END IF;
  END LOOP fetch_loop;
  CLOSE c1;

  -- Now assign the value of the local
  -- variable to the OUT parameter
  SET counter = v_counter;
END @

So let's run this loop.db2 Script :

*  sqlpl db2 -[email protected] -f loop.db2 
DB20000I  The SQL command completed successfully.

*  sqlpl db2 "call loop_until_space(?)"

  Value of output parameters
  --------------------------
  Parameter Name  : COUNTER
  Parameter Value : 36

  Return Status = 0

notes : The sample code is all create procedure instead of create or replace procedure , So it can only be run once …… I don't quite understand why the latter is not used .

Reference resources

原网站

版权声明
本文为[Blue black 2020]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/161/202206101801476263.html