考虑简单的命令:
INSERT INTO TABLE table_name (fldX) VALUES (valueX)
UPDATE table_name SET fldX = valueX WHERE table_id = ? AND version_id = ?
更多的时候,我们只插入或更新一些表字段,但在 INSERT/UPDATE 上的所有 CRUD 存储过程示例都包含所有可更新的表字段,并且要使用这个 SP,我们需要填写所有这些参数。
在以下情况下会出现此类 SP 的问题:
- 用户最初只想设置字段的子集 (1+),因此他不能使用插入所有字段的 SP
- 用户并不总是知道所有表字段,因此他不能使用 SP更新所有字段。我不想为可能的字段子集编写相同的 SP。
- 用户不应访问更新所有字段的 SP。
- 用户/用户操作并不总是有权更改所有表字段的值。
- 用户只想更新 1 个字段,但需要使用 CALL {table}_update( ... ) 中的所有表字段
在此示例中,用户可以访问记录的“主键”和“版本”(时间戳/数字)列.
可能的解决方案:
- 解决方案 0:继续使用 INSERT/UPDATE 语句
这种方法的优点:
- 它有效
这种方法的缺点:
- 允许用户直接访问表时的安全问题-删除记录
时无法保存用户的数据
- 解决方案 1:发送部分 DML 语句作为参数,SP 将使用它来创建动态 SQL 语句:
CALL table_update(p_id AS INT, p_changes CHAR(1000))
-- Parameters: p_changes = "fld1 = 1, fld2 = '01.01.2019', fld3 = 'abc'"
st1 = 'UPDATE table SET' || p_changes || 'WHERE id = p_id';
EXECUTE st1;
这种方法的缺点:
- 可能的 SQL 注入
- 动态 SQL 上没有可用的缓存和优化
- 无法检查输入字符串等...
- 解决方案2:发送未使用的值 AS NULL并添加带有值的列列表的字符串参数以使用实际参数(即使它为空)
PROCEDURE table_update(upd_fields VARCHAR(1000), fld1 CHR(30), fld2 CHAR(30))
-- If we want to update only fld1 we should execute
CALL table_update('fld1', value1, NULL)
这种方法的缺点:
- 如果 SP 将来会更改参数的顺序,则该系统将中断
- 语句将再次动态准备,因此没有缓存。
- 创建“ins_fields”或“upd_fields”参数的复杂性
- 解决方案 3:使用包含所有更改的 XML 字符串发送更新。
PROCEDURE table_update(record_updates XML)
-- or even
PROCEDURE table_edit(table_changes XML) -- all INSERT/UPDATE/DELETE statemens together
这种方法的优点:
- 可用于 1 个 SP 调用中的 INSERTs/UPDATEs/DELETEs
- 只有 1 个参数来列出所有更新的字段。
这种方法的缺点:
- 传输更多数据(因为 XML)
- 由于需要在服务器上解析 XML 而降低性能
- 增加了存储过程的复杂性。
- 增加客户端代码复杂性(创建 XML 字符串)
那么我缺少什么解决方案?哪些被认为是主流/最佳/普遍?
这个问题在现代 ORM 中是如何解决的?他们使用第一种、第二种或第三种方法吗?
我个人想使用第三种解决方案(带有 XML 参数),但我需要示例:
1)此类 XML 参数的模式示例。
2)解析XML参数的存储过程示例
当前使用的环境:使用 Visual FoxPro 应用程序中的 SQL 直通 (ODBC) 执行直接 INSERT/UPDATE/DELETE 语句。DBMS:DB2 for z/OS v10。