DELIMITER // CREATE OR REPLACE PROCEDURE orm_api_kernel_v2( IN p_tablename VARCHAR(100), IN p_pk VARCHAR(100), -- primary key(for update delete) IN p_action VARCHAR(20), -- CRUD IN p_uuid VARCHAR(100), IN p_json_id INT ) /* Function : 通用 orm-api 根据传入参数及设定,智能生成相应SQL Description: 模仿 ORM 设定,让前端程序只需传入参数就能执行增删查改基本功能 Build Date : 2024-03-20 call orm_api_kernel_v2('pms_sprint','sprintid','U','uuid-20250803_2',0); Modify History Item Who Date Modify Docs ==== ========== ========== ================================================ 1 Developer 2024/03/20 从 MS-SQL v2 版本转换为 MariaDB 版本并优化 */ BEGIN DECLARE v_field_identity VARCHAR(100); DECLARE v_fields TEXT; DECLARE v_datas TEXT; DECLARE v_updatedatas TEXT; DECLARE v_pkwhere TEXT; DECLARE v_sql LONGTEXT; DECLARE v_pk_cnt INT; DECLARE v_pk_no INT; DECLARE v_max_no VARCHAR(20); DECLARE v_bill_uuid VARCHAR(100); DECLARE v_bill_head VARCHAR(20); DECLARE v_middlefield VARCHAR(100); DECLARE v_dest_table VARCHAR(100); DECLARE v_pk_id VARCHAR(50); DECLARE v_fieldname VARCHAR(100); DECLARE v_contents LONGTEXT; DECLARE v_fieldtype VARCHAR(20); DECLARE v_quot CHAR(1); DECLARE v_cnt INT; DECLARE v_cnt2 INT; DECLARE v_maxcount INT; DECLARE v_currid INT; DECLARE v_nextrowid INT; DECLARE v_crlf VARCHAR(2); -- 创建临时表存储JSON数据 CREATE TEMPORARY TABLE IF NOT EXISTS temp_jsondata ( parent_id INT, json_key VARCHAR(100), json_value LONGTEXT, ValueType VARCHAR(20), rowid INT AUTO_INCREMENT PRIMARY KEY ); -- 临时表用于同步删除 CREATE TEMPORARY TABLE IF NOT EXISTS temp_sync_del ( dest_table VARCHAR(100), pk_id VARCHAR(50), rowid INT AUTO_INCREMENT PRIMARY KEY ); -- 临时表用于避免重复字段名 CREATE TEMPORARY TABLE IF NOT EXISTS temp_comp_json ( fieldname VARCHAR(100) ); -- 清空临时表 TRUNCATE TABLE temp_jsondata; TRUNCATE TABLE temp_sync_del; TRUNCATE TABLE temp_comp_json; -- 将传入参数转为JSON数据(多筆 Grid 資料寫入) IF p_json_id = 1 then INSERT INTO temp_jsondata (parent_id, json_key, json_value, ValueType) SELECT parent_id, json_key, json_value, ValueType FROM orm_json_tmp WHERE uuid = p_uuid; else INSERT INTO temp_jsondata (parent_id, json_key, json_value, ValueType) SELECT parent_id, json_key, json_value, ValueType FROM orm_json_tmp WHERE uuid = p_uuid AND parent_id = FLOOR(p_json_id / 1000) and object_id = p_json_id - FLOOR(p_json_id / 1000)*1000; end if; -- 获取自增字段 SELECT COLUMN_NAME INTO v_field_identity FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = p_tablename AND EXTRA = 'auto_increment' LIMIT 1; -- 初始化变量 SET v_fields = ''; SET v_datas = ''; SET v_pkwhere = ''; SET v_updatedatas = ''; SET v_pk_cnt = 0; SET v_bill_uuid = ''; SET v_bill_head = ''; SET v_crlf = CONCAT(CHAR(13), CHAR(10)); -- 获取记录数 SELECT COUNT(*) INTO v_maxcount FROM temp_jsondata; SELECT MIN(rowid) INTO v_currid FROM temp_jsondata; -- 遍历JSON数据构建SQL WHILE v_currid <= v_maxcount DO -- 获取当前记录 SELECT json_key, IFNULL(json_value, ''), ValueType INTO v_fieldname, v_contents, v_fieldtype FROM temp_jsondata WHERE rowid = v_currid; -- 设置引号 IF lower(v_fieldtype) = 'string' THEN SET v_quot = ''''; ELSE SET v_quot = ''; END IF; -- 记录billno和uuid用于MD更新 IF v_fieldname = 'uuid' THEN SET v_bill_uuid = v_contents; END IF; IF v_fieldname = 'billno' THEN SET v_bill_head = v_contents; END IF; -- 检查字段是否存在 SELECT COUNT(*) INTO v_cnt FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = p_tablename AND COLUMN_NAME = v_fieldname; SELECT COUNT(*) INTO v_cnt2 FROM temp_comp_json WHERE fieldname = v_fieldname; -- 如果字段存在且未处理过 IF v_cnt > 0 AND v_cnt2 <= 0 THEN -- 记录主键内容 SELECT COUNT(*) INTO v_pk_no FROM ( SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(p_pk, ',', numbers.n), ',', -1) AS col FROM ( SELECT 1 AS n UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 -- 假设最多5个主键字段 ) numbers WHERE numbers.n <= LENGTH(p_pk) - LENGTH(REPLACE(p_pk, ',', '')) + 1 ) AS split_pk WHERE col = v_fieldname; IF v_pk_no > 0 THEN IF v_pk_cnt >= 1 THEN UPDATE sys_transaction SET para02 = v_contents WHERE tablename = p_tablename; ELSE UPDATE sys_transaction SET para01 = v_contents WHERE tablename = p_tablename; END IF; SET v_pk_cnt = v_pk_cnt + 1; END IF; -- 非自增字段处理 IF IFNULL(v_field_identity, '') <> v_fieldname THEN SET v_fields = CONCAT(v_fields, v_fieldname, ','); -- 构建INSERT值 IF p_action = 'C' OR p_action = 'Insert' THEN SET v_datas = CONCAT(v_datas, v_quot, v_contents, v_quot, ','); END IF; END IF; -- 构建UPDATE语句 IF (p_action = 'U' OR p_action = 'Update') AND v_pk_no = 0 THEN -- 处理日期格式 IF SUBSTRING(v_contents, 11, 19) = 'T08:00:00.000+08:00' THEN SET v_contents = SUBSTRING(v_contents, 1, 10); END IF; SET v_updatedatas = CONCAT(v_updatedatas, v_fieldname, ' = ', v_quot, v_contents, v_quot, ','); END IF; -- 构建WHERE条件 IF v_pk_no > 0 THEN SET v_pkwhere = CONCAT(v_pkwhere, v_fieldname, ' = ', v_quot, v_contents, v_quot, ' AND '); END IF; END IF; -- 记录已处理字段 INSERT INTO temp_comp_json VALUES (v_fieldname); -- 获取下一行 SELECT MIN(rowid) INTO v_nextrowid FROM temp_jsondata WHERE rowid > v_currid; SET v_currid = v_nextrowid; END WHILE; -- 处理没有主键的情况 IF v_pk_cnt = 0 THEN SELECT middlefield INTO v_middlefield FROM sys_transaction WHERE tablename = p_tablename LIMIT 1; SELECT json_value INTO v_contents FROM temp_jsondata WHERE json_key = v_middlefield LIMIT 1; IF LENGTH(v_contents) <= 1000 THEN UPDATE sys_transaction SET para01 = v_contents WHERE tablename = p_tablename; END IF; END IF; -- 处理自增主键情况 IF (p_action = 'C' OR p_action = 'Insert') AND (p_pk = v_field_identity) THEN UPDATE sys_transaction SET para01 = 'identity' WHERE tablename = p_tablename; END IF; -- 移除末尾的逗号或AND IF v_fields <> '' THEN -- SET v_fields = SUBSTRING(v_fields, 1, LENGTH(v_fields) - 1); SET v_fields = TRIM(TRAILING ',' FROM v_fields); END IF; IF v_datas <> '' THEN -- SET v_datas = SUBSTRING(v_datas, 1, LENGTH(v_datas) - 1); SET v_datas = TRIM(TRAILING ',' FROM v_datas); END IF; IF v_updatedatas <> '' THEN -- SET v_updatedatas = SUBSTRING(v_updatedatas, 1, LENGTH(v_updatedatas) - 1); SET v_updatedatas = TRIM(TRAILING ',' FROM v_updatedatas); END IF; IF v_pkwhere <> '' THEN SET v_pkwhere = SUBSTRING(v_pkwhere, 1, LENGTH(v_pkwhere) - 5); END IF; -- 构建基础SQL IF p_action = 'C' OR p_action = 'Insert' THEN SET v_sql = CONCAT('INSERT INTO ', p_tablename, ' (', v_fields, ') VALUES (', v_datas, ')'); -- 加入 M-D 的 D 同步 billno update INSERT INTO temp_sync_del (dest_table, pk_id) SELECT dest_table, pk_id FROM sys_sync_delete_detail WHERE tablename = p_tablename; -- 处理同步更新 SELECT COUNT(*) INTO v_maxcount FROM temp_sync_del; SELECT MIN(rowid) INTO v_currid FROM temp_sync_del; WHILE v_currid <= v_maxcount DO SELECT dest_table, pk_id INTO v_dest_table, v_pk_id FROM temp_sync_del WHERE rowid = v_currid; -- 检查目标表是否有uuid字段 SELECT COUNT(*) INTO v_cnt FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = v_dest_table AND COLUMN_NAME = 'uuid'; IF v_cnt > 0 THEN SET v_sql = CONCAT(v_sql, ';\n', 'UPDATE ', v_dest_table, ' SET ', IFNULL(v_pk_id, 'billno'), ' = ''', v_bill_head, ''' WHERE uuid = ''', v_bill_uuid, ''''); END IF; -- 获取下一行 SELECT MIN(rowid) INTO v_nextrowid FROM temp_sync_del WHERE rowid > v_currid; SET v_currid = v_nextrowid; END WHILE; ELSEIF p_action = 'U' OR p_action = 'Update' THEN SET v_sql = CONCAT('UPDATE ', p_tablename, ' SET ', v_updatedatas, ' WHERE ', v_pkwhere); ELSEIF p_action = 'D' OR p_action = 'Delete' THEN -- 基础删除语句 SET v_sql = CONCAT('DELETE FROM ', p_tablename, ' WHERE ', v_pkwhere); -- 处理同步删除 INSERT INTO temp_sync_del (dest_table, pk_id) SELECT dest_table, pk_id FROM sys_sync_delete_detail WHERE tablename = p_tablename; SELECT COUNT(*) INTO v_maxcount FROM temp_sync_del; SELECT MIN(rowid) INTO v_currid FROM temp_sync_del; WHILE v_currid <= v_maxcount DO SELECT dest_table, pk_id INTO v_dest_table, v_pk_id FROM temp_sync_del WHERE rowid = v_currid; -- 解决 M-D 的 pk 栏名不同的问题 IF IFNULL(v_pk_id, '') = '' THEN SET v_sql = CONCAT(v_sql, ';', v_crlf, 'DELETE FROM ', v_dest_table, ' WHERE ', v_pkwhere, ';'); ELSE SET v_sql = CONCAT(v_sql, ';', v_crlf, 'DELETE FROM ', v_dest_table, ' WHERE ', REPLACE(v_pkwhere, p_pk, v_pk_id), ';'); END IF; -- 获取下一行 SELECT MIN(rowid) INTO v_nextrowid FROM temp_sync_del WHERE rowid > v_currid; SET v_currid = v_nextrowid; END WHILE; END IF; -- 处理日期格式问题 IF INSTR(v_sql, '000+08:00') > 0 THEN SET v_sql = REPLACE(v_sql, '000+08:00', '000Z'); END IF; -- 执行SQL /* Mariadb 不支援動態語句多 sql, 只能切割 GET DIAGNOSTICS CONDITION 1 @sqlstate = RETURNED_SQLSTATE, @errno = MYSQL_ERRNO, @text = MESSAGE_TEXT; SELECT 1 AS code, CONCAT('Error: ', @errno, ' (', @sqlstate, '): ', @text) AS msg, 0 AS recno; SELECT v_sql AS error_sql; END; -- 返回成功结果 SELECT 0 AS code, 'ok' AS msg, 0 AS recno; -- 执行SQL SET @dynamic_sql = v_sql; PREPARE stmt FROM @dynamic_sql; EXECUTE stmt; DEALLOCATE PREPARE stmt; END; */ call execute_multiple_sql(v_sql); -- 清理临时表 DROP TEMPORARY TABLE IF EXISTS temp_jsondata; DROP TEMPORARY TABLE IF EXISTS temp_sync_del; DROP TEMPORARY TABLE IF EXISTS temp_comp_json; END // DELIMITER ;