first commit
This commit is contained in:
@@ -0,0 +1,29 @@
|
||||
DELIMITER //
|
||||
CREATE OR REPLACE PROCEDURE execute_multiple_sql(IN v_sql TEXT)
|
||||
BEGIN
|
||||
DECLARE EXIT HANDLER FOR SQLEXCEPTION
|
||||
BEGIN
|
||||
GET DIAGNOSTICS CONDITION 1
|
||||
@sqlstate = RETURNED_SQLSTATE,
|
||||
@errno = MYSQL_ERRNO,
|
||||
@text = MESSAGE_TEXT;
|
||||
|
||||
SELECT 1 AS code, CONCAT('Error: ', @errno, ' (', @sqlstate, '): ', @text) AS msg;
|
||||
END;
|
||||
|
||||
-- 按分号分割并执行多条语句
|
||||
SET @sql = v_sql;
|
||||
WHILE LENGTH(@sql) > 0 DO
|
||||
SET @statement = SUBSTRING_INDEX(@sql, ';', 1);
|
||||
SET @sql = SUBSTRING(@sql, LENGTH(@statement) + 2);
|
||||
|
||||
IF LENGTH(TRIM(@statement)) > 0 THEN
|
||||
PREPARE stmt FROM @statement;
|
||||
EXECUTE stmt;
|
||||
DEALLOCATE PREPARE stmt;
|
||||
END IF;
|
||||
END WHILE;
|
||||
|
||||
SELECT 0 AS code, 'ok' AS msg;
|
||||
END//
|
||||
DELIMITER ;
|
||||
@@ -0,0 +1,67 @@
|
||||
DELIMITER //
|
||||
|
||||
CREATE OR REPLACE FUNCTION gf_split(
|
||||
p_source TEXT,
|
||||
p_split VARCHAR(2)
|
||||
) RETURNS TEXT
|
||||
/*
|
||||
function : 將傳入的字串, 依 p_split 切割為多筆資料, 傳回 table
|
||||
description:
|
||||
呼叫範例:
|
||||
SELECT col FROM JSON_TABLE(gf_split('R,G,B',','), '$[*]'
|
||||
COLUMNS(col VARCHAR(600) PATH '$.col')) t;
|
||||
|
||||
SELECT col FROM JSON_TABLE(gf_split('R,G,B',','), '$[*]'
|
||||
COLUMNS(rowid int PATH '$.rowid', col VARCHAR(600) PATH '$.col')) t WHERE rowid = 1;
|
||||
|
||||
必須要有 CREATE TABLE _split( guid varchar(100), rowid INT, col varchar(600) );
|
||||
|
||||
https://www.sqlines.com/sql-server-to-mariadb/returns_table
|
||||
build date : 2023/11/20
|
||||
|
||||
modify history
|
||||
item who date modify docs
|
||||
==== ========== ========== ================================================
|
||||
1 michael 2011/09/08 新增
|
||||
2 Michael 2025/07/11 改寫為MariaDB版本並優化
|
||||
*/
|
||||
BEGIN
|
||||
DECLARE v_pos INT;
|
||||
DECLARE v_cnt INT;
|
||||
DECLARE v_length INT;
|
||||
DECLARE v_temp TEXT;
|
||||
DECLARE p_uuid VARCHAR(100);
|
||||
DECLARE data TEXT;
|
||||
|
||||
SET v_length = LENGTH(p_split);
|
||||
SET v_temp = p_source;
|
||||
SET p_uuid = UUID();
|
||||
SET v_cnt = 1;
|
||||
|
||||
-- 循環處理分割
|
||||
WHILE LOCATE(p_split, v_temp) > 0 DO
|
||||
SET v_pos = LOCATE(p_split, v_temp);
|
||||
INSERT INTO _split (guid, rowid, col) VALUES (p_uuid, v_cnt, SUBSTRING(v_temp, 1, v_pos - 1));
|
||||
|
||||
SET v_temp = SUBSTRING(v_temp, v_pos + v_length);
|
||||
SET v_cnt = v_cnt + 1;
|
||||
END WHILE;
|
||||
|
||||
-- 添加最後一部分
|
||||
IF LENGTH(v_temp) > 0 THEN
|
||||
INSERT INTO _split(guid, rowid, col) VALUES (p_uuid, v_cnt, v_temp);
|
||||
END IF;
|
||||
|
||||
SELECT JSON_ARRAYAGG(JSON_OBJECT('col', col)) INTO data
|
||||
FROM
|
||||
(
|
||||
SELECT col FROM _split WHERE guid = p_uuid
|
||||
) data;
|
||||
|
||||
-- del temp data
|
||||
delete from _split WHERE guid = p_uuid;
|
||||
|
||||
RETURN data;
|
||||
END //
|
||||
|
||||
DELIMITER ;
|
||||
@@ -0,0 +1,54 @@
|
||||
DELIMITER //
|
||||
|
||||
CREATE OR REPLACE PROCEDURE gp_split(
|
||||
p_uuid VARCHAR(100),
|
||||
p_source TEXT,
|
||||
p_split VARCHAR(2)
|
||||
)
|
||||
/*
|
||||
function : 將傳入的字串, 依 p_split 切割為多筆資料, 傳回暫存 table
|
||||
description:
|
||||
呼叫範例:
|
||||
SET p_uuid = UUID();
|
||||
CALL gp_split(p_uuid, 'R,G,B',',');
|
||||
select col from _split where guid = p_uuid and rowid = 1;
|
||||
DELETE FROM _split WHERE guid = p_uuid;
|
||||
|
||||
必須要有 CREATE TABLE _split( guid varchar(100), rowid INT, col varchar(600) );
|
||||
|
||||
https://www.sqlines.com/sql-server-to-mariadb/returns_table
|
||||
build date : 2023/11/20
|
||||
|
||||
modify history
|
||||
item who date modify docs
|
||||
==== ========== ========== ================================================
|
||||
1 michael 2011/09/08 新增
|
||||
2 Michael 2025/07/11 改寫為MariaDB版本並優化
|
||||
*/
|
||||
BEGIN
|
||||
DECLARE v_pos INT;
|
||||
DECLARE v_cnt INT;
|
||||
DECLARE v_length INT;
|
||||
DECLARE v_temp TEXT;
|
||||
|
||||
SET v_length = LENGTH(p_split);
|
||||
SET v_temp = p_source;
|
||||
SET v_cnt = 1;
|
||||
|
||||
-- 循環處理分割
|
||||
WHILE LOCATE(p_split, v_temp) > 0 DO
|
||||
SET v_pos = LOCATE(p_split, v_temp);
|
||||
INSERT INTO _split (guid, rowid, col) VALUES (p_uuid, v_cnt, SUBSTRING(v_temp, 1, v_pos - 1));
|
||||
|
||||
SET v_temp = SUBSTRING(v_temp, v_pos + v_length);
|
||||
SET v_cnt = v_cnt + 1;
|
||||
END WHILE;
|
||||
|
||||
-- 添加最後一部分
|
||||
IF LENGTH(v_temp) > 0 THEN
|
||||
INSERT INTO _split(guid, rowid, col) VALUES (p_uuid, v_cnt, v_temp);
|
||||
END IF;
|
||||
|
||||
END //
|
||||
|
||||
DELIMITER ;
|
||||
@@ -0,0 +1,345 @@
|
||||
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 ;
|
||||
+117
@@ -0,0 +1,117 @@
|
||||
DELIMITER //
|
||||
|
||||
CREATE OR REPLACE PROCEDURE orm_api_v2(
|
||||
IN p_token VARCHAR(100), -- token(直接傳入)
|
||||
IN p_tablename VARCHAR(200), -- tablename
|
||||
IN p_pk VARCHAR(100), -- primary key(for update delete)
|
||||
IN p_action VARCHAR(20), -- CRUDP(如果是 Read, p_paras 參數內容有特殊寫法)
|
||||
IN p_paras LONGTEXT -- 前端組好的資料內容(應該是 json 格式的內容)
|
||||
)
|
||||
/*
|
||||
Function : 寫一支通用 orm-api 依傳入的參數及設定, 智慧的組出相應的 sql
|
||||
MariaDB 版本
|
||||
|
||||
Description: 本程式是想模仿 orm 的設定, 然後讓前端程式只要傳入參數, 就能執行 orm 的增刪查改的基本功能
|
||||
R(Read) 是讀取單筆資料, p_paras 的參數內容同 CU >> 取消不用
|
||||
P(Page) 是以頁為單位的讀取模式, 一般是 cowork with DataGrid
|
||||
|
||||
呼叫 api 範例如下
|
||||
--新增資料
|
||||
CALL orm_api_v2('B9F290D4-0F57-45B1-A786-F83A63E8BC4D','basarea','areaid','C','{"areaid":"mm", "areacnmae": "Michael"}');
|
||||
CALL orm_api_v2('token_value','basarea','areaid','U','') --修改資料
|
||||
CALL orm_api_v2('token_value','basarea','areaid','D','') --刪除資料
|
||||
|
||||
(pass)CALL orm_api_v2('B9F290D4-0F57-45B1-A786-F83A63E8BC4D','basarea','areaid','P','2^5^areaid^*'); -- 分頁查詢
|
||||
-- 新增 Query 後要分頁顯示(擴充 P 的功能, 多傳 wheresql)
|
||||
SET @para = CONCAT('areaid LIKE ',QUOTE('%A%'));
|
||||
CALL orm_api_v2('token_value','basarea','areaid','P','1^10^fieldid^*^functiontag,tablename,fieldname^zen01');
|
||||
|
||||
-- 多筆資料 update
|
||||
call orm_api_v2('aa54ef9b-7139-11f0-9c5f-d8bbc15c1404','bascustcategory','custcateid','U',
|
||||
'{"rows":[
|
||||
{"custcateid":"03","custcatecname":"大型企業","custcateename":"555","memochar":"","mergetype":"0"},
|
||||
{"custcateid":"04","custcatecname":"政府","custcateename":"666","memochar":"","mergetype":"0"}],
|
||||
"rowsDiff":[
|
||||
{"custcateename":"555"},{"custcateename":"666"}],"indexes":["2","3"],
|
||||
"rowsOrigin":[{"custcateid":"03","custcatecname":"大型企業","custcateename":"","memochar":"","mergetype":"0"},
|
||||
{"custcateid":"04","custcatecname":"政府","custcateename":"","memochar":"","mergetype":"0"}],
|
||||
"unModifiedItems":[
|
||||
{"custcateid":"01","custcatecname":"經銷商","custcateename":"333","memochar":"","mergetype":"0"},
|
||||
{"custcateid":"02","custcatecname":"代理商","custcateename":"444","memochar":"","mergetype":"0"},
|
||||
{"custcateid":"05","custcatecname":"中小企業","custcateename":"","memochar":"","mergetype":"0"},
|
||||
{"custcateid":"06","custcatecname":"學校","custcateename":"","memochar":"","mergetype":"0"},
|
||||
{"custcateid":"07","custcatecname":"竹科","custcateename":"","memochar":"","mergetype":"0"}]
|
||||
,"token":"aa54ef9b-7139-11f0-9c5f-d8bbc15c1404",
|
||||
"_$_tableName":"bascustcategory",
|
||||
"_$_pk":"custcateid","_$_action":"U"}');
|
||||
|
||||
SELECT * FROM orm_json_tmp;
|
||||
delete FROM orm_json_tmp;
|
||||
|
||||
|
||||
Build Date : 2023/12/16 (原始版本)
|
||||
Modify Date: 2023/12/16 (MariaDB 遷移版本)
|
||||
*/
|
||||
BEGIN
|
||||
DECLARE v_userid VARCHAR(100);
|
||||
DECLARE v_uuid VARCHAR(36);
|
||||
DECLARE EXIT HANDLER FOR SQLEXCEPTION
|
||||
BEGIN
|
||||
ROLLBACK;
|
||||
RESIGNAL;
|
||||
END;
|
||||
|
||||
-- 驗證 token
|
||||
SELECT userid INTO v_userid FROM sys_users WHERE token = p_token LIMIT 1;
|
||||
|
||||
IF v_userid IS NULL THEN
|
||||
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'token 錯誤, 請洽系統管理員!!';
|
||||
END IF;
|
||||
|
||||
-- 整理 json 資料
|
||||
SET p_paras = orm_retrive_json_v2(p_paras);
|
||||
|
||||
-- 刪除過期的暫存資料
|
||||
DELETE FROM orm_json_tmp WHERE create_date < DATE_SUB(NOW(), INTERVAL 1 DAY);
|
||||
|
||||
-- 根據操作類型執行不同邏輯
|
||||
IF p_action IN ('C', 'Insert', 'U', 'Update', 'D', 'Delete') THEN
|
||||
-- 開啟事務
|
||||
START TRANSACTION;
|
||||
|
||||
-- 處理 JSON 資料
|
||||
SET p_paras = REPLACE(p_paras, '": "', '":"');
|
||||
SET v_uuid = UUID();
|
||||
|
||||
-- call usp_parsejson(v_uuid,p_paras);
|
||||
CALL parse_JSON(v_uuid, p_paras);
|
||||
|
||||
-- 將傳入的 json 寫入暫存表方便處理
|
||||
INSERT INTO orm_json_tmp (uuid, parent_id, object_id, json_key, json_value, valuetype, create_date)
|
||||
SELECT v_uuid, parent_id, object_id, name, stringvalue, ValueType, NOW()
|
||||
FROM sys_jsondata WHERE UUID = v_uuid and valuetype <> 'OBJECT' and valuetype <> 'ARRAY';
|
||||
-- 測試時先 Mark
|
||||
DELETE FROM sys_jsondata WHERE UUID = v_uuid;
|
||||
|
||||
-- 根據操作類型調用不同副程式
|
||||
IF p_action IN ('C', 'Insert') THEN
|
||||
CALL orm_exec_insert_v2(p_tablename, p_pk, p_action, v_uuid, v_userid);
|
||||
ELSEIF p_action IN ('U', 'Update') THEN
|
||||
CALL orm_exec_update_v2(p_tablename, p_pk, p_action, v_uuid, v_userid);
|
||||
ELSEIF p_action IN ('D', 'Delete') THEN
|
||||
CALL orm_api_kernel_v2(p_tablename, p_pk, p_action, v_uuid, 1);
|
||||
END IF;
|
||||
|
||||
-- 存檔後過帳機制
|
||||
CALL orm_exec_aftersave_v2(p_tablename, p_pk, p_action, v_userid);
|
||||
|
||||
-- 提交事務
|
||||
COMMIT;
|
||||
|
||||
ELSEIF p_action IN ('P', 'Page') THEN
|
||||
-- 核心的 orm 程式, 取得顯示在 DataTable 的分頁資料
|
||||
CALL orm_exec_page_v2(p_tablename, p_pk, v_userid, p_paras);
|
||||
END IF;
|
||||
END //
|
||||
|
||||
DELIMITER ;
|
||||
@@ -0,0 +1,100 @@
|
||||
DELIMITER //
|
||||
|
||||
CREATE OR REPLACE PROCEDURE orm_exec_aftersave_v2(
|
||||
IN p_tablename VARCHAR(100),
|
||||
IN p_pk VARCHAR(100), -- primary key(for update delete)
|
||||
IN p_action VARCHAR(10),
|
||||
IN p_userid VARCHAR(100)
|
||||
)
|
||||
/*
|
||||
功能: orm_api_v2 [存档后处理]的核心程序,智能构建相应SQL
|
||||
描述: 用于保存后执行额外处理逻辑
|
||||
创建日期: 2023/12/16
|
||||
MariaDB转换版本
|
||||
*/
|
||||
BEGIN
|
||||
DECLARE v_sp_name TEXT;
|
||||
DECLARE v_para01 TEXT;
|
||||
DECLARE v_para02 TEXT;
|
||||
DECLARE v_sql_command TEXT;
|
||||
DECLARE v_dest_table TEXT;
|
||||
DECLARE v_dest_field TEXT;
|
||||
DECLARE v_dest_field2 TEXT;
|
||||
DECLARE v_RelationKey TEXT;
|
||||
DECLARE v_filter_user_fieldname TEXT;
|
||||
DECLARE v_max_id INT;
|
||||
|
||||
-- 取得 sys_transaction 信息
|
||||
SELECT
|
||||
sp_name,
|
||||
para01,
|
||||
para02,
|
||||
dest_table,
|
||||
dest_field,
|
||||
dest_field2,
|
||||
RelationKey,
|
||||
filter_user_fieldname
|
||||
INTO
|
||||
v_sp_name,
|
||||
v_para01,
|
||||
v_para02,
|
||||
v_dest_table,
|
||||
v_dest_field,
|
||||
v_dest_field2,
|
||||
v_RelationKey,
|
||||
v_filter_user_fieldname
|
||||
FROM sys_transaction
|
||||
WHERE tablename = p_tablename AND (actiontype = '*' OR LOCATE(p_action, actiontype) > 0)
|
||||
LIMIT 1;
|
||||
|
||||
IF v_sp_name IS NOT NULL AND v_sp_name != '' THEN
|
||||
-- 检查是否为特殊情况
|
||||
IF (v_sp_name != 'sys_transfer_owned2rolemenusecurity') AND (v_sp_name != 'sys_transfer_owned2userroles') THEN
|
||||
-- 如果 pk 是 identity
|
||||
IF v_para01 = 'identity' THEN
|
||||
-- 处理 identity 的情况
|
||||
IF IFNULL(v_filter_user_fieldname, '') = '' THEN
|
||||
SET @sql = CONCAT('SELECT MAX(', p_pk, ') INTO @max_id FROM ', p_tablename);
|
||||
PREPARE stmt FROM @sql;
|
||||
EXECUTE stmt;
|
||||
DEALLOCATE PREPARE stmt;
|
||||
|
||||
SET v_sql_command = CONCAT('UPDATE sys_transaction SET para01 = ? WHERE tablename = ''', p_tablename, '''');
|
||||
PREPARE stmt FROM v_sql_command;
|
||||
EXECUTE stmt USING @max_id;
|
||||
DEALLOCATE PREPARE stmt;
|
||||
ELSE
|
||||
SET @sql = CONCAT('SELECT MAX(', p_pk, ') INTO @max_id FROM ', p_tablename,
|
||||
' WHERE ', v_filter_user_fieldname, ' = ''', p_userid, '''');
|
||||
PREPARE stmt FROM @sql;
|
||||
EXECUTE stmt;
|
||||
DEALLOCATE PREPARE stmt;
|
||||
|
||||
SET v_sql_command = CONCAT('UPDATE sys_transaction SET para01 = ? WHERE tablename = ''', p_tablename, '''');
|
||||
PREPARE stmt FROM v_sql_command;
|
||||
EXECUTE stmt USING @max_id;
|
||||
DEALLOCATE PREPARE stmt;
|
||||
END IF;
|
||||
END IF;
|
||||
|
||||
SET v_sql_command = CONCAT('CALL ', v_sp_name, '( ''', p_tablename, ''' )');
|
||||
ELSE
|
||||
-- 针对特殊情况特别改写 sp 的方案
|
||||
IF IFNULL(v_para01, '') != '' AND IFNULL(v_para02, '') != '' THEN
|
||||
SET v_sql_command = CONCAT('CALL ', v_sp_name, '( ''', v_para01, ''', ''', v_para02, ''' )');
|
||||
ELSEIF IFNULL(v_para01, '') != '' AND IFNULL(v_para02, '') = '' THEN
|
||||
SET v_sql_command = CONCAT('CALL ', v_sp_name, '( ''', v_para01, ''' )');
|
||||
ELSE
|
||||
SET v_sql_command = CONCAT('CALL ', v_sp_name, '()');
|
||||
END IF;
|
||||
END IF;
|
||||
|
||||
-- 执行 SQL
|
||||
SET @dynamic_sql = v_sql_command;
|
||||
PREPARE stmt FROM @dynamic_sql;
|
||||
EXECUTE stmt;
|
||||
DEALLOCATE PREPARE stmt;
|
||||
END IF;
|
||||
END //
|
||||
|
||||
DELIMITER ;
|
||||
@@ -0,0 +1,179 @@
|
||||
DELIMITER //
|
||||
|
||||
CREATE OR REPLACE PROCEDURE orm_exec_insert_v2(
|
||||
IN p_tablename VARCHAR(200), -- tablename
|
||||
IN p_pk VARCHAR(100), -- primary key(for update delete)
|
||||
IN p_action VARCHAR(20), -- CRUDP
|
||||
IN p_uuid VARCHAR(100),
|
||||
IN p_userid VARCHAR(100)
|
||||
)
|
||||
/*
|
||||
Function : orm_api_v2 [新增]的核心程式, 智慧的組出相應的 sql
|
||||
Description: 關於 Master-Detail 的補充說明
|
||||
Build Date : 2023/12/16
|
||||
Modified for MariaDB
|
||||
*/
|
||||
BEGIN
|
||||
DECLARE v_maxcount INT;
|
||||
DECLARE v_currid INT;
|
||||
DECLARE v_is_md SMALLINT;
|
||||
DECLARE v_is_excel SMALLINT;
|
||||
DECLARE v_maxid INT;
|
||||
DECLARE v_excel_id INT;
|
||||
DECLARE v_cnt INT;
|
||||
DECLARE v_cn_field VARCHAR(100);
|
||||
DECLARE v_cd_field VARCHAR(100);
|
||||
DECLARE v_billno VARCHAR(20);
|
||||
DECLARE v_sub_table VARCHAR(100);
|
||||
DECLARE v_sql TEXT;
|
||||
DECLARE v_max_no VARCHAR(20);
|
||||
DECLARE v_maxcnt INT;
|
||||
|
||||
-- step 1: 判斷狀態: 是否 master-detail 多筆資料?
|
||||
SELECT MAX(parent_id) INTO v_maxcount FROM orm_json_tmp WHERE uuid = p_uuid;
|
||||
|
||||
-- @is_md 是使用 input-table template 用的判斷
|
||||
SELECT COUNT(*), IFNULL(MAX(parent_id), 0)
|
||||
INTO v_is_md, v_maxid
|
||||
FROM orm_json_tmp
|
||||
WHERE uuid = p_uuid AND json_key = 'details' AND valuetype = 'array';
|
||||
|
||||
SELECT COUNT(*), IFNULL(MAX(parent_id), 0)
|
||||
INTO v_is_excel, v_excel_id
|
||||
FROM orm_json_tmp
|
||||
WHERE uuid = p_uuid AND json_key = 'excel' AND valuetype = 'array';
|
||||
|
||||
-- step 2: update/insert create_user (僅允許一次一筆資料)
|
||||
SET v_cn_field = 'create_user';
|
||||
SET v_cd_field = 'create_date';
|
||||
|
||||
-- Check if create_user column exists
|
||||
SELECT COUNT(*) INTO v_cnt
|
||||
FROM information_schema.columns
|
||||
WHERE table_name = p_tablename AND column_name = v_cn_field;
|
||||
|
||||
IF v_cnt > 0 THEN
|
||||
SELECT COUNT(*) INTO v_cnt FROM orm_json_tmp WHERE uuid = p_uuid AND json_key = v_cn_field;
|
||||
IF v_cnt = 0 THEN
|
||||
INSERT INTO orm_json_tmp (uuid, parent_id, json_key, json_value, ValueType)
|
||||
VALUES (p_uuid, v_maxcount, v_cn_field, p_userid, 'string');
|
||||
ELSE
|
||||
UPDATE orm_json_tmp SET json_value = p_userid
|
||||
WHERE uuid = p_uuid AND json_key = v_cn_field;
|
||||
END IF;
|
||||
END IF;
|
||||
|
||||
-- Check if create_date column exists
|
||||
SELECT COUNT(*) INTO v_cnt
|
||||
FROM information_schema.columns
|
||||
WHERE table_name = p_tablename AND column_name = v_cd_field;
|
||||
|
||||
IF v_cnt > 0 THEN
|
||||
SELECT COUNT(*) INTO v_cnt FROM orm_json_tmp WHERE uuid = p_uuid AND json_key = v_cd_field;
|
||||
IF v_cnt = 0 THEN
|
||||
INSERT INTO orm_json_tmp (uuid, parent_id, json_key, json_value, ValueType)
|
||||
VALUES (p_uuid, v_maxcount, v_cd_field, DATE_FORMAT(NOW(), '%Y-%m-%d'), 'string');
|
||||
ELSE
|
||||
UPDATE orm_json_tmp SET json_value = DATE_FORMAT(NOW(), '%Y-%m-%d')
|
||||
WHERE uuid = p_uuid AND json_key = v_cd_field;
|
||||
END IF;
|
||||
END IF;
|
||||
|
||||
-- step 3: 針對 m-d 的單號前置處理(針對 billno=自動編碼, 給定新的單號)
|
||||
SELECT COUNT(*) INTO v_cnt
|
||||
FROM orm_json_tmp
|
||||
WHERE uuid = p_uuid AND json_key = 'billno'
|
||||
AND (json_value LIKE '%自動%' OR json_value LIKE '%Auto%');
|
||||
|
||||
IF v_cnt > 0 THEN
|
||||
-- hard-code
|
||||
IF p_pk = '' OR p_tablename LIKE '%_d%' THEN
|
||||
-- master-detail 的 detail insert
|
||||
SET v_max_no = CONCAT(SUBSTRING(p_tablename, 4, 6), SUBSTRING(p_userid, 1, 6));
|
||||
ELSE
|
||||
-- 先取得今天最大號
|
||||
SET @sql = CONCAT('SELECT MAX(billno) INTO @max_billno FROM ', p_tablename,
|
||||
' WHERE DATE(billdate) = CURDATE()');
|
||||
PREPARE stmt FROM @sql;
|
||||
EXECUTE stmt;
|
||||
DEALLOCATE PREPARE stmt;
|
||||
|
||||
-- 計算新單號 (需要實現 sys_next_no 函數)
|
||||
SET v_max_no = sys_next_no(@max_billno);
|
||||
|
||||
-- 紀錄新增單號
|
||||
DELETE FROM sys_new_billno WHERE create_time < DATE_SUB(NOW(), INTERVAL 3 DAY);
|
||||
|
||||
-- 防錯
|
||||
SELECT COUNT(*) INTO v_maxcnt
|
||||
FROM sys_new_billno
|
||||
WHERE tablename = p_tablename AND login_user = p_userid;
|
||||
|
||||
IF v_maxcnt > 0 THEN
|
||||
UPDATE sys_new_billno SET billno = v_max_no
|
||||
WHERE tablename = p_tablename AND login_user = p_userid;
|
||||
ELSE
|
||||
INSERT INTO sys_new_billno VALUES (p_tablename, p_userid, v_max_no, NOW());
|
||||
END IF;
|
||||
END IF;
|
||||
|
||||
UPDATE orm_json_tmp SET json_value = v_max_no
|
||||
WHERE uuid = p_uuid AND json_key = 'billno'
|
||||
AND (json_value LIKE '%自動%' OR json_value LIKE '%Auto%');
|
||||
END IF;
|
||||
|
||||
-- master-detail
|
||||
IF v_is_md > 0 THEN
|
||||
-- 寫入 master 一筆
|
||||
CALL orm_api_kernel_v2(p_tablename, p_pk, p_action, p_uuid, v_maxcount);
|
||||
|
||||
-- 取得表頭的單號
|
||||
SELECT billno INTO v_billno
|
||||
FROM sys_new_billno
|
||||
WHERE tablename = p_tablename AND login_user = p_userid;
|
||||
|
||||
-- 寫入 details 多筆
|
||||
SELECT detail_table INTO v_sub_table
|
||||
FROM zen_function
|
||||
WHERE maintable = p_tablename
|
||||
LIMIT 1;
|
||||
|
||||
IF IFNULL(v_sub_table, '') = '' THEN
|
||||
SET v_sub_table = CONCAT(SUBSTRING(p_tablename, 1, LENGTH(p_tablename)-1), 'd');
|
||||
END IF;
|
||||
|
||||
-- 多筆 detail 資料寫入
|
||||
SET v_currid = 1;
|
||||
WHILE v_currid < v_maxid DO
|
||||
-- 執行核心程式
|
||||
CALL orm_api_kernel_v2(v_sub_table, p_pk, p_action, p_uuid, v_currid);
|
||||
|
||||
-- 取得下一筆資料
|
||||
SET v_currid = v_currid + 1;
|
||||
END WHILE;
|
||||
ELSEIF v_is_excel > 0 THEN
|
||||
-- excel 多筆資料匯入
|
||||
SET v_currid = 1;
|
||||
WHILE v_currid < v_excel_id-1 DO
|
||||
-- 執行核心程式
|
||||
CALL orm_api_kernel_v2(p_tablename, p_pk, p_action, p_uuid, v_currid);
|
||||
|
||||
-- 取得下一筆資料
|
||||
SET v_currid = v_currid + 1;
|
||||
END WHILE;
|
||||
ELSEIF v_maxcount > 1 THEN
|
||||
-- 多筆資料寫入
|
||||
SET v_currid = 1;
|
||||
WHILE v_currid <= v_maxcount DO
|
||||
-- 執行核心程式
|
||||
CALL orm_api_kernel_v2(p_tablename, p_pk, p_action, p_uuid, v_currid);
|
||||
|
||||
-- 取得下一筆資料
|
||||
SET v_currid = v_currid + 1;
|
||||
END WHILE;
|
||||
ELSE
|
||||
CALL orm_api_kernel_v2(p_tablename, p_pk, p_action, p_uuid, 1);
|
||||
END IF;
|
||||
END //
|
||||
|
||||
DELIMITER ;
|
||||
@@ -0,0 +1,181 @@
|
||||
DELIMITER $$
|
||||
|
||||
CREATE OR REPLACE PROCEDURE orm_exec_page_v2 (
|
||||
IN _tablename VARCHAR(200),
|
||||
IN _pk VARCHAR(100),
|
||||
IN _userid VARCHAR(100),
|
||||
IN _paras TEXT
|
||||
)
|
||||
/*
|
||||
Function : orm_api_v2 [分頁查詢]的核心程式, 智慧的組出相應的 sql, 被 orm_api_v2 呼叫使用
|
||||
Description: 要特別注意傳入的參數正確性, 下面是一個正確的 case
|
||||
call orm_api_v2('b013a91a-daf1-11f0-a07a-d8bbc15c1404','basperson','personid','P','1^100^personid^*^^^personcname^林^^');
|
||||
Build Date : 2025/07/11
|
||||
|
||||
Modify History
|
||||
Item Who Date Modify Docs
|
||||
==== ========== ========== ================================================
|
||||
1 Michael 2025/07/11 根據 ms-sql 的版本, 利用 ChatGPT/DeepSeek 等AI, 改寫為 Mariadb 版
|
||||
|
||||
*/
|
||||
BEGIN
|
||||
DECLARE _pageno INT DEFAULT 1;
|
||||
DECLARE _pagerec INT DEFAULT 10;
|
||||
DECLARE _orderby TEXT DEFAULT '';
|
||||
DECLARE _udf_fields TEXT DEFAULT '*';
|
||||
DECLARE _wheresql TEXT DEFAULT '';
|
||||
DECLARE _wheresql_org TEXT DEFAULT '';
|
||||
DECLARE _where_value TEXT DEFAULT '';
|
||||
DECLARE _where_fields TEXT DEFAULT '';
|
||||
DECLARE _where_field TEXT DEFAULT '';
|
||||
DECLARE _where_idvalue TEXT DEFAULT '';
|
||||
DECLARE _menuid TEXT DEFAULT '';
|
||||
DECLARE _jointables TEXT DEFAULT '';
|
||||
DECLARE _joinfields TEXT DEFAULT '';
|
||||
DECLARE _tbl_alias TEXT DEFAULT '';
|
||||
DECLARE _alias TEXT DEFAULT '';
|
||||
DECLARE _startrec INT DEFAULT 0;
|
||||
DECLARE _sql TEXT;
|
||||
DECLARE _sql_cnt TEXT;
|
||||
DECLARE _dtc INT DEFAULT 0;
|
||||
DECLARE _guid VARCHAR(100);
|
||||
--
|
||||
DECLARE v_field VARCHAR(200);
|
||||
DECLARE v_pos INT DEFAULT 1;
|
||||
DECLARE v_count INT;
|
||||
|
||||
-- 錯誤處理
|
||||
/*
|
||||
DECLARE CONTINUE HANDLER FOR SQLEXCEPTION
|
||||
BEGIN
|
||||
SELECT '9999' AS code, '資料庫操作錯誤' AS msg;
|
||||
END;
|
||||
*/
|
||||
|
||||
DECLARE CONTINUE HANDLER FOR SQLEXCEPTION
|
||||
BEGIN
|
||||
GET DIAGNOSTICS CONDITION 1
|
||||
@sqlstate = RETURNED_SQLSTATE,
|
||||
@errno = MYSQL_ERRNO,
|
||||
@text = MESSAGE_TEXT;
|
||||
|
||||
SELECT 1 AS code, CONCAT('Error: ', @errno, ' (', @sqlstate, '): ', @text) AS msg;
|
||||
END;
|
||||
|
||||
SET _guid = UUID();
|
||||
CALL gp_split(_guid, _paras, '^');
|
||||
|
||||
-- 使用 split 暫存表方式處理參數
|
||||
SELECT col INTO _pageno FROM _split WHERE guid = _guid and rowid = 1;
|
||||
SELECT col INTO _pagerec FROM _split WHERE guid = _guid and rowid = 2;
|
||||
SELECT col INTO _orderby FROM _split WHERE guid = _guid and rowid = 3;
|
||||
SELECT col INTO _udf_fields FROM _split WHERE guid = _guid and rowid = 4;
|
||||
SELECT col INTO _wheresql_org FROM _split WHERE guid = _guid and rowid = 5;
|
||||
SELECT col INTO _menuid FROM _split WHERE guid = _guid and rowid = 6;
|
||||
SELECT col INTO _where_fields FROM _split WHERE guid = _guid and rowid = 7;
|
||||
SELECT col INTO _where_value FROM _split WHERE guid = _guid and rowid = 8;
|
||||
SELECT col INTO _where_field FROM _split WHERE guid = _guid and rowid = 9;
|
||||
SELECT col INTO _where_idvalue FROM _split WHERE guid = _guid and rowid = 10;
|
||||
|
||||
DELETE FROM _split WHERE guid = _guid;
|
||||
|
||||
-- 預設排序欄位
|
||||
IF _orderby IS NULL OR _orderby = '' THEN SET _orderby = _pk; END IF;
|
||||
IF _udf_fields IS NULL OR _udf_fields = '' THEN SET _udf_fields = '*'; END IF;
|
||||
|
||||
-- 防錯
|
||||
SET _jointables = '';
|
||||
IF _menuid IS NOT NULL AND _menuid <> '' THEN
|
||||
SELECT joinfields, jointables INTO _joinfields, _jointables
|
||||
FROM sys_joinfields WHERE menuid = _menuid;
|
||||
|
||||
SET _alias = 'ma.';
|
||||
SET _tbl_alias = ' ma ';
|
||||
IF LOCATE('ma.', _orderby) = 0 THEN
|
||||
SET _orderby = CONCAT(_alias, _orderby);
|
||||
END IF;
|
||||
END IF;
|
||||
|
||||
-- 建立 WHERE 條件
|
||||
IF _where_value IS NOT NULL AND _where_value <> '' THEN
|
||||
IF LOCATE(',', _where_fields) > 0 THEN
|
||||
-- SET _wheresql = REPLACE(_where_fields, ',', CONCAT(' LIKE ',"'",'%', _where_value, '%', "'", ' OR ', _alias));
|
||||
-- SET _wheresql = CONCAT(' WHERE (', _alias, _where_fields, ' LIKE ', QUOTE(CONCAT('%', _where_value, '%')), ')');
|
||||
|
||||
-- 改寫, 本段程式目的是要多欄位 like 查詢
|
||||
SET v_count = LENGTH(_where_fields) - LENGTH(REPLACE(_where_fields, ',', '')) + 1;
|
||||
WHILE v_pos <= v_count DO
|
||||
SET v_field = TRIM(
|
||||
SUBSTRING_INDEX(
|
||||
SUBSTRING_INDEX(_where_fields, ',', v_pos),
|
||||
',', -1
|
||||
)
|
||||
);
|
||||
|
||||
SET _wheresql = CONCAT(
|
||||
_wheresql,
|
||||
IF(v_pos > 1, ' OR ', ''),
|
||||
v_field,
|
||||
' LIKE ',
|
||||
QUOTE(CONCAT('%', _where_value, '%'))
|
||||
);
|
||||
|
||||
SET v_pos = v_pos + 1;
|
||||
END WHILE;
|
||||
SET _wheresql = CONCAT(' WHERE (', _wheresql, ')');
|
||||
--
|
||||
ELSE
|
||||
SET _wheresql = CONCAT(' WHERE ', _alias, _where_fields, ' LIKE ', QUOTE(CONCAT('%', _where_value, '%')));
|
||||
END IF;
|
||||
END IF;
|
||||
-- debug
|
||||
-- select concat('where9: ',_wheresql);
|
||||
|
||||
-- 加入網址參數條件
|
||||
IF _where_idvalue IS NOT NULL AND _where_idvalue <> '' THEN
|
||||
IF _wheresql = '' THEN
|
||||
SET _wheresql = CONCAT(' WHERE ', _alias, _where_field, ' = ', QUOTE(_where_idvalue));
|
||||
ELSE
|
||||
SET _wheresql = CONCAT(_wheresql, ' AND ', _alias, _where_field, ' = ', QUOTE(_where_idvalue));
|
||||
END IF;
|
||||
END IF;
|
||||
|
||||
-- 加上前端傳入的原始 WHERE
|
||||
IF _wheresql_org IS NOT NULL AND _wheresql_org <> '' THEN
|
||||
SET _wheresql_org = REPLACE(_wheresql_org, '~', "'");
|
||||
IF _wheresql = '' THEN
|
||||
SET _wheresql = CONCAT(' WHERE ', _wheresql_org);
|
||||
ELSE
|
||||
SET _wheresql = CONCAT(_wheresql, ' AND ', _wheresql_org);
|
||||
END IF;
|
||||
END IF;
|
||||
|
||||
-- 計算 offset
|
||||
SET _startrec = (_pageno - 1) * _pagerec;
|
||||
|
||||
-- 查詢筆數
|
||||
SET _sql_cnt = CONCAT('SELECT COUNT(*) INTO @dtc FROM ', _tablename, _tbl_alias, ' ', _wheresql);
|
||||
PREPARE stmt_cnt FROM _sql_cnt;
|
||||
EXECUTE stmt_cnt;
|
||||
DEALLOCATE PREPARE stmt_cnt;
|
||||
|
||||
SELECT 0 AS code, 'ok' AS msg, @dtc AS recno;
|
||||
-- SELECT 'debug' AS code, _sql_cnt AS msg, @dtc AS recno;
|
||||
|
||||
-- 組合查詢 SQL
|
||||
IF _jointables IS NULL OR _jointables = '' THEN
|
||||
SET _sql = CONCAT('SELECT ', _udf_fields, ' FROM ', _tablename, _tbl_alias, ' ', _wheresql,
|
||||
' ORDER BY ', _orderby, ' LIMIT ', _pagerec, ' OFFSET ', _startrec);
|
||||
ELSE
|
||||
SET _sql = CONCAT('SELECT ', _joinfields, ' FROM ', _tablename, _tbl_alias, _jointables, ' ',
|
||||
_wheresql, ' ORDER BY ', _orderby, ' LIMIT ', _pagerec, ' OFFSET ', _startrec);
|
||||
END IF;
|
||||
|
||||
-- 執行查詢
|
||||
PREPARE stmt FROM _sql;
|
||||
EXECUTE stmt;
|
||||
DEALLOCATE PREPARE stmt;
|
||||
|
||||
END$$
|
||||
|
||||
DELIMITER ;
|
||||
@@ -0,0 +1,99 @@
|
||||
DELIMITER //
|
||||
|
||||
CREATE OR REPLACE PROCEDURE orm_exec_update_v2(
|
||||
IN p_tablename VARCHAR(200), -- 表名
|
||||
IN p_pk VARCHAR(100), -- 主键(用于更新/删除)
|
||||
IN p_action VARCHAR(20), -- CRUDP操作
|
||||
IN p_uuid VARCHAR(100), -- UUID标识
|
||||
IN p_userid VARCHAR(100) -- 用户ID
|
||||
)
|
||||
/*
|
||||
功能: orm_api_v2 [更新]的核心程序,智能构建相应SQL
|
||||
描述: 用于更新操作的ORM核心逻辑
|
||||
创建日期: 2023/12/16
|
||||
MariaDB转换版本
|
||||
*/
|
||||
BEGIN
|
||||
DECLARE v_maxcount, v_rec INT;
|
||||
DECLARE v_currid INT;
|
||||
DECLARE v_cnt INT;
|
||||
DECLARE v_un_field VARCHAR(100);
|
||||
DECLARE v_ud_field VARCHAR(100);
|
||||
|
||||
-- 步骤1: 获取最小parent_id (rows)
|
||||
SELECT MIN(parent_id) INTO v_maxcount
|
||||
FROM orm_json_tmp
|
||||
WHERE uuid = p_uuid; -- AND valuetype in ('ARRAY','object');
|
||||
|
||||
-- 取得欲更新筆數
|
||||
SELECT MAX(object_id) INTO v_rec
|
||||
FROM orm_json_tmp
|
||||
WHERE uuid = p_uuid AND parent_id = v_maxcount;
|
||||
|
||||
-- 步骤2: 更新/插入update_user和update_date字段
|
||||
SET v_un_field = 'update_user';
|
||||
SET v_ud_field = 'update_date';
|
||||
|
||||
-- 检查update_user字段是否存在
|
||||
SELECT COUNT(*) INTO v_cnt
|
||||
FROM information_schema.columns
|
||||
WHERE table_name = p_tablename AND column_name = v_un_field;
|
||||
|
||||
IF v_cnt > 0 THEN
|
||||
SELECT COUNT(*) INTO v_cnt
|
||||
FROM orm_json_tmp
|
||||
WHERE uuid = p_uuid AND json_key = v_un_field;
|
||||
|
||||
IF v_cnt = 0 THEN
|
||||
INSERT INTO orm_json_tmp (uuid, parent_id, json_key, json_value, ValueType)
|
||||
VALUES (p_uuid, v_maxcount, v_un_field, p_userid, 'string');
|
||||
ELSE
|
||||
UPDATE orm_json_tmp
|
||||
SET json_value = p_userid
|
||||
WHERE uuid = p_uuid AND json_key = v_un_field;
|
||||
END IF;
|
||||
END IF;
|
||||
|
||||
-- 检查update_date字段是否存在
|
||||
SELECT COUNT(*) INTO v_cnt
|
||||
FROM information_schema.columns
|
||||
WHERE table_name = p_tablename AND column_name = v_ud_field;
|
||||
|
||||
IF v_cnt > 0 THEN
|
||||
SELECT COUNT(*) INTO v_cnt
|
||||
FROM orm_json_tmp
|
||||
WHERE uuid = p_uuid AND json_key = v_ud_field;
|
||||
|
||||
IF v_cnt = 0 THEN
|
||||
INSERT INTO orm_json_tmp (uuid, parent_id, json_key, json_value, ValueType)
|
||||
VALUES (p_uuid, v_maxcount, v_ud_field, DATE_FORMAT(NOW(), '%Y-%m-%d'), 'string');
|
||||
ELSE
|
||||
UPDATE orm_json_tmp
|
||||
SET json_value = DATE_FORMAT(NOW(), '%Y-%m-%d')
|
||||
WHERE uuid = p_uuid AND json_key = v_ud_field;
|
||||
END IF;
|
||||
END IF;
|
||||
|
||||
-- 日期欄位要格式化處理(待驗證)
|
||||
UPDATE orm_json_tmp
|
||||
SET json_value = DATE_FORMAT(substr(json_value,1,10), '%Y-%m-%d')
|
||||
WHERE uuid = p_uuid AND json_key in (select column_name from information_schema.columns WHERE table_name = p_tablename and substr(data_type,1,4) = 'date')
|
||||
and json_value is not null;
|
||||
|
||||
-- 判断是否有多笔资料
|
||||
IF v_rec > 1 THEN -- v_maxcount
|
||||
SET v_currid = 1;
|
||||
WHILE v_currid <= v_rec DO
|
||||
-- 执行核心程序
|
||||
CALL orm_api_kernel_v2(p_tablename, p_pk, p_action, p_uuid, v_maxcount*1000 + v_currid);
|
||||
|
||||
-- 取得下一笔资料
|
||||
SET v_currid = v_currid + 1;
|
||||
END WHILE;
|
||||
ELSE
|
||||
-- 單筆資料傳入
|
||||
CALL orm_api_kernel_v2(p_tablename, p_pk, p_action, p_uuid, 1);
|
||||
END IF;
|
||||
END //
|
||||
|
||||
DELIMITER ;
|
||||
@@ -0,0 +1,131 @@
|
||||
DELIMITER //
|
||||
|
||||
DROP FUNCTION IF EXISTS orm_page_where_v2;
|
||||
CREATE FUNCTION orm_page_where_v2(
|
||||
tablename VARCHAR(200), -- 表名
|
||||
pk VARCHAR(100), -- 主键(用于更新删除)
|
||||
where_sql TEXT, -- 原始 WHERE 条件
|
||||
userid VARCHAR(100) -- 用户ID
|
||||
)
|
||||
RETURNS TEXT
|
||||
DETERMINISTIC
|
||||
/*
|
||||
Function : orm_api_v2 [分頁查詢] where 條件判斷的核心程式, 智慧的組出相應的 sql, 被 orm_api_page_v2 呼叫使用
|
||||
Description:
|
||||
Build Date : 2024-06-20
|
||||
Modify History:
|
||||
1 Michael 2023/12/16 原始版本
|
||||
2 [优化版] 2024-06-20 MariaDB优化版本
|
||||
*/
|
||||
BEGIN
|
||||
DECLARE wheresql TEXT;
|
||||
DECLARE limit_s_date VARCHAR(100);
|
||||
DECLARE limit_e_date VARCHAR(100);
|
||||
DECLARE limit_field VARCHAR(100);
|
||||
DECLARE limit_field_d VARCHAR(100);
|
||||
DECLARE limit_filter_master TEXT;
|
||||
DECLARE limit_table_d VARCHAR(1000);
|
||||
DECLARE limit_filter_detail TEXT;
|
||||
DECLARE limit_filter_date VARCHAR(200);
|
||||
DECLARE maxcount INT DEFAULT 0;
|
||||
DECLARE new_billno VARCHAR(100);
|
||||
DECLARE comma_pos INT;
|
||||
DECLARE emp1, emp2, emp3 VARCHAR(200);
|
||||
|
||||
-- 初始化 WHERE 子句
|
||||
SET wheresql = IF(where_sql = '', ' WHERE 1=1 ', where_sql);
|
||||
|
||||
-- 获取高级查询限制配置
|
||||
SELECT
|
||||
limit_field, limit_table_d, limit_field_d, limit_s_date, limit_e_date
|
||||
INTO
|
||||
limit_field, limit_table_d, limit_field_d, limit_s_date, limit_e_date
|
||||
FROM sys_menutable
|
||||
WHERE limit_table = tablename
|
||||
AND islimitdata = 'Y'
|
||||
LIMIT 1;
|
||||
|
||||
-- 如果存在限制字段且用户已登录
|
||||
IF limit_field IS NOT NULL AND userid <> '' THEN
|
||||
-- 检查是否有全局权限 (*)
|
||||
SELECT COUNT(*) INTO maxcount
|
||||
FROM basperson_share
|
||||
WHERE personid = userid
|
||||
AND share_personid = '*';
|
||||
|
||||
-- 如果没有全局权限,则添加个人限制条件
|
||||
IF maxcount = 0 THEN
|
||||
-- 初始化过滤条件
|
||||
SET limit_filter_master = '';
|
||||
SET limit_filter_detail = '';
|
||||
SET limit_filter_date = '';
|
||||
|
||||
-- 添加日期范围限制
|
||||
IF limit_s_date <> '' AND limit_e_date <> '' THEN
|
||||
SET limit_filter_date = CONCAT(
|
||||
' AND ', limit_s_date, ' <= CURDATE()',
|
||||
' AND ', limit_e_date, ' >= CURDATE()'
|
||||
);
|
||||
END IF;
|
||||
|
||||
-- 添加明细表限制
|
||||
IF limit_field_d <> '' THEN
|
||||
SET limit_filter_detail = CONCAT(
|
||||
' OR ', pk, ' IN (',
|
||||
'SELECT ', pk, ' FROM ', limit_table_d,
|
||||
' WHERE ', limit_field_d, ' = ', QUOTE(userid),
|
||||
limit_filter_date, ')'
|
||||
);
|
||||
END IF;
|
||||
|
||||
-- 处理多字段限制
|
||||
SET comma_pos = LOCATE(',', limit_field);
|
||||
IF comma_pos > 0 THEN
|
||||
-- 拆分字段列表
|
||||
SET emp1 = SUBSTRING_INDEX(limit_field, ',', 1);
|
||||
SET emp2 = SUBSTRING_INDEX(SUBSTRING_INDEX(limit_field, ',', 2), ',', -1);
|
||||
SET emp3 = IF(LOCATE(',', limit_field, LENGTH(emp1) + LENGTH(emp2) + 3) > 0,
|
||||
SUBSTRING_INDEX(limit_field, ',', -1),
|
||||
NULL);
|
||||
|
||||
-- 构建多字段限制条件
|
||||
SET wheresql = CONCAT(wheresql, ' AND (');
|
||||
SET wheresql = CONCAT(wheresql, emp1, ' IN (SELECT share_personid FROM basperson_share WHERE personid = ', QUOTE(userid), ')');
|
||||
|
||||
IF emp2 <> '' THEN
|
||||
SET wheresql = CONCAT(wheresql, ' OR ', emp2, ' IN (SELECT share_personid FROM basperson_share WHERE personid = ', QUOTE(userid), ')');
|
||||
END IF;
|
||||
|
||||
IF emp3 IS NOT NULL THEN
|
||||
SET wheresql = CONCAT(wheresql, ' OR ', emp3, ' IN (SELECT share_personid FROM basperson_share WHERE personid = ', QUOTE(userid), ')');
|
||||
END IF;
|
||||
|
||||
SET wheresql = CONCAT(wheresql, limit_filter_date, ')', limit_filter_detail);
|
||||
ELSE
|
||||
-- 单字段限制条件
|
||||
SET limit_filter_master = CONCAT(
|
||||
' AND ', limit_field, ' IN (',
|
||||
'SELECT share_personid FROM basperson_share WHERE personid = ', QUOTE(userid), ')',
|
||||
limit_filter_date
|
||||
);
|
||||
SET wheresql = CONCAT(wheresql, limit_filter_master, limit_filter_detail);
|
||||
END IF;
|
||||
END IF;
|
||||
END IF;
|
||||
|
||||
/* 新增记录后只显示刚添加的数据 */
|
||||
SELECT billno INTO new_billno
|
||||
FROM sys_new_billno
|
||||
WHERE tablename = tablename
|
||||
AND login_user = userid
|
||||
AND create_time >= NOW() - INTERVAL 30 SECOND
|
||||
LIMIT 1;
|
||||
|
||||
IF new_billno IS NOT NULL THEN
|
||||
SET wheresql = CONCAT(wheresql, ' AND billno = ', QUOTE(new_billno));
|
||||
END IF;
|
||||
|
||||
RETURN wheresql;
|
||||
END //
|
||||
|
||||
DELIMITER ;
|
||||
@@ -0,0 +1,64 @@
|
||||
DELIMITER //
|
||||
|
||||
CREATE OR REPLACE FUNCTION orm_retrive_json_v2(
|
||||
paras TEXT
|
||||
)
|
||||
RETURNS TEXT
|
||||
DETERMINISTIC
|
||||
/*
|
||||
Function : orm_api_v2 [傳入 json 的資料預處理] 的核心程式, 被 orm_api_v2 呼叫使用
|
||||
Description: 刪除 @para 多餘的內容(amis)
|
||||
如果有特殊元件(如 transfer) 會多 POST 非 orm 所需的資料, 一樣要拿掉
|
||||
picker 如果有設 joinValues:false, 也會多傳一些多餘的資料
|
||||
Build Date : 2024-06-20
|
||||
Modify History:
|
||||
1 Michael 2023/12/16 原始版本
|
||||
2 Michael 2024-06-20 改寫為MariaDB版本並優化
|
||||
*/
|
||||
BEGIN
|
||||
DECLARE result TEXT;
|
||||
DECLARE maxcount INT;
|
||||
DECLARE currid INT;
|
||||
DECLARE trans_data TEXT;
|
||||
DECLARE json_valid BOOLEAN;
|
||||
|
||||
-- 檢查是否為有效JSON,如果是則直接處理,否則按原邏輯處理
|
||||
SET json_valid = JSON_VALID(paras);
|
||||
|
||||
-- 進行一些操作,根據需求修改下面的程式碼
|
||||
SET result = paras;
|
||||
|
||||
-- 處理 config 部分
|
||||
SET maxcount = INSTR(result, '"config":[');
|
||||
IF maxcount > 0 THEN
|
||||
-- 在 config 後可能還有資料
|
||||
SET trans_data = SUBSTRING(result FROM maxcount);
|
||||
SET currid = INSTR(trans_data, '],');
|
||||
SET trans_data = SUBSTRING(trans_data FROM currid + 2);
|
||||
|
||||
SET result = CONCAT(SUBSTRING(result FROM 1 FOR maxcount - 1), ' ', trans_data);
|
||||
END IF;
|
||||
|
||||
-- 處理 token 部分(除非是電子書情況)
|
||||
SET maxcount = INSTR(result, '"token"');
|
||||
IF maxcount > 0 THEN
|
||||
SET result = CONCAT(SUBSTRING(result FROM 1 FOR maxcount - 2), '}');
|
||||
END IF;
|
||||
|
||||
-- 處理換行符
|
||||
IF INSTR(result, '\\n') > 0 THEN
|
||||
SET result = REPLACE(REPLACE(result, '\\r\\n', CHAR(10)), '\\n', CHAR(10));
|
||||
END IF;
|
||||
|
||||
-- 如果是有效JSON,最後再驗證一次
|
||||
IF json_valid THEN
|
||||
IF NOT JSON_VALID(result) THEN
|
||||
-- 如果處理後變無效,返回原始值
|
||||
RETURN paras;
|
||||
END IF;
|
||||
END IF;
|
||||
|
||||
RETURN result;
|
||||
END //
|
||||
|
||||
DELIMITER ;
|
||||
+168
@@ -0,0 +1,168 @@
|
||||
DELIMITER //
|
||||
|
||||
CREATE OR REPLACE PROCEDURE Parse_JSON(
|
||||
IN p_uuid VARCHAR(100),
|
||||
IN json_input JSON
|
||||
)
|
||||
/*
|
||||
call Parse_JSON('uuid-20250803',
|
||||
'{"custcateid":"08","custcatecname":"8888","custcateename":"","memochar":"","mergetype":"","token":"c975931c-6f8d-11f0-9c5f-d8bbc15c1404","_$_tableName":"bascustcategory",
|
||||
"_$_pk":"custcateid",
|
||||
"_$_action":"D"}');
|
||||
|
||||
call Parse_JSON('uuid-20250803',
|
||||
'{"sprintid":"Next-Sprint","sprint_title":"調整現行 PBI 緩衝用的 Sprint(2025)","sprint_startdate":"2025-01-01T00:00:00.000+08:00","sprint_enddate":"2099-12-30T16:00:00.000Z","time_range":"2099",
|
||||
"token":"768f1c89-6fb9-11f0-9c5f-d8bbc15c1404",
|
||||
"_$_tableName":"pms_sprint",
|
||||
"_$_pk":"sprintid",
|
||||
"_$_action":"U"}');
|
||||
|
||||
call Parse_JSON('uuid-20250803_3',
|
||||
'{"rows":[{"custcateid":"09","custcatecname":"9999","custcateename":"9999-memo","memochar":"","mergetype":""}],
|
||||
"rowsDiff":[{"custcateename":"9999-memo"}],"indexes":["7"],
|
||||
"rowsOrigin":
|
||||
[{"custcateid":"09","custcatecname":"9999","custcateename":"","memochar":"","mergetype":""}],
|
||||
"unModifiedItems":[
|
||||
{"custcateid":"01","custcatecname":"經銷商","custcateename":"333","memochar":"","mergetype":"0"},
|
||||
{"custcateid":"02","custcatecname":"代理商","custcateename":"444","memochar":"","mergetype":"0"},
|
||||
{"custcateid":"03","custcatecname":"大型企業","custcateename":"","memochar":"","mergetype":"0"},
|
||||
{"custcateid":"04","custcatecname":"政府","custcateename":"","memochar":"","mergetype":"0"},
|
||||
{"custcateid":"05","custcatecname":"中小企業","custcateename":"","memochar":"","mergetype":"0"},
|
||||
{"custcateid":"06","custcatecname":"學校","custcateename":"","memochar":"","mergetype":"0"},
|
||||
{"custcateid":"07","custcatecname":"竹科","custcateename":"","memochar":"","mergetype":"0"}],
|
||||
"token":"d101363e-700c-11f0-9c5f-d8bbc15c1404","_$_tableName":"bascustcategory","_$_pk":"custcateid","_$_action":"U"}');
|
||||
|
||||
call Parse_JSON('uuid-20250820_1',
|
||||
'{"projectclassid":"soft-dev","proj_boss":"120102",
|
||||
"config":[{"label":"(GM) 總經理室",
|
||||
"children":[
|
||||
{"label":"(120101) 高光","value":"120101"},
|
||||
{"label":"(121108) 沈秋月","value":"121108"},
|
||||
{"label":"(200605) 陳明文","value":"200605"},
|
||||
{"label":"(120102) 王俊傑","value":"120102"},
|
||||
{"label":"(150201) 衛斯理","value":"150201"},
|
||||
{"label":"(190802) 葉子龍","value":"190802"},
|
||||
{"label":"(210301) 高國華","value":"210301"},
|
||||
{"label":"(admin)admin","value":"admin"},
|
||||
{"label":"(160805) 邱雅惠","value":"160805"},
|
||||
{"label":"(170911) 劉強南","value":"170911"},
|
||||
{"label":"(201001) 林志堅","value":"201001"},
|
||||
{"label":"(120912) 陳進德","value":"120912"},
|
||||
{"label":"(170109) 林玉玲","value":"170109"},
|
||||
{"label":"(180210) 秦一明","value":"180210"},
|
||||
{"label":"(191006) 歐陽龍","value":"191006"},
|
||||
{"label":"(201036) 邱郁芳","value":"201036"},
|
||||
{"label":"(demo) 測試用戶","value":"demo"}]
|
||||
}],
|
||||
"projectid":"IT-2025-Chaos","proj_cname":"MariaDB改寫專案","proj_status":"SASD","proj_startdate":"2025-08-01","proj_enddate":"2025-09-30",
|
||||
"proj_year":"2025","token":"a85afca2-7dc5-11f0-9c5f-d8bbc15c1404",
|
||||
"_$_tableName":"pmsproject",
|
||||
"_$_pk":"projectid",
|
||||
"_$_action":"C"}');
|
||||
|
||||
|
||||
*/
|
||||
BEGIN
|
||||
DECLARE i INT DEFAULT 0;
|
||||
DECLARE total_keys INT;
|
||||
DECLARE key_name VARCHAR(255);
|
||||
DECLARE val JSON;
|
||||
|
||||
DECLARE sub_key_name VARCHAR(255);
|
||||
DECLARE sub_val JSON;
|
||||
DECLARE sub_total_keys INT;
|
||||
DECLARE j INT;
|
||||
DECLARE x INT;
|
||||
DECLARE y INT;
|
||||
DECLARE arr_count,arr_idx INT;
|
||||
DECLARE arr_obj JSON;
|
||||
|
||||
-- 取第一層 keys 數量
|
||||
SET total_keys = JSON_LENGTH(JSON_KEYS(json_input));
|
||||
SET x = 1;
|
||||
SET y = 1;
|
||||
|
||||
WHILE i < total_keys DO
|
||||
SET key_name = JSON_UNQUOTE(JSON_EXTRACT(JSON_KEYS(json_input), CONCAT('$[', i, ']')));
|
||||
SET val = JSON_EXTRACT(json_input, CONCAT('$.', key_name));
|
||||
|
||||
-- 插入第一層
|
||||
-- INSERT INTO tmp_json_parse_result (level, parent_key, key_name, value)
|
||||
INSERT INTO sys_jsondata (UUID, `NAME`, SequenceNo, parent_ID, StringValue, ValueType)
|
||||
VALUES (p_uuid, key_name, x, NULL, JSON_UNQUOTE(val), JSON_TYPE(val));
|
||||
|
||||
SET y = x;
|
||||
SET x = x + 1;
|
||||
|
||||
-- 第二層處理:若 value 是 object 或 array,解析其 key-value (當前版本只處理 2層, 多的暫時不管)
|
||||
IF JSON_TYPE(val) IN ('OBJECT', 'ARRAY') THEN
|
||||
-- 先處理 ARRAY 可能有多筆資料
|
||||
IF JSON_TYPE(val) = 'ARRAY' THEN
|
||||
SET arr_count = JSON_LENGTH(val);
|
||||
SET arr_idx = 0;
|
||||
|
||||
WHILE arr_idx < arr_count DO
|
||||
-- 取出陣列中的單一物件
|
||||
SET arr_obj = JSON_EXTRACT(val, CONCAT('$[', arr_idx, ']'));
|
||||
SET j = 0;
|
||||
SET sub_total_keys = JSON_LENGTH(JSON_KEYS(arr_obj));
|
||||
|
||||
WHILE j < sub_total_keys DO
|
||||
SET sub_key_name = JSON_UNQUOTE(JSON_EXTRACT(JSON_KEYS(arr_obj), CONCAT('$[', j, ']')));
|
||||
SET sub_val = JSON_EXTRACT(arr_obj, CONCAT('$.', sub_key_name));
|
||||
|
||||
INSERT INTO sys_jsondata (UUID, `NAME`, SequenceNo, parent_ID, Object_ID, StringValue, ValueType)
|
||||
VALUES (p_uuid, sub_key_name, x, y, arr_idx+1, JSON_UNQUOTE(sub_val), JSON_TYPE(sub_val));
|
||||
|
||||
SET j = j + 1;
|
||||
SET x = x + 1;
|
||||
END WHILE;
|
||||
|
||||
SET arr_idx = arr_idx + 1;
|
||||
END WHILE;
|
||||
ELSE
|
||||
-- 處理單一 OBJECT
|
||||
SET j = 0;
|
||||
SET sub_total_keys = JSON_LENGTH(JSON_KEYS(val));
|
||||
|
||||
WHILE j < sub_total_keys DO
|
||||
SET sub_key_name = JSON_UNQUOTE(JSON_EXTRACT(JSON_KEYS(val), CONCAT('$[', j, ']')));
|
||||
SET sub_val = JSON_EXTRACT(val, CONCAT('$.', sub_key_name));
|
||||
|
||||
INSERT INTO sys_jsondata (UUID, `NAME`, SequenceNo, parent_ID, StringValue, ValueType)
|
||||
VALUES (p_uuid, sub_key_name, x, y, JSON_UNQUOTE(sub_val), JSON_TYPE(sub_val));
|
||||
|
||||
SET j = j + 1;
|
||||
SET x = x + 1;
|
||||
END WHILE;
|
||||
END IF;
|
||||
END IF;
|
||||
|
||||
/*
|
||||
-- 第二層處理:若 value 是 object,解析其 key-value
|
||||
IF JSON_TYPE(val) in ('OBJECT','ARRAY') THEN
|
||||
-- 先解決 rows Grid Edit 多筆資料, 後續應該還有其他狀況要一一排除
|
||||
SET j = 0;
|
||||
-- IF SELECT TRIM(BOTH '[]' FROM '[example]') AS result;
|
||||
SET sub_total_keys = JSON_LENGTH(JSON_KEYS(val));
|
||||
|
||||
WHILE j < sub_total_keys DO
|
||||
SET sub_key_name = JSON_UNQUOTE(JSON_EXTRACT(JSON_KEYS(val), CONCAT('$[', j, ']')));
|
||||
SET sub_val = JSON_EXTRACT(val, CONCAT('$.', sub_key_name));
|
||||
|
||||
-- INSERT INTO tmp_json_parse_result (level, parent_key, key_name, value)
|
||||
INSERT INTO sys_jsondata (UUID, `NAME`, SequenceNo, parent_ID, StringValue, ValueType)
|
||||
VALUES (p_uuid, sub_key_name, x, y , JSON_UNQUOTE(sub_val), JSON_TYPE(val));
|
||||
|
||||
SET j = j + 1;
|
||||
SET x = x + 1;
|
||||
END WHILE;
|
||||
END IF;
|
||||
*/
|
||||
|
||||
SET i = i + 1;
|
||||
END WHILE;
|
||||
|
||||
END //
|
||||
|
||||
DELIMITER ;
|
||||
@@ -0,0 +1,70 @@
|
||||
DELIMITER $$
|
||||
|
||||
CREATE OR REPLACE PROCEDURE usp_parsejson (
|
||||
IN _uuid VARCHAR(100),
|
||||
IN _json TEXT
|
||||
)
|
||||
/*
|
||||
CALL usp_parsejson('1234', '{ "id":"abc", "nmae": "Michael"}');
|
||||
SELECT * from _jsondata WHERE guid = '1234';
|
||||
|
||||
DELETE FROM _jsondata WHERE guid = '1234';
|
||||
*/
|
||||
BEGIN
|
||||
DECLARE _json_clean TEXT;
|
||||
DECLARE _pair TEXT;
|
||||
DECLARE _key VARCHAR(255);
|
||||
DECLARE _value TEXT;
|
||||
DECLARE _valuetype VARCHAR(20);
|
||||
DECLARE _pos INT DEFAULT 1;
|
||||
DECLARE _len INT;
|
||||
DECLARE _curr INT DEFAULT 1;
|
||||
DECLARE _next INT;
|
||||
DECLARE _cnt INT DEFAULT 1;
|
||||
|
||||
-- 建立暫存表
|
||||
CREATE TEMPORARY TABLE IF NOT EXISTS _jsondata (
|
||||
guid VARCHAR(100),
|
||||
rowid INT,
|
||||
fieldname VARCHAR(255),
|
||||
contents TEXT,
|
||||
fieldtype VARCHAR(20)
|
||||
);
|
||||
|
||||
-- 清除左右大括號與空白
|
||||
SET _json_clean = REPLACE(_json,'{','');
|
||||
SET _json_clean = REPLACE(_json_clean,'}','');
|
||||
|
||||
-- 計算逗號數(也就是 key:value 數)
|
||||
SET _len = LENGTH(_json_clean) - LENGTH(REPLACE(_json_clean, ',', '')) + 1;
|
||||
|
||||
WHILE _cnt <= _len DO
|
||||
-- 取出第 cnt 個 key:value 配對
|
||||
SET _pair = SUBSTRING_INDEX(SUBSTRING_INDEX(_json_clean, ',', _cnt), ',', -1);
|
||||
|
||||
-- 取出 key
|
||||
SET _key = SUBSTRING_INDEX(_pair, ':', 1);
|
||||
SET _key = REPLACE(TRIM(_key),'"','');
|
||||
|
||||
-- 取出 value
|
||||
SET _value = SUBSTRING_INDEX(_pair, ':', -1);
|
||||
SET _value = TRIM(_value);
|
||||
|
||||
-- 判斷型別
|
||||
IF LEFT(_value, 1) = '"' AND RIGHT(_value, 1) = '"' THEN
|
||||
SET _valuetype = 'string';
|
||||
SET _value = REPLACE(_value,'"','');
|
||||
ELSE
|
||||
SET _valuetype = 'number';
|
||||
END IF;
|
||||
|
||||
-- 寫入結果
|
||||
INSERT INTO _jsondata (guid, rowid, fieldname, contents, fieldtype)
|
||||
VALUES (_uuid, _cnt, _key, _value, _valuetype);
|
||||
|
||||
-- 下一筆
|
||||
SET _cnt = _cnt + 1;
|
||||
END WHILE;
|
||||
END$$
|
||||
|
||||
DELIMITER ;
|
||||
Reference in New Issue
Block a user