ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

SQLite3 插入多变量时 AUTOINCREMENT 字段怎么处理?TaoToken 场景下的 Python 实操大纲

SQLite3 插入多变量时 AUTOINCREMENT 字段怎么处理?TaoToken 场景下的 Python 实操大纲 1. 从一次批量入库报错说起SQLite3 自增主键到底该不该占位先说结论在 Python 的 sqlite3 里做insert into多变量插入时AUTOINCREMENT那个字段不要出现在字段列表里也不要给它占位符。你只要把需要写入的列名和对应的?排好队自增主键交给 SQLite 自己填就行。这个规则听起来简单但实际写脚本时十个人里有八个会在第一次批量插入时踩坑。我见过最典型的场景是这样的本地跑一个爬虫或者数据采集脚本抓回来一批记录想一次性塞进 SQLite。表结构里有个id INTEGER PRIMARY KEY AUTOINCREMENT然后写插入语句的时候顺手把id也写进去了变成insert into jobs (id, name, salary) values (?, ?, ?)参数里还得硬凑一个 id 值。结果要么报datatype mismatch要么插入的 id 全是手动指定的自增机制形同虚设后面再插新数据直接主键冲突。还有一种更隐蔽的写法用字符串format拼接 SQL像values ({},{},{})这样。单条插入可能侥幸能跑一旦字段里带单引号或者特殊字符SQL 直接语法错误严重的话还有注入风险。所以这篇内容我打算把三件事讲透建表时自增字段怎么声明、execute和executemany的参数化写法、以及插入后怎么用lastrowid把自增 id 读回来验证。适合谁看如果你在用 Python 写本地小工具、轻量服务、数据清洗脚本需要把一批变量写进 SQLite同时对自增主键的处理心里没底那这篇就是给你准备的。整套流程我会给可复制的建表 SQL、完整的 Python 代码、以及跑通后的输出结果你照着敲一遍就能落地。调试环节如果涉及通过统一 Key/API 通道排查请求我也会说明怎么借助 TaoToken 的接口做请求侧的问题定位避免把数据库问题和网络问题混在一起查。核心检索词先摆出来SQLite3、insert into、python、自动增长字段、AUTOINCREMENT。这几个词基本覆盖了你要解决的全部问题域。下面从建表开始一步步把自增字段的占位问题拆开。2. TaoToken 前置准备统一 Key/API 通道在调试环节的作用在正式写插入代码之前先花点篇幅说清楚 TaoToken 在这个场景里扮演什么角色。你可能会问我只是往本地 SQLite 插数据跟 API 通道有什么关系关系在于调试链路的隔离。当你的脚本不只是本地入库还要调用模型接口做数据加工、字段补全或者结果校验时请求侧的问题和数据库侧的问题很容易混在一起。这时候有一个统一的 Key/API 通道能把「请求有没有发出去、返回了什么」和「数据有没有写进库」分开看排查效率会高很多。TaoToken 的定位是统一的模型调用入口官网地址是 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content API 入口是 https://taotoken.net/api 。它的价值在于你不需要为每个模型单独维护一套鉴权和地址用一个 Key 就能走通多条调用链路。对于本地脚本来说这意味着你的配置项更少出问题时需要检查的变量也更少。前置准备分三步。第一步拿到 API Key。进入控制台的 API Keys 页面创建地址是 https://taotoken.net/console/api-keys?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。创建后把 Key 复制出来存到环境变量里别硬编码进脚本。第二步确认你要调用的模型 ID。不同模型的能力和计费不一样选一个适合你任务的即可。第三步把 Base URL 指向 https://taotoken.net/api 这样你的请求就会走统一通道。这里给一个最小可用的配置片段用环境变量管理避免 Key 泄露export TAOTOKEN_API_KEY你的Key export TAOTOKEN_BASE_URLhttps://taotoken.net/api export TAOTOKEN_MODEL你的模型ID如果你用的是 Python读取方式就是os.environ.get(TAOTOKEN_API_KEY)。这样做的好处是脚本可以进版本库Key 不会跟着泄露。我试过把 Key 直接写在代码里然后不小心提交后面清理起来很麻烦所以这一步别省。需要强调的是TaoToken 在这里是调试辅助通道不是数据库本身。SQLite 的插入逻辑完全在本地完成TaoToken 负责的是当你的数据需要经过模型处理时提供一个稳定的请求出口。两者职责分开排查问题时才能各查各的。如果你只是纯本地入库不涉及任何接口调用那这一节可以当作背景知识直接跳到下一节的建表和插入代码。对于长期做编码和 Agent 类任务的同学如果调用频率比较高可以了解一下 Coding Plan地址是 https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 按需选择即可。模型对话的入口在 https://taotoken.net/models?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 接入文档在 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 需要查参数的时候直接翻文档最快。3. 可复制配置建表 SQL 与参数化插入写法这一节是全文的核心直接给能跑的代码。先建表。假设我们要存一批职位数据字段有职位名、薪资、公司主键自增。建表 SQL 如下CREATE TABLE IF NOT EXISTS jobs ( id INTEGER PRIMARY KEY AUTOINCREMENT, job_name TEXT NOT NULL, job_money TEXT, company TEXT, created_at TEXT DEFAULT CURRENT_TIMESTAMP );关键点在id INTEGER PRIMARY KEY AUTOINCREMENT这一行。在 SQLite 里INTEGER PRIMARY KEY本身就已经是行号别名默认就会自增。加上AUTOINCREMENT关键字后SQLite 会额外维护一个sqlite_sequence表来保证 id 严格单调递增不会复用被删除的 id。如果你不需要严格不复用其实INTEGER PRIMARY KEY就够了但既然标题里点名了 AUTOINCREMENT我们就按严格模式来。建表之后插入语句的字段列表里只写业务字段不写 idimport sqlite3 conn sqlite3.connect(jobs.db) cursor conn.cursor() cursor.execute( CREATE TABLE IF NOT EXISTS jobs ( id INTEGER PRIMARY KEY AUTOINCREMENT, job_name TEXT NOT NULL, job_money TEXT, company TEXT, created_at TEXT DEFAULT CURRENT_TIMESTAMP ) ) conn.commit()接下来是单条参数化插入。注意占位符用?参数用元组传顺序和字段列表一一对应cursor.execute( INSERT INTO jobs (job_name, job_money, company) VALUES (?, ?, ?), (Python 开发, 20k-35k, 某科技公司) ) conn.commit() print(单条插入后的 lastrowid:, cursor.lastrowid)cursor.lastrowid就是刚插入这条记录的自增 id。这是回读自增字段最直接的方式不需要再查一次数据库。批量插入用executemany参数是一个可迭代对象每个元素是一个元组rows [ (数据分析师, 15k-25k, 某数据公司), (后端工程师, 25k-40k, 某互联网公司), (测试开发, 18k-28k, 某软件公司), ] cursor.executemany( INSERT INTO jobs (job_name, job_money, company) VALUES (?, ?, ?), rows ) conn.commit() print(批量插入影响行数:, cursor.rowcount) print(批量插入后最后一条的 lastrowid:, cursor.lastrowid)这里有个细节要注意executemany执行完后cursor.lastrowid返回的是最后一条插入记录的 id不是每一条的。如果你想拿到每一条的 id要么逐条execute要么插入后按业务字段回查。批量场景下通常不需要每条 id知道最后一条就够了。如果你需要把配置写成结构化文件方便脚本读取可以用 JSON{ db_path: jobs.db, table: jobs, columns: [job_name, job_money, company], base_url: https://taotoken.net/api, model: 你的模型ID }注意columns里不包含 id这跟插入语句的字段列表保持一致。配置文件里也不要写 KeyKey 走环境变量。这样一套配置下来建表、单条插入、批量插入、自增回读就全通了。再强调一次那个最容易错的点INSERT INTO jobs (id, job_name, ...) VALUES (?, ?, ...)这种写法除非你明确要手动指定 id否则不要写。让 SQLite 自己管自增字段你只管业务列。字符串format拼接的写法也丢掉参数化查询既安全又省心。4. 验证请求与成功结果lastrowid 回读与完整跑通示例代码写完得跑一遍看结果。这一节给一个完整的、可以直接复制运行的脚本把建表、插入、回读、查询验证串起来。跑完之后你能看到自增 id 的实际值确认 AUTOINCREMENT 生效。import sqlite3 import os DB_PATH jobs.db def init_db(conn): conn.execute( CREATE TABLE IF NOT EXISTS jobs ( id INTEGER PRIMARY KEY AUTOINCREMENT, job_name TEXT NOT NULL, job_money TEXT, company TEXT, created_at TEXT DEFAULT CURRENT_TIMESTAMP ) ) conn.commit() def insert_one(conn, job_name, job_money, company): cur conn.execute( INSERT INTO jobs (job_name, job_money, company) VALUES (?, ?, ?), (job_name, job_money, company) ) conn.commit() return cur.lastrowid def insert_many(conn, rows): cur conn.executemany( INSERT INTO jobs (job_name, job_money, company) VALUES (?, ?, ?), rows ) conn.commit() return cur.rowcount, cur.lastrowid def query_all(conn): cur conn.execute(SELECT id, job_name, job_money, company FROM jobs ORDER BY id) return cur.fetchall() if __name__ __main__: conn sqlite3.connect(DB_PATH) init_db(conn) first_id insert_one(conn, Python 开发, 20k-35k, 某科技公司) print(第一条插入的 id:, first_id) rows [ (数据分析师, 15k-25k, 某数据公司), (后端工程师, 25k-40k, 某互联网公司), (测试开发, 18k-28k, 某软件公司), ] count, last_id insert_many(conn, rows) print(批量插入行数:, count) print(批量插入最后一条 id:, last_id) print(全表数据:) for row in query_all(conn): print(row) conn.close()跑一遍输出大概是这样第一条插入的 id: 1 批量插入行数: 3 批量插入最后一条 id: 4 全表数据: (1, Python 开发, 20k-35k, 某科技公司) (2, 数据分析师, 15k-25k, 某数据公司) (3, 后端工程师, 25k-40k, 某互联网公司) (4, 测试开发, 18k-28k, 某软件公司)看到 id 从 1 连续到 4说明自增字段工作正常而且我们全程没有手动给 id 赋值。lastrowid在单条插入时返回 1批量插入后返回 4跟全表查询的结果对得上。这就是验证成功的标志。如果你在脚本里还调用了模型接口做数据加工比如把职位描述丢给模型做摘要那验证就要分两层先确认接口返回正常再确认数据入库正常。接口侧可以用 TaoToken 的模型对话入口手动发一条测试请求地址是 https://taotoken.net/models?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 看返回结构是否符合预期。数据库侧就用上面的脚本验证。两层都过了整条链路才算通。还有一个验证技巧插入之后立刻用SELECT last_insert_rowid()查一次结果应该跟cursor.lastrowid一致。如果两者不一致说明中间有别的连接插入了数据或者你用的不是同一个 cursor。这个检查在并发场景下特别有用。cur conn.execute(SELECT last_insert_rowid()) print(SQL 查询到的 last_insert_rowid:, cur.fetchone()[0])实测下来单连接单线程的本地脚本基本不会出问题但养成回读验证的习惯后面数据量大了也不会慌。5. 本篇常见错排查401、local proxy failed、reading choices 与 OAuth这一节把实际会撞到的报错列出来对照着查。注意区分数据库侧和请求侧别把两类问题混在一起。报错一sqlite3.OperationalError: table jobs has 4 columns but 5 values were supplied这是字段数和值数对不上。最常见的原因就是你给自增 id 也写了占位符但字段列表里没写 id或者反过来。检查INSERT INTO jobs (...)括号里的列数和VALUES (?, ?, ?)里的问号数以及参数元组的长度三者必须一致。自增字段不参与所以列数应该是 3问号 3 个元组 3 个元素。报错二sqlite3.IntegrityError: NOT NULL constraint failed: jobs.job_name参数顺序错了或者某个必填字段传了 None。参数化插入是按位置对应的元组里第一个值对应字段列表第一个列。如果你把company的值传到了job_name的位置就可能触发非空约束。打印一下你的字段列表和参数元组逐个对齐。报错三sqlite3.ProgrammingError: Incorrect number of bindings suppliedexecutemany的每个元素长度和占位符数量不一致。比如你写的是 3 个问号但某个元组只有 2 个元素。检查rows里每一条的长度是否统一。报错四HTTP 401 Unauthorized这是请求侧的问题不是数据库问题。说明你的 API Key 没带上、带错了或者环境变量没读到。检查TAOTOKEN_API_KEY是否设置成功可以用echo $TAOTOKEN_API_KEY确认。如果是在 Python 里读的打印一下os.environ.get(TAOTOKEN_API_KEY)看是不是 None。Key 的创建入口在 https://taotoken.net/console/api-keys?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 重新生成一个再试。报错五local proxy failed或连接超时这类报错通常出现在请求发不出去的时候。先确认 Base URL 是不是https://taotoken.net/api路径有没有拼错。然后确认本机网络能正常访问外网。如果你在容器或虚拟环境里跑检查环境变量有没有透传进去。这个报错跟 SQLite 无关别去翻数据库代码。报错六reading choices相关解析错误这通常发生在你解析模型返回结果的时候。返回体结构跟你预期的不一样可能是模型 ID 选错了或者请求参数不完整。先用模型对话入口手动发一条最简单的请求看原始返回长什么样再对照你的解析代码。地址是 https://taotoken.net/models?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。报错七OAuth 相关鉴权失败如果你用的是需要 OAuth 流程的客户端检查 token 是否过期、回调地址是否配置正确。这类问题优先看接入文档 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 里面通常有完整的鉴权步骤说明。排查顺序建议先看报错是sqlite3.开头还是 HTTP 状态码开头。前者查数据库代码后者查请求配置。两类问题分开处理效率会高很多。数据库侧的问题九成出在字段列表和参数对不上请求侧的问题九成出在 Key 和 Base URL。把这两个高频点记住大部分报错都能自己解决。6. 语义一致的收尾把自增字段交给 SQLite把调试交给统一通道回到最开始那个问题AUTOINCREMENT字段怎么处理答案就是三个字——不处理。建表时声明好插入时字段列表里不写它参数里不给它占位SQLite 自己会把 id 填上。你要做的只是用cursor.lastrowid把值读回来验证。这套逻辑在单条插入和executemany批量插入里都成立代码可以直接复制去用。真正容易出问题的地方从来不是自增字段本身而是字段列表和参数的对齐、以及请求侧和数据库侧的混淆。前者靠参数化查询和逐项核对解决后者靠把 TaoToken 的统一通道和本地 SQLite 分开看待来解决。当你的脚本既要入库又要调接口时先确认接口返回正常再确认数据写入正常两层验证都过了整条链路才算稳。如果你在调试请求时遇到鉴权或返回解析的问题API Keys 页面和接入文档是最快的入口https://taotoken.net/console/api-keys?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 和 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。需要手动验证模型返回时模型对话入口在 https://taotoken.net/models?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。长期跑编码和 Agent 任务的话Coding Plan 在 https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。最后留一个实用习惯每次改完插入逻辑先跑一遍全表查询看 id 是不是连续递增。连续就说明自增没被破坏不连续就回头查是不是手动写了 id 或者删过数据。这个小检查花不了几秒但能帮你省下大量排查时间。
返回列表