IntegrityError错误

本文记录了一次使用Python操作SQLite3数据库时遇到的IntegrityError错误,并详细解析了错误原因及解决方法。作者在尝试插入数据时未正确设置非空字段导致插入失败。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

   Python插入数据库提交失败,一直走IntegrityError错误,没打印错误信息(一定注意编码规范,记住打印错误信息),以为插不进去,弄了好久,最后打印了错误信息

 

(sqlite3.IntegrityError) samples.file_type may not be NULL [SQL: u'INSERT INTO samples (file_size, file_type, md5, crc32, sha1, sha256, sha512, ssdeep) VALUES (?, ?, ?, ?, ?, ?, ?, ?)'] [parameters: (53, None, 'hello', 'crc32', 'sha1', 'sha256', 'sha512', None)]

 

  提示为file_type不能为空,但是我建表的时候file_type设置的是不允许为空,而插入的时候file_type传入为NULL,所以Insert不成功,报错IntegrityError

from sqlalchemy import Column, Integer, String
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Text, Index
from sqlalchemy.exc import SQLAlchemyError, IntegrityError
from sqlalchemy.orm import sessionmaker

Base = declarative_base()


class Sample(Base):
    """Submitted files details."""
    __tablename__ = "samples"

    id = Column(Integer(), primary_key=True)
    file_size = Column(Integer(), nullable=False)
    file_type = Column(Text(), nullable=False)
    md5 = Column(String(32), nullable=False)
    crc32 = Column(String(8), nullable=False)
    sha1 = Column(String(40), nullable=False)
    sha256 = Column(String(64), nullable=False)
    sha512 = Column(String(128), nullable=False)
    ssdeep = Column(String(255), nullable=True)
    __table_args__ = Index("hash_index", "md5", "crc32", "sha1",
                           "sha256", "sha512", unique=True),

    def __repr__(self):
        return "<Sample('{0}','{1}')>".format(self.id, self.sha256)


    def __init__(self, md5, crc32, sha1, sha256, sha512,
                 file_size, file_type=None, ssdeep=None):
        self.md5 = md5
        self.sha1 = sha1
        self.crc32 = crc32
        self.sha256 = sha256
        self.sha512 = sha512
        self.file_size = file_size
        if file_type:
            self.file_type = file_type
        if ssdeep:
            self.ssdeep = ssdeep
			
engine = create_engine("sqlite:///cuckoo.db",echo=True)   #返回连接引擎

metadata = Base.metadata
metadata.create_all(engine)  #连接或者创建

			
#sample_mike = Sample("hello", "crc32", "sha1", "sha256", "sha512", 53, None, None)  #非空数据不能传空
sample_mike = Sample("hello", "crc32", "sha1", "sha256", "sha512", 53, "aa", None)
Session = sessionmaker(bind=engine) session = Session() session.add(sample_mike)  #数据库会话
try:
  session.commit() #提交
except IntegrityError as e:
  print e
except SQLAlchemyError as e:
  print e

  

最后在网上看到一个比较有用的工具sqlite,查看db数据库

 

sqlite、db、insert.py下载     http://files.cnblogs.com/files/aliflycoris/db.zip

转载于:https://www.cnblogs.com/aliflycoris/p/5748393.html

<think>嗯,用户现在的问题是,在使用pymysql插入数据时如何忽略错误。我需要根据他们之前的讨论和提供的引用内容来回答。首先,用户之前提到过关于PostgreSQL的处理方法,比如使用游标、异常处理等,但现在转向了pymysql,也就是MySQL的Python驱动。 首先,我需要回忆pymysql的基本用法,尤其是插入数据时的错误处理。在之前的回答中,用户提到了异常处理,比如捕获psycopg2.Error,但这里需要针对pymysql的错误处理。pymysql常见的错误包括IntegrityError,比如主键冲突、外键约束失败等,还有DataError、OperationalError等。 用户想忽略这些错误,即当插入数据时出现错误,程序不中断,继续执行后续操作。常见的做法是使用try-except块捕获特定的异常,然后做出相应处理,比如记录日志但继续执行。 接下来,我需要参考用户提供的引用内容。引用[1]提到了MySQL的配置参数,比如innodb_buffer_pool_size,但用户的问题是关于插入时忽略错误,可能不直接相关。引用[2]是关于sqlite3的上下文管理器,但用户现在用pymysql,所以可能需要类似的连接管理。引用[3]涉及SQL的随机抽样,可能和当前问题无关。引用[4]是UDP客户端的示例代码,也不相关。 所以主要参考用户之前的回答,比如异常处理、事务管理、游标操作等。用户之前提到了在PostgreSQL中使用事务回滚,在pymysql中也需要类似的处理,比如在捕获异常后回滚事务,或者根据情况提交。 用户的需求是忽略错误,即插入时如果出错,跳过该条记录,继续插入其他数据。可能的解决方案包括: 1. 使用INSERT IGNORE语句:这是MySQL的语法,可以在插入时忽略错误,但需要修改SQL语句。 2. 使用ON DUPLICATE KEY UPDATE:处理重复键的情况,但可能不是完全忽略错误。 3. 捕获pymysql的IntegrityError异常,并在except块中pass或者记录错误,然后继续执行。 需要比较这些方法的优缺点。INSERT IGNORE是服务器端处理,不会引发异常,但可能隐藏其他潜在错误。捕获异常的方法更灵活,可以针对特定错误进行处理,但需要正确识别异常类型。 另外,用户可能需要批量插入时的错误处理,比如使用executemany方法,但其中部分记录出错时如何处理。这可能涉及到事务的控制,比如是否在插入失败时回滚整个事务,还是只跳过错误记录。 还要注意pymysql的事务默认是自动提交的,或者在开启事务后需要手动提交。如果在插入多条数据时忽略单条错误,可能需要逐条插入并处理异常,或者在批量插入时使用某种方式忽略错误。 结合用户之前的回答中提到的异常处理和事务管理,最佳实践可能包括: - 使用try-except块捕获pymysql的IntegrityError和其他可能的异常。 - 在插入时使用INSERT IGNORE语句,避免抛出异常。 - 或者在批量处理时,逐条插入并捕获异常,记录错误后继续。 同时,需要考虑事务的一致性需求。如果用户希望即使部分插入失败,其他成功的插入仍然提交,可能需要设置autocommit为True,或者在捕获异常后执行commit。否则,可能需要手动控制事务点。 比如,使用INSERT IGNORE不需要修改Python代码,只需修改SQL语句,但可能无法区分不同的错误类型。而捕获异常的方法可以在代码层面更灵活地处理错误,比如记录日志、跳过特定错误类型等。 另外,用户可能需要知道如何配置pymysql的连接参数,比如设置autocommit,或者在执行插入后手动提交。 总结可能的步骤: 1. 修改SQL语句为INSERT IGNORE INTO ...,这样MySQL会忽略可忽略的错误,如重复键。 2. 在Python代码中使用try-except块,捕获pymysql.errors.IntegrityError,并在except块中处理(如pass)。 3. 批量插入时,可能需要逐条处理,或者在executemany中使用某种方式忽略错误。 同时,需要提到事务处理,例如,如果使用事务,部分错误可能导致需要回滚,但用户希望忽略错误,可能需要逐条提交或者调整事务的粒度。 可能还需要提到使用LOGGER来记录错误,而不是静默忽略,以便后续排查问题。 根据用户之前的回答中提到的性能注意事项,比如使用executemany的效率问题,可能需要权衡逐条插入和批量插入的性能影响。 所以,最佳实践可能包括: - 使用INSERT IGNORE语句来让MySQL自动忽略重复等错误。 - 结合异常处理,捕获特定的错误,确保其他类型的错误(如数据类型错误)仍能被捕获和处理。 - 在批量插入时,逐条处理并使用异常处理,或者使用INSERT IGNORE配合executemany。 - 管理好事务,避免因部分错误导致整个事务回滚,如果业务允许的话。 需要验证这些方法的正确性,比如测试INSERT IGNORE是否真的在pymysql中不抛出异常,或者在哪些情况下会抛出异常。例如,如果插入的数据类型错误,即使使用INSERT IGNORE,MySQL可能仍然会报错,导致异常被抛出,此时仍需要异常处理。 因此,综合来看,最佳实践应该是结合SQL语句的修改(如INSERT IGNORE)和Python代码中的异常处理,同时合理管理事务和连接。</think>在使用`pymysql`插入数据时忽略错误,可通过以下6种方法实现,结合事务控制与异常处理: --- ### 一、核心解决方案 #### 1. **INSERT IGNORE 语句** 直接通过SQL语法忽略重复键等错误(不影响其他错误): ```python import pymysql from pymysql import MySQLError sql = "INSERT IGNORE INTO users (id, name) VALUES (%s, %s)" data = [(1, 'Alice'), (1, 'Bob')] # 主键冲突示例 with pymysql.connect(host='localhost', user='root', database='test') as conn: cursor = conn.cursor() try: cursor.executemany(sql, data) conn.commit() # 提交事务 except MySQLError as e: print(f"非重复键错误: {e}") conn.rollback() ``` #### 2. **异常捕获过滤** 精确控制需要忽略的错误类型: ```python from pymysql.err import IntegrityError try: cursor.execute("INSERT INTO products VALUES (1001, 'Phone')") except IntegrityError as e: # 主键冲突、外键约束等 code, _ = e.args if code == 1062: # 主键重复错误码 print("重复数据已跳过") else: raise # 其他错误重新抛出 except MySQLError as e: print(f"其他数据库错误: {e}") ``` --- ### 二、高级配置方案 #### 3. **批量插入容错模式** 逐条插入并记录失败记录: ```python success, errors = [], [] for record in big_data: try: cursor.execute("INSERT INTO logs VALUES (%s, %s)", record) success.append(record) except IntegrityError: errors.append(record) conn.commit() # 提交所有成功操作 print(f"成功插入{len(success)}条,跳过{len(errors)}条错误") ``` #### 4. **SQL改写兼容** 使用`ON DUPLICATE KEY UPDATE`实现静默更新: ```python sql = """INSERT INTO inventory (item_id, stock) VALUES (%s, %s) ON DUPLICATE KEY UPDATE stock = VALUES(stock)""" cursor.executemany(sql, stock_updates) ``` --- ### 三、完整工程化示例 ```python import logging from pymysql import connect, MySQLError, IntegrityError logger = logging.getLogger(__name__) def safe_insert(conn_params, table, data): try: with connect(**conn_params) as conn: conn.autocommit(False) # 关闭自动提交 with conn.cursor() as cursor: placeholders = ','.join(['%s']*len(data[0])) query = f"INSERT IGNORE INTO {table} VALUES ({placeholders})" cursor.executemany(query, data) conn.commit() return {'success': cursor.rowcount, 'failed': len(data)-cursor.rowcount} except IntegrityError as e: logger.warning(f"数据完整性错误: {e}") conn.rollback() return {'success': 0, 'failed': len(data)} except MySQLError as e: logger.error(f"数据库操作失败: {e}") conn.rollback() raise ``` --- ### 四、关键注意事项 1. **错误类型识别** - `IntegrityError` (错误码1062/1452):主键冲突、外键约束违反 - `DataError`:数据类型不匹配 - 通过`e.args[0]`获取具体错误码 2. **事务原子性控制** - 默认情况下`executemany`是原子操作,任一错误会导致全部回滚 - 需要部分提交时需改用逐条插入+异常捕获 3. **性能平衡策略** | 方法 | 优点 | 缺点 | |---|---|--| | `INSERT IGNORE` | 单次交互高效 | 无法区分错误类型 | | 逐条插入 | 精确错误控制 | 网络开销大 | | 批量提交 | 平衡性能与容错 | 需手动管理批次 | --- ### 五、扩展应用场景 1. **ETL任务中的脏数据处理** ```python def etl_pipeline(): raw_data = extract_from_source() cleaned = [transform(d) for d in raw_data] result = safe_insert(cleaned) logger.info(f"成功加载{result['success']}条,丢弃{result['failed']}条异常数据") ``` 2. **实时流数据写入** ```python from concurrent.futures import ThreadPoolExecutor def async_insert(record): with get_connection() as conn: try: conn.cursor().execute("INSERT IGNORE INTO sensor_data VALUES (%s)", (record,)) conn.commit() except MySQLError: conn.rollback() with ThreadPoolExecutor() as executor: executor.map(async_insert, realtime_stream) ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值