1. 达梦SQL函数基础与应用场景达梦数据库的SQL函数体系相当完善涵盖了数据处理所需的各类操作。在实际项目中我经常用这些函数来解决数据清洗、转换和计算问题。举个例子在员工管理系统中我们经常需要处理这样的场景计算员工工龄、格式化姓名、统计部门薪资等。字符串处理是最常见的需求之一。比如员工姓名可能存在前后空格或不规范的大小写这时候就可以用**TRIM()和INITCAP()**函数组合处理-- 去除空格并规范姓名格式 SELECT INITCAP(TRIM(ename)) AS formatted_name FROM employee;日期函数在考勤统计中特别实用。计算员工工龄可以用MONTHS_BETWEEN()配合FLOOR()-- 计算精确到月份的工龄 SELECT ename, FLOOR(MONTHS_BETWEEN(SYSDATE, hire_date)/12) AS work_years FROM employee;数值函数在薪资计算时大显身手。比如计算部门平均薪资并保留两位小数-- 部门薪资统计 SELECT dept_no, ROUND(AVG(salary), 2) AS avg_salary, SUM(salary) AS total_salary FROM employee GROUP BY dept_no;提示达梦的ROUND函数与Oracle行为一致但和MySQL有细微差异第二个参数为负数时表示对整数部分进行四舍五入。2. 内置函数深度解析与实战技巧2.1 字符串函数高级用法字符串处理是数据库操作的基石。达梦的REGEXP系列函数支持POSIX标准正则表达式比基础的通配符更强大。最近在处理用户地址数据时我就用到了这个功能-- 提取地址中的邮编6位数字 SELECT address, REGEXP_SUBSTR(address, [0-9]{6}) AS postal_code FROM customer WHERE REGEXP_LIKE(address, [0-9]{6});LISTAGG函数是行列转换的利器。在生成部门员工名单时-- 将部门员工姓名合并为逗号分隔的字符串 SELECT dept_no, LISTAGG(ename, ,) WITHIN GROUP (ORDER BY ename) AS members FROM employee GROUP BY dept_no;2.2 日期函数实战案例达梦的日期函数非常丰富特别是LAST_DAY和NEXT_DAY这类特殊日期计算函数。在做月度报表时我经常这样获取当月最后一天-- 获取当月最后一天23:59:59 SELECT LAST_DAY(SYSDATE) INTERVAL 23:59:59 HOUR TO SECOND FROM dual;时间间隔计算也有多种方案。计算两个日期之间的工作日排除周末-- 计算工作日函数 CREATE OR REPLACE FUNCTION work_days(start_date DATE, end_date DATE) RETURN NUMBER AS days NUMBER : 0; curr DATE : start_date; BEGIN WHILE curr end_date LOOP IF TO_CHAR(curr, DY) NOT IN (SAT, SUN) THEN days : days 1; END IF; curr : curr 1; END LOOP; RETURN days; END;3. 自定义函数开发全流程3.1 函数创建语法详解创建自定义函数的完整语法结构如下CREATE [OR REPLACE] FUNCTION 函数名 ( [参数1 [IN|OUT|IN OUT] 数据类型 [DEFAULT 默认值], 参数2 [IN|OUT|IN OUT] 数据类型...] ) RETURN 返回值类型 [AUTHID DEFINER|CURRENT_USER] [DETERMINISTIC] [PARALLEL_ENABLE] [PIPELINED] IS|AS [声明部分变量、常量、游标等] BEGIN 执行体 [EXCEPTION 异常处理] END;我开发过一个薪资计算函数包含绩效系数和考勤扣减CREATE OR REPLACE FUNCTION calc_salary( base_salary NUMBER, performance_ratio NUMBER DEFAULT 1.0, absent_days NUMBER DEFAULT 0 ) RETURN NUMBER AS daily_salary NUMBER; deduction NUMBER; BEGIN daily_salary : base_salary / 21.75; -- 月计薪天数 deduction : daily_salary * absent_days; RETURN ROUND(base_salary * performance_ratio - deduction, 2); END;3.2 复杂业务逻辑实现对于需要访问数据库的自定义函数游标是常用工具。比如这个部门薪资分析函数CREATE OR REPLACE FUNCTION dept_salary_report( p_dept_no VARCHAR2 ) RETURN CLOB AS v_result CLOB : EMPTY_CLOB(); CURSOR c_emp IS SELECT ename, salary FROM employee WHERE dept_no p_dept_no ORDER BY salary DESC; BEGIN DBMS_LOB.CREATETEMPORARY(v_result, TRUE); FOR r IN c_emp LOOP v_result : v_result || r.ename || : || r.salary || CHR(10); END LOOP; RETURN v_result; END;注意使用CLOB大对象时一定要记得释放资源这里用DBMS_LOB.CREATETEMPORARY创建的临时LOB会在会话结束时自动释放。4. 函数性能优化与调试4.1 执行计划分析技巧函数性能问题经常出现在SQL调优中。达梦的EXPLAIN命令可以分析函数调用情况-- 查看包含函数调用的SQL执行计划 EXPLAIN SELECT ename, calc_salary(salary, performance) FROM employee WHERE dept_no D001;常见优化手段包括避免在WHERE条件中使用函数对函数内访问的表建立合适索引使用DETERMINISTIC标记纯函数4.2 调试与错误处理完善的异常处理能让函数更健壮。我通常这样记录错误信息CREATE OR REPLACE FUNCTION safe_divide( a NUMBER, b NUMBER ) RETURN NUMBER AS BEGIN IF b 0 THEN INSERT INTO error_log VALUES( DIVIDE_BY_ZERO, SYSDATE, safe_divide: divisor is zero ); RETURN NULL; END IF; RETURN a / b; EXCEPTION WHEN OTHERS THEN INSERT INTO error_log VALUES( SQLCODE, SYSDATE, safe_divide: || SQLERRM ); RETURN NULL; END;5. 跨数据库函数迁移指南5.1 与Oracle函数差异达梦与Oracle函数兼容性较高但仍有需要注意的区别功能需求Oracle实现达梦实现字符串连接CONCAT或空值处理NVLNVL或ISNULL正则表达式REGEXP_系列REGEXP_系列分页查询ROWNUMROWNUM或LIMIT/OFFSET序列生成SEQUENCE.NEXTVAL相同5.2 与MySQL函数转换MySQL迁移到达梦时这些函数需要特别注意-- MySQL写法 SELECT IFNULL(salary, 0), DATE_FORMAT(hire_date, %Y-%m), GROUP_CONCAT(ename) FROM employee; -- 达梦等价写法 SELECT NVL(salary, 0), TO_CHAR(hire_date, yyyy-mm), LISTAGG(ename, ,) FROM employee;时间计算函数的转换示例-- MySQL日期加减 SELECT DATE_ADD(hire_date, INTERVAL 1 MONTH); -- 达梦等价实现 SELECT ADD_MONTHS(hire_date, 1);在实际迁移过程中我发现达梦的WM_CONCAT与MySQL的GROUP_CONCAT在排序行为上略有不同需要额外测试验证结果是否符合预期。