跳转至

脚本开发 / SQL 构造 DFF.SQL

使用 DFF.SQL(...) 可以方便地生成动态 SQL 语句,避免手工拼接 SQL 导致 SQL 注入问题。

参数 类型 必须 / 默认值 说明
sql str 必须 SQL 语句,可包含参数占位符。
? 表示需要转义的参数;
?? 表示不需要转义的参数
sql_params list None SQL 参数

绝大多数 SQL 类连接器已内置此功能

绝大多数通过 DFF.CONN(...) 创建的,SQL 类的连接器操作对象都已经内置了此功能,可以直接使用

直接使用 conn.query(sql, sql_params) 即可,不用单独调用此方法。

此方法主要用于方便 DEBUG SQL 语句,通过 print(...) 观察实际执行的 SQL 语句

示例
1
2
3
sql = 'SELECT * FROM ?? WHERE id = ?'
sql_params = [ 'users', 'user-001' ]
print(DFF.SQL(sql, sql_params))
示例输出
1
SELECT * FROM users WHERE id = 'user-001'

参数展开

为了方便动态 SQL 的生成,本方法会根据 sql_params 中的值类型,进行参数展开。

允许用户将不确定数量的内容打包作为一个参数传入,由系统自动展开。

使用时,针对某个参数占位符填入数组或数组即可,如:

数组展开式

参数为数组的,会自动展开为如下形式:

数组参数展开
1
p1, p2, p3, ...
示例 1
1
2
3
4
5
6
7
8
9
sql = 'SELECT * FROM ?? WHERE status IN (?)'
sql_params = [
    # 对应第一个参数占位符 ??
    'demo',

    # 对应第二个参数占位符 ?,参数值为数组,自动展开为多个值
    [ 'error', 'warning' ]
]
result = db.query(sql, sql_params=sql_params)
实际执行的 SQL
1
SELECT * FROM demo WHERE status IN ('error', 'warning')

参数为数组,且其元素也为数组的,会自动进行二层展开为如下形式:

二维数组参数展开
1
(p1_1, p1_2, p1_3, ...), (p2_1, p2_2, p2_3, ...), (p3_1, p3_2, p3_3, ...), ...`.
示例 2
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
sql = 'INSERT INTO ?? (id, name, value) VALUES ?'
sql_params = [
    # 对应第一个参数占位符 ??
    'demo',

    # 对应第二个参数占位符 ?,参数值为数组,自动展开为多个值(即多条数据库记录)
    [
        # 参数值数组内元素依然为数组,自动继续展开(即每条数据库记录的多个字段)
        [ 1, 'zhang3', 100 ],
        [ 1, 'li4', 200 ],
    ]
]
effected_rows = db.non_query(sql, sql_params=sql_params)
实际执行的 SQL
1
INSERT INTO demo (id, name, value) VALUES (1, 'zhang3', 100), (1, 'li4', 200)

字典展开式

示例
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
sql = 'INSERT INTO ?? SET ?'
sql_params = [
    # 对应第一个参数占位符 ??
    'demo',

    # 对应第二个参数占位符 ?,字典自动展开为多个赋值语法
    {
      'id'   : 1,
      'name' : 'zhang3',
      'value': 100,
    }
]
effected_rows = db.non_query(sql, sql_params=sql_params)
实际执行的 SQL
1
INSERT INTO demo SET id = 1, name = 'zhang3', value = 100