|-----------------------------------------------------------------------------------------------------------------------------------------------|
| 适用人群 :编程小白、初学Flask接口、对接Oracle数据库、医保/HIS后台开发 笔记特点 :全程人话、无废话、可直接复制运行、生产可用、避坑全覆盖 学习闭环 :前端传参 → 后端接收解析 → 安全查库 → 组装JSON返回 → 批量入库 → 生产避坑 |
一、小白必懂核心总览(先看这个,全局通透)
所有 Flask+Oracle 接口,永远只有一套固定流程:
- 接收入参 :request.args.get() / request.get_json(),必须带默认值防报错
- 安全SQL :SQL只用占位符 :xxx,绝不字符串拼接
- 参数绑定:参数和SQL分开传,防SQL注入
- 字典游标:开启 rowfactory,告别下标取值,零出错
- 安全读取 :单条用fetchone,批量小数据fetchall,大数据必须fetchmany分批
- 资源关闭:必须close,防止连接泄露
- 统一返回:jsonify 返回标准JSON
全篇所有代码,全部遵循以上流程,记住就全会了。
二、两种返回JSON方式(小白必分清)
1、jsonify()【接口专用】
后端返回数据给前端/第三方,所有接口最终返回只用它。
- 自动带 Content-Type:application/json
- 中文不乱码
- 返回标准响应对象
2、json.dumps()【工具专用】
只用来打日志、数据预处理,不能直接当接口返回。
三、Oracle 查询两大模式(彻底解决取值混乱)
1、默认元组模式(不推荐)
返回:(值1,值2,值3),只能用 row0、row1 下标取值。
坑:记错字段顺序直接取错数据,小白极易翻车。
2、字典游标模式(全程推荐、万能)
查询结果自动变成字典,直接字段名取值,永不乱。
小白万能固定代码,所有查询无脑复制放在cursor后
|--------------------------------------------------------------------------------------------------------------------------|
| python # 小白神器:自动把【元组】转【字典】,永久告别下标取值 cur.rowfactory = lambda *args: dict(zip(d\[0 for d in cur.description], args)) |
人话解释:自动拿本次SQL的字段名 + 自动匹配每一行数据,帮你组装好字典。
四、入参接收两种场景(全覆盖)
1、GET接口URL传参
用于查询列表、查询详情
|-----------------------------------------------------------------------------------------------------------------|
| python # 语法:get(参数名, 默认值) jshid = request.args.get("jshid", "") max_rows = request.args.get("max_rows", "1000") |
2、POST接口JSON传参
用于新增、修改、批量上报
|---------------------------------------------------------------------------------------------------------------------------------------|
| python # silent=True 报错容错,非法JSON不崩接口 req_json = request.get_json(silent=True) # 所有取值必须带默认值,杜绝KeyError name = req_json.get("name", "") |
五、小白保命核心:入参绑定三步法(最重要)
所有动态查询,100%统一这套写法,杜绝所有SQL注入、特殊字符报错
标准三步固定流程
- 第一步:接收参数 + 默认值兜底
- 第二步:SQL写占位符 :xxx,不拼接任何变量
- 第三步:execute(sql, 参数列表) 顺序绑定
错误写法(生产绝对禁止)
|---------------------------------------------------------------------------------|
| python # 危险!字符串拼接 = 漏洞 + 报错 sql = f"select * from table where jshid = {jshid}" |
正确标准写法
|------------------------------------------------------------------------------------------------------------------------------------------------------------|
| python # 1. 取值兜底 jshid = request.args.get("jshid", "") # 2. 占位符SQL sql = "select * from table where jshid=:jshid" # 3. 参数绑定执行 cur.execute(sql, jshid) |
小白口诀:取值带默认、SQL留空位、参数单独传
六、三种查询方式彻底分清(生产必规范)
1、fetchone() → 单条详情专用
只查1行,适合详情、单条校验,安全无坑。
2、fetchall() → 仅小数据用
一次性读取全部数据,大表绝对禁止。
隐患:无行数上限,但会塞满内存导致OOM崩溃、接口超时。
3、fetchmany() → 大数据唯一安全写法
分批读取,内存可控,生产明细、流水、日志表统一用这个。
|-----------------------------------------------------------------------------------------------------------------------------------------------|
| python # 标准安全分批读取 data_list = \[\] batch_size = 500 while True: batch = cur.fetchmany(batch_size) if not batch: break data_list.extend(batch) |
七、四大核心业务完整Demo(全覆盖)
1、单条详情查询(GET + 入参绑定 + 字典取值)
|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| python @app.route("/api/get_one", methods="GET") def get_one(): conn = oracledb.connect("user/pwd@dsn") cur = conn.cursor() cur.rowfactory = lambda *args: dict(zip(d\[0 for d in cur.description], args)) # 1.入参接收兜底 jshid = request.args.get("jshid", "B20260820001") # 2.占位符SQL sql = "select jshid,billno,patientname,amount from t_his_drug_upload where jshid=:p_jshid" # 3.参数绑定执行 cur.execute(sql, jshid) row = cur.fetchone() if not row: cur.close() conn.close() return jsonify({"code":404,"msg":"未找到数据"}) cur.close() conn.close() return jsonify({"code":0,"msg":"成功","data":row}) |
2、大数据列表查询(安全分批版)
|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| python @app.route("/api/list_demo", methods="GET") def list_demo(): conn = oracledb.connect("user/pwd@dsn") cur = conn.cursor() cur.rowfactory = lambda *args: dict(zip(d\[0 for d in cur.description], args)) max_rows = request.args.get("max_rows", "1000") sql = "select jshid,drugcode,drugname,amount from t_his_drug_upload where rownum<=:page_size" cur.execute(sql, max_rows) # 分批读取,防内存溢出 data_list = \[\] batch_size = 500 while True: batch = cur.fetchmany(batch_size) if not batch: break data_list.extend(batch) cur.close() conn.close() return jsonify({"code":0,"msg":"ok","total":len(data_list),"dataList":data_list}) |
3、嵌套JSON返回(主表+明细,医保常用)
Python dict嵌套list → 自动转为JSON对象+数组
4、POST JSON解析 + 批量入库(executemany)
接收前端批量数组,事务控制,要么全成功、要么全回滚,杜绝脏数据。
八、小白通用万能模板(可直接上线)
所有GET查询接口,复制改SQL、改参数即可用,标准、安全、零报错
|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| python from flask import Flask, jsonify, request import oracledb app = Flask(name) @app.route("/api/common_query", methods="GET") def common_query(): conn = oracledb.connect("user/pwd@dsn") cur = conn.cursor() cur.rowfactory = lambda *args: dict(zip(d\[0 for d in cur.description], args)) # 1.入参接收+兜底 limit_num = request.args.get("limit_num", "1000") jshid = request.args.get("jshid", "") # 2.占位符SQL sql = """select jshid,billno,patientname,amount from t_his_drug_upload where jshid=:jshid and rownum<=:limit_num""" # 3.参数绑定执行 cur.execute(sql, jshid, limit_num) # 4.安全分批读取 data_list = \[\] batch_size = 500 while True: batch = cur.fetchmany(batch_size) if not batch: break data_list.extend(batch) # 5.释放资源 cur.close() conn.close() return jsonify({ "code": 0, "msg": "查询成功", "total": len(data_list), "dataList": data_list }) if name == "main": app.run(debug=True, port=8080) |
九、小白终极避坑清单(90%新手报错全在这)
- 禁止SQL字符串拼接,一律占位符+参数绑定
- 禁止裸用fetchall查大表,必OOM崩溃
- 禁止字典硬取值 dict"key",全部用.get()兜底
- 禁止下标记错:row下标是【列序号】,不是行号
- 必须关闭连接游标,防止连接泄露、数据库卡死
- 批量操作必须事务:成功commit、异常rollback
- 接口返回只用jsonify,不用dumps
- 所有入参必须默认值,防止用户不传参崩服务
十、极简速查口诀(小白永久背诵)
入参带默认,SQL留空位,参数单独传
查询转字典,批量用分批,用完必关闭
不拼字符串,不裸fetchall,不硬取值