Summary on 20080701: insert value for identity column in sql

本文详细介绍了在SQL Server中如何为标识列手动赋值的方法。默认情况下,SQL Server不允许用户直接为标识列赋值,而是由系统自动分配。若要进行手动赋值,需要启用identity_insert选项,并指定列名进行插入操作。

In MSSQLServer, by default, user can‘t insert/assign/update value for identity column; SQLServer will do this for user automatically, so there is one problem caused that: what will do if  wants to assign value for identity column? for one table like: teacher(teacher_id, teacher_name, teacher_age), and teacher_id is identity the insert should be like: insert into teacher values('kalash',12), that's correct format, if insert is like: insert into teacher values(1,'kalash',12), there will be error when execute the statement

and for the case that user want to insert value for identity column, user can turn on the identity_insert for implicitly insert, the code is as followed:

set identity_insert [table_name] on

insert into teacher(teacher_id, teacher_name)
values(1,'klasch');

set identity_insert [table_name] off

for the above code, please note that: 1. for the insert, the column name should be listed out, especially the 'teacher_id' 2. any time, the 'identity_insert' can be set to 'on' for only one table, if the 'identity_insert' is set to 'on' and set that for another table, there will be error, so for tip3 3. it's suggested that every time after set the identity_insert to be 'on', set it back to 'off' after the operation

CREATE OR REPLACE PROCEDURE UPDATE_hsy( p_table_name VARCHAR2, p_column_name VARCHAR2 ) AS sysdb_user VARCHAR2(32) := 'T100_GSUPR1_CPTLSYS_00'; tenant_id VARCHAR2(32) := '100'; i NUMBER := 1; str VARCHAR2(255); res VARCHAR2(255); ele VARCHAR2(50); ele_copy VARCHAR2(50); BEGIN SELECT VALUE INTO str FROM T100_GSUPR1_CPTLSYS_00.CPS_SYS_PARAM_INST_SITE WHERE PARAM_CODE = 'RECONCILIATION_AUTO_SUMMARY_REPORT_NOTIFICATION_OPERATOR' AND VALUE LIKE '203%'; IF str IS NULL THEN RETURN; END IF; UPDATE T100_GSUPR1_CPTLSYS_00.CPS_SYS_PARAM_INST_SITE SET VALUE = '' WHERE PARAM_CODE = 'RECONCILIATION_AUTO_SUMMARY_REPORT_NOTIFICATION_OPERATOR'; WHILE i <= 1 + (LENGTH(str) - LENGTH(REPLACE(str, ',', ''))) LOOP ele := SUBSTRING_INDEX(SUBSTRING_INDEX(str, ',', i), ',', -1); EXECUTE IMMEDIATE ' insert into T100_GSUPR1_CPTLSYS_00.TMP_CONDITION_NUM values (' || ele || ') '; EXECUTE IMMEDIATE ' ' || ele_copy || ' := SELECT CASE WHEN SUBSTRING(' || ele || ', -9, 1) <> ''2'' THEN CONCAT(' || tenant_id || ', ''0000'', 2000, 8, SUBSTRING(' || ele || ', -6)) WHEN SUBSTRING(' || ele || ', -9, 1) = ''2'' THEN CONCAT(' || tenant_id || ', ''0000'', 2000, SUBSTRING(' || ele || ', -7)) END '; res := CONCAT(CONCAT(ele_copy, ','), res); i := i + 1; END LOOP; UPDATE T100_GSUPR1_CPTLSYS_00.CPS_SYS_PARAM_INST_SITE SET VALUE = res WHERE PARAM_CODE = 'RECONCILIATION_AUTO_SUMMARY_REPORT_NOTIFICATION_OPERATOR'; COMMIT; END; / CALL UPDATE_hsy('CPS_BANK_ORG_MAPPING', 'IDENTITY_ID'); 中间 ' || ele_copy || ' := SELECT CASE WHEN SUBSTRING(' || ele || ', -9, 1) <> ''2'' THEN CONCAT(' || tenant_id || ', ''0000'', 2000, 8, SUBSTRING(' || ele || ', -6)) WHEN SUBSTRING(' || ele || ', -9, 1) = ''2'' THEN CONCAT(' || tenant_id || ', ''0000'', 2000, SUBSTRING(' || ele || ', -7)) END好像不支持 要如何改
09-09
你遇到的错误: ``` [ERROR] refresh_summary 执行异常: not enough arguments for format string ``` 说明:**Python 字符串格式化时,占位符 `%s` 的数量与传入参数的数量不匹配。** --- ### ❌ 问题定位 在 `refresh_summary()` 函数中,我们构建了动态 SQL 查询语句,其中使用了: ```python if material_codes_filter: placeholders = ','.join(['%s'] * len(material_codes_filter)) condition = f"AND mm.material_code IN ({placeholders})" full_params = params + material_codes_filter # ✅ 这里没问题 else: condition = "" full_params = params # ✅ 没问题 ``` 然后执行: ```python cursor.execute(query, full_params) ``` 但 `query` 是通过 **f-string 拼接进来的 `condition`**,而 `condition` 中包含 `%s`,这会导致 Python 把它误认为是字符串格式化的占位符! > 🔥 **这就是根本原因!** > > ```python > query = f""" > SELECT ... > WHERE ... {condition} ← condition 包含 %s,但 f-string 不会保留它们给 pymysql > """ > ``` > > 结果:Python 提前尝试格式化整个字符串 → 占位符数量 ≠ 参数数量 → 抛出异常。 --- ## ✅ 正确解决方案:避免 f-string 与 `%s` 冲突 我们要让 SQL 中的 `%s` 完整传递给 `pymysql` 处理,而不是被 Python 提前解析。 ### ✅ 修改方式一:用 `{}` 替代 `%s` 在 f-string 中(推荐) 将 `IN (%s, %s, ...)` 中的 `%s` 改为 `{}`,最后再替换回来。 ```python # ============================= # ✅ 刷新统计函数(修复:避免 %s 被提前解析) # ============================= def refresh_summary(start_date_str, end_date_str, filter_text=""): for row in summary_tree.get_children(): summary_tree.delete(row) try: start_dt = datetime.strptime(start_date_str, "%Y-%m-%d") end_dt = datetime.strptime(end_date_str, "%Y-%m-%d") except ValueError: messagebox.showwarning("日期错误", "请使用 YYYY-MM-DD 格式输入登记时间范围") return try: base_where = "cr.Date >= %s AND cr.Date < %s + INTERVAL 1 DAY" params = [start_dt, end_dt] material_codes_filter = [] if filter_text.strip(): like_term = f"%{filter_text.strip()}%" query_match_material = """ SELECT DISTINCT mm.material_code FROM material_master mm INNER JOIN CK_receipt cr ON mm.CustomerRef = cr.CK_Item OR mm.material_code = cr.MappedMaterialCode WHERE (mm.CustomerRef LIKE %s OR mm.material_code LIKE %s) AND cr.Date BETWEEN %s AND %s """ cursor.execute(query_match_material, (like_term, like_term, start_dt, end_dt)) rows = cursor.fetchall() material_codes_filter = [r[0].strip() for r in rows] if rows else [] if not material_codes_filter: summary_tree.insert("", "end", values=["-", "-", "0", "0"], tags=("empty",)) return # 构建 IN 条件:使用 {} 避免被 % 格式化干扰 if material_codes_filter: placeholders = ','.join(['%s'] * len(material_codes_filter)) condition = f"AND mm.material_code IN ({placeholders})" full_params = params + material_codes_filter else: condition = "" full_params = params # 使用 {} 占位,避免 %s 被提前处理 query_template = """ SELECT mm.material_code, mm.CustomerRef, COALESCE(out_stats.total_out, 0), COALESCE(cr_stats.total_received, 0) FROM material_master mm LEFT JOIN ( SELECT o.material_code, SUM(o.quantity) AS total_out FROM outbound o WHERE o.date_out BETWEEN %s AND %s GROUP BY o.material_code ) out_stats ON mm.material_code = out_stats.material_code LEFT JOIN ( SELECT cr.MappedMaterialCode, SUM(cr.Qty) AS total_received FROM CK_receipt cr WHERE cr.Date >= %s AND cr.Date < %s + INTERVAL 1 DAY GROUP BY cr.MappedMaterialCode ) cr_stats ON mm.material_code = cr_stats.MappedMaterialCode WHERE mm.CustomerRef IS NOT NULL AND mm.CustomerRef != '' {condition} AND (out_stats.total_out > 0 OR cr_stats.total_received > 0) ORDER BY mm.material_code """ # 将 {condition} 插入,但保留 %s 给 execute 处理 query = query_template.format(condition=condition) cursor.execute(query, full_params) rows = cursor.fetchall() if not rows: summary_tree.insert("", "end", values=["-", "-", "0", "0"], tags=("empty",)) else: for row in rows: material_code = str(row[0]) customer_ref = str(row[1]) total_out = float(row[2]) total_in = float(row[3]) summary_tree.insert("", "end", values=[ material_code, customer_ref, f"{total_out:g}", f"{total_in:g}" ]) except Exception as e: messagebox.showerror("统计失败", f"加载统计数据失败:\n{str(e)}") print(f"[ERROR] refresh_summary 执行异常: {e}") ``` --- ### ✅ 关键修改点总结 | 原代码问题 | 修正方法 | |----------|---------| | `f"SELECT ... {condition}"` 中 `condition` 含 `%s` | 改用 `.format()` 插入 `condition` | | 直接拼接导致 `%s` 被 Python 解析 | 让所有 `%s` 留给 `cursor.execute()` 处理 | --- ### ✅ 其他建议优化 如果你担心 SQL 注入(虽然这里不会),可以用更安全的方式生成条件: ```python # 更清晰的写法 if material_codes_filter: placeholders = ','.join(['%s'] * len(material_codes_filter)) condition = f"AND mm.material_code IN ({placeholders})" sql_params = [start_dt, end_dt, start_dt, end_dt] + material_codes_filter else: condition = "" sql_params = [start_dt, end_dt, start_dt, end_dt] ``` 然后确保最终 SQL 不经过 `%` 或 `f""` 格式化。 --- ✅ 现在你应该不会再看到 `not enough arguments for format string` 错误了! ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值