跳轉到

指令碼開發 / 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