DM8 提供了过程化 SQL 编程能力,通常称为 DMSQL。其语法与 PL/SQL 高度兼容,并支持通过存储过程、存储函数、包等方式实现数据库端业务逻辑。
DMSQL程序是对标准SQL语言的扩展,是一种过程化SQL语言。普通的SQL语句只能执行单一的数据查询或操作,而DMSQL程序在此基础上增加了编程语言的特点——通过逻辑判断、循环控制等结构,可以实现复杂的功能和业务逻辑。
简单来说:SQL让你“问”数据库要数据,DMSQL程序让你“告诉”数据库怎么做。
DMSQL程序具备以下核心优势:
DMSQL程序的控制结构,正是赋予SQL“智能”的关键所在。
在深入控制结构之前,先了解DMSQL的基本组成单位——语句块(Block)。
一个完整的语句块由四部分组成:
DECLARE
-- 声明部分:定义变量、常量、类型、游标等(可选)
v_name VARCHAR2(50);
v_age INT := 25;
BEGIN
-- 执行部分:编写各种PL/SQL语句和业务逻辑(必需)
v_name := '张三';
DBMS_OUTPUT.PUT_LINE('姓名:' || v_name || ',年龄:' || v_age);
EXCEPTION
-- 异常处理部分:处理运行时错误(可选)
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('发生异常!');
END;
--标记程序体部分结束
块可以嵌套——外层块中可以包含内层子块,类似于SQL中的子查询。
块的两大分类:
目前达梦数据库支持DMSQL程序的控制结构主要有三种:选择结构、循环结构以及跳转结构。
IF语句通过布尔条件(TRUE / FALSE / NULL)来控制执行流程。
基本语法:
IF condition1 THEN
statements1;
[ELSIF condition2 THEN
statements2;]
[ELSE
else_statements;]
END IF;
示例:根据部门调整工资
假设输入一个员工号,根据所属部门决定工资涨幅:
DECLARE
v_empno NUMBER(4) := 10;
v_deptno NUMBER(5);
v_increment NUMBER(4);
BEGIN
SELECT deptno INTO v_deptno FROM emp WHERE empno = v_empno;
IF v_deptno = 10 THEN
v_increment := 100; -- 10号部门涨100
ELSIF v_deptno = 20 THEN
v_increment := 150; -- 20号部门涨150
ELSE
v_increment := 200; -- 其他部门涨200
END IF;
UPDATE emp SET sal = sal + v_increment WHERE empno = v_empno;
END;
CASE语句提供两种形式:
(1)简单CASE语句:将一个表达式与多个值进行比较
CASE test_value
WHEN value1 THEN statements1;
WHEN value2 THEN statements2;
...
[ELSE else_statements;]
END CASE;
示例:根据成绩等级输出评语
DECLARE
v_grade CHAR(1) := 'B';
v_result VARCHAR2(20);
BEGIN
v_result := CASE v_grade
WHEN 'A' THEN 'Excellent'
WHEN 'B' THEN 'Very Good'
WHEN 'C' THEN 'Good'
ELSE 'INPUT ERROR'
END;
DBMS_OUTPUT.PUT_LINE(v_result);
END;
(2)搜索CASE语句:基于多个布尔条件进行判断
CASE
WHEN condition1 THEN statements1;
WHEN condition2 THEN statements2;
...
[ELSE else_statements;]
END CASE;
示例:根据工资区间决定涨幅
DECLARE
v_empno NUMBER(4) := 10;
v_sal NUMBER(10);
v_increment NUMBER(4);
BEGIN
SELECT sal INTO v_sal FROM emp WHERE empno = v_empno;
CASE
WHEN v_sal < 1000 THEN
v_increment := 200; -- 低于1000涨200
WHEN v_sal < 2000 THEN
v_increment := 150; -- 1000-2000涨150
ELSE
v_increment := 50; -- 2000以上涨50
END CASE;
UPDATE emp SET sal = sal + v_increment WHERE empno = v_empno;
END;
循环结构用于重复执行一段代码,循环结构主要用到的有LOOP基本循环、WHILE循环、FOR循环语句。
最简单的循环形式,需在循环体内包含EXIT语句退出,否则将陷入死循环。
基本语法:
LOOP
sequence_of_statement;
EXIT [WHEN condition];
END LOOP;
示例:插入50条测试数据
DECLARE
v_counter INTEGER;
BEGIN
v_counter := 1;
LOOP
INSERT INTO temp_table VALUES (v_counter, 'Loop index');
v_counter := v_counter + 1;
EXIT WHEN v_counter > 50;
END LOOP;
END;
当条件为TRUE时重复执行循环体,条件判断在循环开始前进行。
基本语法:
WHILE condition LOOP
sequence_of_statement;
END LOOP;
示例:使用WHILE插入50条数据
DECLARE
v_counter INTEGER;
BEGIN
v_counter := 1;
WHILE v_counter <= 50 LOOP
INSERT INTO temp_table VALUES (v_counter, 'Loop index');
v_counter := v_counter + 1;
END LOOP;
END;
基本语法:
FOR loop_counter IN [REVERSE] low_bound .. high_bound LOOP
sequence_of_statement;
END LOOP;
系统默认时,循环变量从下界到上界递增。使用REVERSE关键字,循环变量从上界到下界递减。循环变量只能在循环体内使用,循环体外不可引用。
示例:FOR循环插入50条数据
BEGIN
FOR v_counter IN 1 .. 50 LOOP
INSERT INTO temp_table VALUES (v_counter, 'Loop index');
END LOOP;
END;
示例:倒序循环
BEGIN
FOR i IN REVERSE 1 .. 5 LOOP
DBMS_OUTPUT.PUT_LINE('i = ' || i);
END LOOP;
END;
-- 输出:i = 5, i = 4, i = 3, i = 2, i = 1
实战建议:批量数据处理是循环的典型场景。例如,使用FOR循环向表中批量插入大量数据,或用循环遍历游标结果集逐行处理。
GOTO语句实现无条件跳转,将控制权转移到指定标号处。
基本语法:
<<label_name>> ... GOTO label_name;
使用限制(这也是不建议滥用GOTO的原因):
DECLARE
v_counter INTEGER := 1;
BEGIN
<<loop_start>>
DBMS_OUTPUT.PUT_LINE('Counter: ' || v_counter);
v_counter := v_counter + 1;
IF v_counter <= 5 THEN
GOTO loop_start; -- 跳回标号处
END IF;
END;
提醒:大多数场景下,使用IF、CASE和循环结构完全可以替代GOTO的功能。
文章
阅读量
获赞
