PostgreSQL插入数据报错:目标列数与表达式数不匹配求助
解决PostgreSQL插入数据时的"INSERT contains more target columns than expressions"错误
问题根源分析
- JSON字段解析错误:你用
request.json.get('clientId,drinkId,status,time')的方式完全错误,get()方法只能接收单个键名,这样写会返回None,导致插入的表达式数量和目标列数不匹配。 - 全局数组导致重复插入:全局的
orders数组会在每次请求时追加数据,多次调用接口后,VALUES子句里会包含多条记录,但你的SQL只对应一组列,必然报错。 - 表结构语法错误:创建表时字段类型和名称顺序写反了,正确的写法是
字段名 类型,而非类型 字段名。 - 时间格式不兼容:传入的
20232410 10:15:45不符合PostgreSQL timestamp类型的默认格式,需要转换为YYYY-MM-DD HH:MI:SS格式。 - 数据库资源泄漏:每次请求创建新连接但未关闭,会导致连接耗尽。
修正后的完整代码
from psycopg2 import sql import psycopg2 from flask import Flask, request, jsonify app = Flask(__name__) @app.route('/client/order', methods=["POST", "OPTIONS"]) def save_order(): if request.method == "OPTIONS": return jsonify({}) # 解析JSON中的各个字段 client_id = request.json.get('clientId') drink_id = request.json.get('drinkId') status = request.json.get('status') time_str = request.json.get('time') # 转换时间格式:将20232410调整为2023-10-24(注意原时间的日/月顺序,需根据实际业务调整) formatted_time = f"{time_str[:4]}-{time_str[6:8]}-{time_str[4:6]} {time_str[9:]}" conn = None cursor = None try: conn = psycopg2.connect( user='postgres', password='*********', database='pyDB', host='127.0.0.1', port=5432 ) cursor = conn.cursor() # 参数化查询避免SQL注入,同时匹配列数 insert_query = sql.SQL(''' INSERT INTO orders (client_id, drink_id, status, order_time) VALUES (%s, %s, %s, %s) ''') # 将status字符串转换为布尔值 status_bool = status.lower() == 'true' cursor.execute(insert_query, (client_id, drink_id, status_bool, formatted_time)) conn.commit() return jsonify({"order": "saved"}) except Exception as e: if conn: conn.rollback() return jsonify({"error": str(e)}), 500 finally: # 确保关闭游标和连接,避免资源泄漏 if cursor: cursor.close() if conn: conn.close() if __name__ == '__main__': app.run(debug=True)
关键修改说明
- 正确解析JSON字段:分别获取每个键对应的值,确保插入的字段数量和表列数完全匹配。
- 移除全局数组:每次请求只处理当前的单条订单数据,避免重复插入历史数据。
- 修复表结构:重新创建符合PostgreSQL语法的orders表:
CREATE TABLE orders( drink_id INT NOT NULL, client_id INT NOT NULL, status BOOLEAN NOT NULL, order_time TIMESTAMP WITHOUT TIME ZONE );
- 时间格式转换:将传入的时间字符串转换为PostgreSQL兼容的格式(若原时间的日/月顺序有误,需根据实际业务逻辑调整)。
- 参数化查询:使用
%s占位符代替字符串拼接,既避免SQL注入风险,又简化语法。 - 资源清理:通过try-finally确保数据库连接和游标被正确关闭,防止连接资源耗尽。
- OPTIONS请求处理:单独返回空响应,符合跨域请求的预处理要求。
内容的提问来源于stack exchange,提问作者N Studio
相关产品推荐
相关产品推荐

