DM8数据库DESCRIBE命令详解:获取对象结构信息
🌺The Begin🌺点点关注,收藏不迷路🌺
|
一、DESCRIBE命令概述
在达梦数据库(DM8)中,DESCRIBE(或简写为DESC)是一个非常实用的命令,用于获取数据库对象的结构信息。这个命令可以帮助开发人员和DBA快速了解表、视图、存储过程、函数、包等各种数据库对象的结构定义。
DESCRIBE命令的基本语法非常简单:
DESC[RIBE] [<模式名>.]<对象名>;
二、不同类型对象的结构信息
1. 表或视图
对于表和视图,DESCRIBE会返回以下信息:
- 列名
- 列数据类型
- 列是否允许为空
示例1:获取表sysgrants的结构描述
SQL> desc MYDMDB.employees;
执行结果:
SQL> desc MYDMDB.employees;
行号 NAME TYPE$ NULLABLE
---------- ------------- ------------ --------
1 EMPLOYEE_ID INTEGER N
2 FIRST_NAME VARCHAR(50) N
3 LAST_NAME VARCHAR(50) N
4 EMAIL VARCHAR(100) Y
5 PHONE_NUMBER VARCHAR(20) Y
6 HIRE_DATE DATE N
7 JOB_ID VARCHAR(20) N
8 SALARY DEC(10, 2) Y
9 DEPARTMENT_ID INTEGER Y
10 MANAGER_ID INTEGER Y
11 BIRTH_DATE DATE Y
行号 NAME TYPE$ NULLABLE
---------- ------- ------------ --------
12 GENDER CHAR(1) Y
13 ADDRESS VARCHAR(200) Y
13 rows got
已用时间: 19.512(毫秒). 执行号:502.
SQL>
2. 函数和存储过程
对于函数和存储过程,DESCRIBE返回两类信息:
- 存储函数/过程名、类型(函数或过程)、函数返回值类型
- 参数名、参数数据类型、参数输入输出属性、参数缺省值
示例2:获取存储过程的结构描述
CREATE OR REPLACE PROCEDURE PROC_1(A IN OUT INT) AS
B INT;
BEGIN
A:=A+B;
EXCEPTION
WHEN OTHERS THEN NULL;
END;
/
SQL> describe PROC_1;
执行结果:
行号 NAME TYPEV IO DEF RT_TYPE
---------- ------ ------- ----- --- -------
1 PROC_1 PROC
2 A INTEGER INOUT
3. 包
对于包,DESCRIBE返回的信息与函数/过程类似,但会包含包内所有函数和过程的信息:
- 包内存储函数/过程名、类型、函数返回值类型
- 包内参数名、参数数据类型、参数输入输出属性、参数缺省值
示例3:获取包的结构描述
- 创建员工表并插入测试数据
-- 创建员工表
CREATE TABLE Employee(
EmpID INT IDENTITY,
EmpName VARCHAR(100),
Department VARCHAR(50),
Salary DECIMAL(10,2),
JoinDate DATE
);
-- 插入测试数据
INSERT INTO Employee(EmpName, Department, Salary, JoinDate)
VALUES('张三', '研发部', 15000.00, '2020-05-10');
INSERT INTO Employee(EmpName, Department, Salary, JoinDate)
VALUES('李四', '市场部', 12000.00, '2019-08-15');
INSERT INTO Employee(EmpName, Department, Salary, JoinDate)
VALUES('王五', '财务部', 18000.00, '2021-03-22');
- 创建员工管理包规范
CREATE OR REPLACE PACKAGE EmployeeMgmt AS
-- 自定义异常
E_NoEmployee EXCEPTION;
-- 包级变量
TotalEmployee INT;
EmpCursor CURSOR;
-- 添加员工
PROCEDURE AddEmployee(
EName VARCHAR(100),
EDept VARCHAR(50),
ESalary DECIMAL(10,2),
EJoinDate DATE
);
-- 删除员工(按姓名和部门)
PROCEDURE RemoveEmployee(
EName VARCHAR(100),
EDept VARCHAR(50)
);
-- 删除员工(按ID)
PROCEDURE RemoveEmployee(
EID INT
);
-- 获取员工总数
FUNCTION GetEmployeeCount RETURN INT;
-- 列出所有员工信息
PROCEDURE ListAllEmployees;
-- 按部门统计平均工资
FUNCTION GetDeptAvgSalary(
DeptName VARCHAR(50)
) RETURN DECIMAL(10,2);
END EmployeeMgmt;
/
- 创建员工管理包体
CREATE OR REPLACE PACKAGE BODY EmployeeMgmt AS
-- 添加员工
PROCEDURE AddEmployee(
EName VARCHAR(100),
EDept VARCHAR(50),
ESalary DECIMAL(10,2),
EJoinDate DATE
) AS
BEGIN
INSERT INTO Employee(EmpName, Department, Salary, JoinDate)
VALUES(EName, EDept, ESalary, EJoinDate);
TotalEmployee := TotalEmployee + SQL%ROWCOUNT;
PRINT('成功添加员工: ' || EName);
EXCEPTION
WHEN OTHERS THEN
PRINT('添加员工失败: ' || SQLERRM);
END AddEmployee;
-- 删除员工(按姓名和部门)
PROCEDURE RemoveEmployee(
EName VARCHAR(100),
EDept VARCHAR(50)
) AS
BEGIN
DELETE FROM Employee
WHERE EmpName LIKE EName
AND Department LIKE EDept;
TotalEmployee := TotalEmployee - SQL%ROWCOUNT;
PRINT('成功删除员工: ' || EName || ' (' || EDept || ')');
EXCEPTION
WHEN OTHERS THEN
PRINT('删除员工失败: ' || SQLERRM);
END RemoveEmployee;
-- 删除员工(按ID)
PROCEDURE RemoveEmployee(EID INT) AS
BEGIN
DELETE FROM Employee WHERE EmpID = EID;
TotalEmployee := TotalEmployee - SQL%ROWCOUNT;
PRINT('成功删除员工ID: ' || EID);
EXCEPTION
WHEN OTHERS THEN
PRINT('删除员工失败: ' || SQLERRM);
END RemoveEmployee;
-- 获取员工总数
FUNCTION GetEmployeeCount RETURN INT AS
BEGIN
RETURN TotalEmployee;
END GetEmployeeCount;
-- 列出所有员工信息
PROCEDURE ListAllEmployees AS
V_ID INT;
V_Name VARCHAR(100);
V_Dept VARCHAR(50);
V_Salary DECIMAL(10,2);
V_JoinDate DATE;
BEGIN
IF TotalEmployee = 0 THEN
RAISE E_NoEmployee;
END IF;
OPEN EmpCursor FOR
SELECT EmpID, EmpName, Department, Salary, JoinDate
FROM Employee;
LOOP
FETCH EmpCursor INTO V_ID, V_Name, V_Dept, V_Salary, V_JoinDate;
EXIT WHEN EmpCursor%NOTFOUND;
PRINT('ID: ' || V_ID ||
', 姓名: ' || V_Name ||
', 部门: ' || V_Dept ||
', 薪资: ' || V_Salary ||
', 入职日期: ' || TO_CHAR(V_JoinDate, 'YYYY-MM-DD'));
END LOOP;
CLOSE EmpCursor;
EXCEPTION
WHEN E_NoEmployee THEN
PRINT('错误: 当前没有员工记录!');
WHEN OTHERS THEN
PRINT('列出员工失败: ' || SQLERRM);
END ListAllEmployees;
-- 按部门统计平均工资
FUNCTION GetDeptAvgSalary(
DeptName VARCHAR(50)
) RETURN DECIMAL(10,2) AS
AvgSal DECIMAL(10,2);
BEGIN
SELECT AVG(Salary) INTO AvgSal
FROM Employee
WHERE Department = DeptName;
RETURN NVL(AvgSal, 0);
EXCEPTION
WHEN OTHERS THEN
RETURN -1; -- 返回-1表示出错
END GetDeptAvgSalary;
-- 包初始化部分
BEGIN
SELECT COUNT(*) INTO TotalEmployee FROM Employee;
PRINT('员工管理包初始化完成,当前员工数: ' || TotalEmployee);
END EmployeeMgmt;
/
- 描述包结构
-- 查看包结构
DESCRIBE EmployeeMgmt;
三、DESCRIBE的高级显示设置
达梦数据库的DESCRIBE命令支持多种显示设置,可以更灵活地控制输出格式:
1. DEPTH参数
控制显示嵌套类型的深度:
SET DESCRIBE DEPTH <n>;
其中n表示要显示的深度级别。
2. LINENUM参数
控制是否显示行号ID和PID信息:
SET DESCRIBE LINENUM ON|OFF;
3. INDENT参数
控制是否对嵌套结构进行缩进显示:
SET DESCRIBE INDENT ON|OFF;
示例4:使用DEPTH显示列的结构信息
-- 创建复杂类型和表
CREATE TYPE ADDRESS AS OBJECT
( STREET VARCHAR2(20),
CITY VARCHAR2(20)
);
/
CREATE TYPE ADDRESS1 AS OBJECT
( NO INT,
SADDR ADDRESS
);
/
CREATE TABLE EMPINFO
( LAST_NAME VARCHAR2(30),
EMPADDR ADDRESS,
SMADDR ADDRESS1,
JOB_ID VARCHAR2(20),
SALARY NUMBER(7,2)
);
-- 设置显示方式
SQL> SET DESCRIBE DEPTH 1 LINENUM ON INDENT ON;
-- 获取表结构
SQL> DESC EMPINFO;
执行结果:
行号 ID PID NAME TYPEV NULLABLE
---------- -- --- --------- ----------- --------
1 1 LAST_NAME VARCHAR(30) Y
2 2 EMPADDR ADDRESS Y
3 3 2 STREET VARCHAR(20)
4 4 2 CITY VARCHAR(20)
5 5 SMADDR ADDRESS1 Y
6 6 5 NO INTEGER
7 7 5 SADDR ADDRESS
8 8 JOB_ID VARCHAR(20) Y
9 9 SALARY DEC(7, 2) Y
9 rows got
四、注意事项
-
当仅声明了包或自定义类型中的过程或函数,但包还未创建包主体或自定义类型还未创建类型体时,对包或自定义类型使用DESC会报错。
-
对于复杂嵌套类型,合理使用DEPTH参数可以控制信息的显示深度,避免输出过于冗长。
-
在脚本中使用DESCRIBE时,建议明确设置显示参数以确保输出格式的一致性。
五、总结
达梦数据库的DESCRIBE命令是数据库开发和维护中不可或缺的工具,它能够快速展示数据库对象的结构信息,极大提高了工作效率。通过合理使用各种显示参数,我们可以根据需要定制输出格式,获取最符合需求的结构信息。
掌握DESCRIBE命令的使用方法,将帮助您更高效地进行达梦数据库的开发和管理工作。
🌺The End🌺点点关注,收藏不迷路🌺
|