MySql -- 学习笔记 REPLACE + PREPARED

博客介绍了MySQL REPLACE语句的用法,若给定行数据不存在则插入新行,存在则先删旧行再插新行,某些情况仅更新现有行,还对比了与INSERT、UPDATE的差异。此外,还提及使用其他三个MySQL语句来执行带占位符的查询以提高速度和安全性。
  • 如果给定行数据不存在,那么MySQL REPLACE语句会插入一个新行
  • 如果给定行数据存在,则REPLACE语句首先删除旧行,然后插入一个新行。 在某些情况下,REPLACE语句仅更新现有行

REPLACE类似于INSERT用法,但是当REPLACE的时候没有列默认值的时候会报错,而INSERT不会


第二种用法类似UPDATE

REPLACE INTO table SET column1 = value1, column2 = value2;

与UPDATE不同,如果没指定列,会使用默认值

 

PREPARE语句来执行带占位符的查询,以提高查询的速度,并使您的查询更安全。

为了使用MySQL准备语句,您需要使用其他三个MySQL语句如下:

  • PREPARE - 准备执行的声明。
  • EXECUTE - 执行由PREPARE语句定义的语句。
  • DEALLOCATE PREPARE - 发布PREPARE语句。

 

https://www.yiibai.com/mysql/prepared-statement.html

 

 


 

你遇到了关键错误: ```sql ERROR 1243 (HY000): Unknown prepared statement handler (stmt) given to DEALLOCATE PREPARE ``` 并且表中数据 **没有被清空**(`TABLE_ROWS` 显示大量记录)。 --- ## 🔍 错误原因分析 在你的存储过程中,有这一行: ```sql DEALLOCATE PREPARE stmt; ``` 但你在 `PREPARE` 时使用的是变量名 `prepared_stmt`: ```sql PREPARE prepared_stmt FROM @stmt; ``` 而释放时却写成了: ```sql DEALLOCATE PREPARE stmt; -- ❌ 错了!应该是 prepared_stmt ``` ### 🚫 错误点: ```sql DEALLOCATE PREPARE stmt; -- 错误的句柄名 ``` 应该为: ```sql DEALLOCATE PREPARE prepared_stmt; -- ✅ 正确 ``` 由于句柄名称不匹配,导致 `DEALLOCATE` 失败,后续循环也会中断 —— 存储过程实际 **未正确执行任何 `TRUNCATE` 操作**! --- ## ✅ 修复后的完整存储过程(已修正命名) ```sql USE board_db; -- 禁用外键检查 SET FOREIGN_KEY_CHECKS = 0; -- 删除旧的存储过程(如果有) DROP PROCEDURE IF EXISTS truncate_all_tables; DELIMITER $$ CREATE PROCEDURE truncate_all_tables() BEGIN DECLARE done INT DEFAULT FALSE; DECLARE tbl_name VARCHAR(255); -- 声明游标:获取当前数据库中所有表名 DECLARE cur CURSOR FOR SELECT table_name FROM information_schema.tables WHERE table_schema = DATABASE() AND table_type = 'BASE TABLE'; -- 声明循环结束标志 DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE; -- 打开游标 OPEN cur; read_loop: LOOP FETCH cur INTO tbl_name; IF done THEN LEAVE read_loop; END IF; -- 动态构造并执行 TRUNCATE TABLE `xxx` SET @stmt = CONCAT('TRUNCATE TABLE `', tbl_name, '`'); PREPARE prepared_stmt FROM @stmt; EXECUTE prepared_stmt; DEALLOCATE PREPARE prepared_stmt; -- ✅ 修正:句柄名一致 END LOOP; CLOSE cur; END$$ DELIMITER ; ``` --- ## ✅ 重新创建并调用存储过程 ```sql -- 重新创建存储过程 SOURCE /path/to/your/script.sql; -- 或手动粘贴上面代码 -- 调用 CALL truncate_all_tables(); -- 恢复外键检查(虽然前面已设,再确认一次) SET FOREIGN_KEY_CHECKS = 1; ``` --- ## ✅ 验证是否清空成功 ```sql SELECT table_name, table_rows AS estimated_count FROM information_schema.tables WHERE table_schema = 'board_db' ORDER BY table_name; ``` 预期输出:所有 `estimated_count` 应为 `0` 或非常小(InnoDB 统计是估算值)。 > 💡 提示:`information_schema.tables.table_rows` 是 InnoDB 的**估算值**,不一定准确。要验证真实行数,请对具体表执行: > > ```sql > SELECT COUNT(*) FROM b_warehouse; > SELECT COUNT(*) FROM b_dock; > ``` --- ## ✅ 替代方案:使用 DELETE(更兼容、可调试) 如果你仍遇到问题,可以用 `DELETE FROM` 替代(支持级联、可回滚): ```sql -- 使用 DELETE 清空所有表(适合有外键依赖且不想改结构) SET FOREIGN_KEY_CHECKS = 0; -- 示例:逐个删除(你可以写脚本生成这些语句) DELETE FROM ai_appoperationlogs; DELETE FROM ai_appreportrecords; -- ... 其他表 DELETE FROM b_warehouse; SET FOREIGN_KEY_CHECKS = 1; ``` 📌 注意:`DELETE` 不会重置自增 ID,如需重置: ```sql ALTER TABLE b_warehouse AUTO_INCREMENT = 1; ``` --- ## ✅ 推荐终极安全脚本(Python 实现,推荐用于生产环境) ```python import pymysql conn = pymysql.connect( host='localhost', user='root', password='your_password', database='board_db' ) cursor = conn.cursor() try: cursor.execute("SET FOREIGN_KEY_CHECKS=0;") print("✅ 已禁用外键检查") # 获取所有表 cursor.execute("SHOW TABLES") tables = [row[0] for row in cursor.fetchall()] for table in tables: cursor.execute(f"TRUNCATE TABLE `{table}`") print(f"✅ 清空表: {table}") conn.commit() print("🎉 所有表已成功清空!") except Exception as e: conn.rollback() print("❌ 操作失败:", str(e)) finally: cursor.close() conn.close() ``` --- ## ✅ 总结:你之前失败的原因 | 问题 | 解决方式 | |------|----------| | `DEALLOCATE PREPARE stmt` 句柄名错误 | 改为 `prepared_stmt` | | 存储过程因异常中断,未执行任何 `TRUNCATE` | 修正后重新创建 | | `TABLE_ROWS` 不为零 | 因根本没删成 | ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值