语法知识和案例
目录
- 前言
- 一、select查询
- 二、DM程序设计基础
- 1.变量声明及初始化
- 2.变量的赋值
- 3.变量类型
- 3.1标量
- 3.2 大数据类型
- 3.3 %TYPE 类型
- 3.4 %ROWTYPE
- 3.5 动态数组
- 三、案例
- 1.数据库查询与操作
- 2.DM SQL程序设计基础
- 总结
前言
主要涵盖了数据库查询和DM(Data Migration)程序设计基础的相关内容,以下是对各部分的总结:
一、select查询
select 查询项 from 表格
where 条件表达式
group by 分组字段 having 统计结果的条件表达式
order by 排序字段 desc/asc
limit 偏移量 ,记录数;
--设置当前模式为达梦
set schema dmhr;
例1.查询employee表中,工资在2000到5000之间的员工信息
select * from employee where salary between 2000 and 5000;
例2:查询部门编号(department)为101,102,103的员工信息
select * from employee where department_id in(101,102,103);
例3:查询employee表中姓名中姓黄的员工信息
'_':任意单个字符
'%':任意多个字符
select * from employee where employee_name like '黄%';
例4.查询各部门的人数,人数排名前5,显示部门名称,人数。
select department_name as 部门名称 ,count(*) as 人数
from department
group by department_name
order by count(*) desc
limit 5;
例5.查询employee各工作岗位的人数,人数排名前6-10的记录,显示中文工作编号,人数.
select job_id 工作编号,count(*) 人数
from employee
group by job_id
order by count(*) desc
limit 5,5;
hav
select
from 表1 join 表2
on 表2.公共字段=表1.公共字段
--非公共字段前面的表名可以省略不写,但是公共字段必须写
例6:查询员工的姓名(employee_name)、员工电话号码(phone_num)、员工的部门名称(department_name)、员工的地址编号(location_id)
select employee_name,phone_num,department_name,location_id,a.department_id
from employee a
join department b
on b.department_id=a.department_id;
例7:查询所有街道所在城市名称,显示街道名称,城市名称
select street_address,city_name from city a inner join location b on b.city_id=a.city_id;
--连接成一张大表
select
from
inner join location 表2 on 表2.公共字段=表1.公共字段
group by
order by
limit
练习8-1:查询街道“江宁开发区迎翠路7号”所在城市
select street_address,city_name
from city a
inner join location b on b.city_id=a.city_id
练习8-2:查询所有街道所在城市名称,显示街道名称,城市名称,按照city_name 排序 desc 前面5条记录
select street_address,city_name
from city a inner join location b on b.city_id = a.city_id
order by city_name desc
limit 5;
例9:查询员工编号(employee_id)、姓名(employee_name)、电子邮箱(email),所属部门(department_name),职务(job_title)、办公城市(city_name)。
员工编号(employee_id)、姓名(employee_name)、电子邮箱(email) = >来自于employee
所属部门(department_name) => 来自于department
职务(job_title) => 来自于job
办公城市(city_name) => 来自于city
select a.employee_id,employee_name,email,department_name,job_title,city_name
from employee a inner join job b on b.job_id=a.job_id
inner join department c on c.department_id=a.department_id
inner join location d on d.location_id=c.location_id
inner join city e on e.city_id=d.city_id;
例10:部门名称为“行政部”且所在城市为“武汉”的员工的员工编号(employee_id)、姓名(employee_name)、电子邮箱(email),所属部门(department_name),职务(job_title)、办公城市(city_name)。
select a.employee_id,employee_name,email,department_name,job_title,city_name
from employee a inner join job b on b.job_id=a.job_id
inner join department c on c.department_id=a.department_id
inner join location d on d.location_id=c.location_id
inner join city e on e.city_id=d.city_id
where department_name='行政部' and city_name='武汉';
例13:查询街道“江宁开发区迎翠路7号”所在城市
第一步查询街道的city_id
elect city_id from location where street_address='江宁开发区迎翠路7号';--nj
第二步根据city_id查询相应的城市名称
select city_name from city where city_id=(select city_id from location where street_address='江宁开发区迎翠路7号');
二、DM程序设计基础
1.变量声明及初始化
标识符[constant] 数据类型 [not null][:= | default 表达式];
代码如下(示例):
DECLARE
v_name varchar(40) not null:='马学铭';
BEGIN
SELECT * FROM dmhr.employee WHERE employee_name=v_name;
END;
练习1:定义一个变量dep_id,初始值为‘104’,请查询department_id=dep_id的所有员工记录
DECLARE
dep_id int not null:='104';
BEGIN
SELECT * FROM dmhr.department WHERE department_id=dep_id;
END;
2.变量的赋值
variable :=expression
或者 set variable :=expression
操作符: + - * / < > <> :=赋值符号 IS NULL LIKE BETWEEN IN AND OR NOT
3.变量类型
3.1标量
数字型:INT, INTEGER, BIGINT, SMALLINT, BYTE, NUMERIC, BIT, FLOAT, DOUBLE, DECIMAL, NUMERIC
字符型:CHAR, VARCHAR
日期时间型:DATE, TIME, TIMESTAMP
布尔型:BOOL, BOOLEAN
3.2 大数据类型
BLOB, CLOB, TEXT, IMAGE, LONGVARBINARY, LONGVARCHAR, BFILE
3.3 %TYPE 类型
表名 %type
在程序中,变量可以被用来处理存储在数据库表中的数据。在这种情况下,变量应该拥有与表列相同的类型
练习2:请定义一个变量v_phone 与employee表中phone_num字段的数据类型保持一致。
DECLARE
v_phone dmhr.employee.phone_num %type;
v_email dmhr employee.email %type;
3.4 %ROWTYPE
将返回一个基于表定义的复合类型,它将一个记录声明为具有相同结构的数据表的一行。与%type类似,如果表结构定义发生变化了,那么%ROWTYPE类型也发生变化。
代码如下(示例):
set schema dmhr;
DECLARE
emp_record employee %ROWTYPE;
BEGIN
select * into emp_record from dmhr.employee where employee_id='1003';
print emp_record.employee_id;
print emp_record.identity_card;
print emp_record.phone_num;
print emp_record.email;
print emp_record.hire_date;
END;
练习3:定义一个变量job_record,将job_id=21的job记录显示出来,请输出
job_title.min_salary.max_salary
set job_title.min_salary.max_salary from dmhr.job where job_id=21;
DECLARE
job_record dmhr.job %ROWTYPE;
BEGIN
select * into job_record from dmhr.job where job_id=21;
print job_record.job_title;
print job_record.min_salary;
print job_record.max_salary;
END;
3.5 动态数组
动态数组语法格式:
TYPE 数组名 IS ARRAY 数据类型[,...]
为多维动态数组分配空间的语法如下:
数组名 := NEW 数据类型[常量表达式1, 常量表达式2,...]
例5:动态数组举例
DECLARE
TYPE array_type IS ARRAY INT[]; -- 定义数组类型
a array_type;-- 用自己定义的数组类型声明数组
BEGIN
a:=NEW INT[8]; --动态分配空间
FOR i IN 1..8 LOOP
a[i]:=i*10;
print a[i];
END LOOP;
END;
例6:多维动态数组举例
DECLARE
TYPE array_type IS ARRAY INT[,]; -- 定义数组类型
a array_type;-- 用自己定义的数组类型声明数组
BEGIN
a:=NEW INT[3,4]; --动态分配空间
FOR i IN 1..3 LOOP
FOR J IN 1..4 LOOP
a[i][j]:=i+j;
print a[i][j];
END LOOP;
END;
三、案例
数据库的E-R图如下:
1.数据库查询与操作
set schema dmhr;
练习1:在DMHR模式下,查询工资为8000~12000元的员工信息。
select * from employee where salary between 8000 and 12000;
参考截图:
2.在DMHR模式下,查询姓名为两个汉字且姓“周”的员工的姓名、职务、工资及提高20%后的工资,并用中文显示列名。
select a.employee_name as 姓名,b.job_title as 职务,a.salary as 工资,a.salary * 1.2 as 提高后的工资
from employee a
join job b
on b.job_id=a.job_id
where a.employee_name like '周_';
参考截图:
3.在DMHR模式下,查询2012年以后入职的员工信息,要求显示员工的姓名、所属部门、电子邮箱、电话号码、入职日期和工资。
select a.employee_name as 姓名,b.department_id as 所属部门,a.email as 电子邮箱,a.phone_num as 电话号码,a.hire_date as 入职日期,a.salary as 工资
from employee a
inner join department b on a.department_id=b.department_id
where a.hire_date>'2012-01-1';
参考截图:
4.在DMHR模式下,从员工表查询员工数量大于100的部门,要求显示部门名称、员工数量,并用中文显示列名。
select department_name as 部门名称,count(*) as 员工数量
from employee a
inner join department b on a.department_id=b.department_id
group by department_name
having count(*)>100;
参考截图:
2.DM SQL程序设计基础
SET SCHEMA dmhr;
1.自定义类型定义动态数组。变量分配一个包含5个元素的数组空间,for循环遍历范围
DECLARE
TYPE v_var_type IS VARCHAR(100);
TYPE v_varry_type IS ARRAY v_var_type[];
b v_varry_type;
BEGIN
b = new v_var_type[5];
FOR i IN 1..4 LOOP
b[i] :=i*11;
PRINT b[i];
END LOOP;
PRINT ARRAYLEN(b);
END;
参考截图:
2.补充完成:【例1-31】REPEAT语句用法举例-1。
DECLARE
a int;
BEGIN
a:=0;
REPEAT
print a;
a:=a+1;
UNTIL a>10;
END;
参考截图:
3.补充完成:【例1-31】REPEAT语句用法举例-2
DECLARE
a int;
BEGIN
a:=0;
REPEAT
print a;
a:=a+1;
UNTIL a>11;
END;
参考截图:
4.循环语句 FOR语句应用:输出1+2+3+...+n的结果s ,n=10
DECLARE
s int:=0;
n int:=10;
BEGIN
FOR i IN 1..n LOOP
s:=s+i;
END LOOP;
PRINT '1+2+3+...+n='||s;
END;
参考截图:
5. 条件控制语句 IF-THEN-ELSE 应用:
定义变量 x = 32
如果 x ≥ 18,则输出“允许参加竞赛”
如果 x < 18,则输出“不允许参加竞赛”
DECLARE
x NUMBER :=32;
BEGIN
IF x>=18 THEN
PRINT ('允许参加竞赛');
ELSE
PRINT ('不允许参加竞赛');
END IF;
END;
参考截图:
四、 异常处理与游标应用实战
1..预定义的异常
(没有抛出异常,直接输出异常)
例1.更新指定员工工资,如工资小于8500,则加100
set schema dmhr;
DECLARE
v_empno employee.employee_id%TYPE :=1003;
v_sal employee.salary%TYPE;
BEGIN
SELECT salary INTO v_sal FROM employee WHERE employee_id=v_empno;
IF v_sal<=8500 THEN
UPDATE employee SET salary=salary+100 WHERE employee_id=v_empno;
PRINT('编码为'||v_empno||'员工工资已更新!');
ELSE
PRINT('编码为'||v_empno||'员工工资已经超过规定值!');
END IF;
EXCEPTION
WHEN NO_DATA_FOUND THEN
PRINT('数据库中没有编码为'||v_empno||'的员工');
END;
2.非预定义的异常
此方法可以关联DM服务器内部异常,
语法如下: 异常名 EXCEPTION;
PRAGMA EXCEPTION_INIT (异常名,错误号)
例2:删除指定部门的记录信息,以确保该部门没有员工。
(在DM服务器内部异常):
DECLARE
v_deptno department.department_id%TYPE :=102
BEGIN
DELETE FROM department WHERE department_id=v_deptno
END;
例3:更新指定部门的记录信息,薪水=原薪水+100。
set schema dmhr;
区别:
当UPDATE或DELETE语句的WHERE子句未找到时触发属性SQL%NOTFOUND;
SELECT...INTO语句WHERE子句未找到时会触发异常:NO_DATA_FOUND。
DECLARE
empno_exception EXCEPTION;
BEGIN
UPDATE dmhr.employee SET salary=salary+100 WHERE employee_id=:v_empno;
IF SQL%NOTFOUND THEN
RAISE empno_exception;
END IF;
EXCEPTION
WHEN empno_exception THEN
PRINT('你的数据更新语句失败了!');
WHEN OTHERS THEN
NULL;
END;
3.游标
循环读取数据举例:
例:查询前10名员工的信息。
第一种方式(1)while...loop
set schema dmhr;
DECLARE
v_ename employee.employee_name%TYPE;
v_sal employee.salary%TYPE;
CURSOR c_cursor IS SELECT employee_name,salary FROM dmhr.employee WHERE rownum<11;
BEGIN
OPEN c_cursor;
FETCH c_cursor INTO v_ename,v_sal;
while(c_cursor%FOUND) loop --当最近一次读记录时成功返回,则值为TRUE;
print(v_ename||'的工资是:'||v_sal);
FETCH c_cursor INTO v_ename,v_sal;
end loop;
close c_cursor;
END;
第二种方式(2) loop...end loop
set schema dmhr;
DECLARE
v_ename employee.employee_name%TYPE;
v_sal employee.salary%TYPE;
CURSOR c_cursor IS SELECT employee_name,salary FROM dmhr.employee WHERE rownum<11;
BEGIN
OPEN c_cursor;
LOOP
FETCH c_cursor INTO v_ename,v_sal;
EXIT WHEN c_cursor%NOTFOUND;
PRINT(v_ename||'的工资是:'||v_sal);
END LOOP;
close c_cursor;
END;
第三种方式
(3)For 记录名 in 游标名 LOOP;
end loop;
for它自动打开,关闭游标,提取数据,推进指针
set schema dmhr;
DECLARE
v_ename employee.employee_name%TYPE;
v_sal employee.salary%TYPE;
CURSOR c_cursor IS SELECT employee_name,salary FROM dmhr.employee WHERE rownum<11;
BEGIN
FOR c_record IN c_cursor LOOP
print c_record.employee_name||'工资是:'||c_record.salary ;
END LOOP;
END;
4.应用实战
1.题目: 编写一个DM SQL代码块,使用FOR循环和游标,从表中读取职位ID为31的员工的employee_id、employee_name、phone_num和email,并打印这些信息。
提示: 使用游标参数来传递职位ID,并在FOR循环中打印每个员工的信息。
说明:
-
游标定义: 定义了一个带参数的游标emp_cursor,该参数用于接收职位ID。
-
FOR循环: 使用FOR循环读取职位ID为31的员工信息。
-
打印信息: 使用PRINT语句打印每个员工的employee_id、employee_name、 phone_num和email
SET SCHEMA DMHR;
DECLARE
CURSOR emp_cursor(v_job_id employee.job_id%TYPE)
IS SELECT employee_id, employee_name, phone_num, email
FROM employee
WHERE job_id=v_job_id;
BEGIN
FOR v_record IN emp_cursor(31) loop
PRINT v_record.employee_id;
PRINT v_record.employee_name;
PRINT v_record.phone_num;
PRINT v_record.email;
END LOOP;
END;
参考截图:
2.题目:使用CTAS方式创建一个新表 dmhr.t1_employee ,基于 dmhr.employee 表的结构和数据。然后参考【例 1-54】编写一个DM SQL代码块,使用游标定位操作,删除 dmhr.t1_employee 表中 department_id 为 101 的第 3 条记录。
说明
-
创建新表: 使用 CREATE TABLE AS SELECT (CTAS) 方式创建 dmhr.t1_employee 表,该表具有与 dmhr.employee 表相同的结构和数据。
-
游标定义:定义了一个带 FOR UPDATE 子句的游标 emp_cursor,用于锁定 department_id 为 101 的记录,以便进行删除操作。
-
游标操作:使用 FETCH ABSOLUTE 语句遍历游标,游标定位到结果集中的第 3 条记录。
-
删除记录:使用 DELETE WHERE CURRENT OF 语句删除游标当前指向的记录。
-
关闭游标:游标使用完后,关闭游标,从内存释放活动集。
-
事务提交:在操作完成后提交事务,以确保数据更改永久生效。
CREATE TABLE dmhr.t1_employee AS
SELECT *FROM dmhr.employee;
DECLARE
CURSOR emp_cursor IS
SELECT*FROM dmhr.t1_employee WHERE DEPARTMENT_ID=101 FOR UPDATE;
BEGIN
OPEN emp_cursor;
FETCH ABSOLUTE 3 emp_cursor;
DELETE FROM dmhr.t1_employee
WHERE CURRENT OF emp_cursor;
close emp_cursor;
COMMIT;
END;
参考截图:
4. 题目:使用CTAS方式创建一个新表 dmhr.t2_employee ,基于 dmhr.employee 表的结构和数据。写一个DM SQL代码块,使用游标定位操作,将 dmhr.t2_employee 表中 department_id 为 101 的第 3 条记录中工资 salary 列增加 1000。
说明:
创建新表:使用 CREATE TABLE AS SELECT (CTAS) 方式创建 dmhr.t2_employee 表,该表具有与 dmhr.employee 表相同的结构和数据。
游标定义:定义了一个带 FOR UPDATE 子句的游标 emp_cursor,用于锁定 department_id 为 101 的记录,以便进行更新操作。
游标操作:使用 FETCH ABSOLUTE 语句遍历游标,游标定位到结果集中的第 3 条记录。
更新数据:使用 UPDATA SET WHERE CURRENT OF 语句更新游标当前指向的记录的 salary 列。
关闭游标:游标使用完后,关闭游标,从内存释放活动集。
事务提交:在操作完成后提交事务,以确保数据更改永久生效。
CREATE TABLE dmhr.t2_employee AS
SELECT * FROM DMHR.employee;
DECLARE
CURSOR emp_cursor IS
SELECT * FROM dmhr.t2_employee WHERE department_id = 101 FOR UPDATE;
BEGIN
OPEN emp_cursor;
FETCH ABSOLUTE 3 emp_cursor;
UPDATE dmhr.t2_employee SET SALARY=salary+1000 WHERE CURRENT OF emp_cursor;
CLOSE emp_cursor;
COMMIT;
END;
参考截图:
总结
对整个文档的内容进行了回顾和总结,帮助读者巩固所学知识。通过以上章节的学习,读者可以掌握基本的数据库查询技术和异常处理与游标、DM程序设计的基础知识,从而在实际工作中能够有效地进行数据处理和分析。