数据迁移快速验数
凌晨两点,DBA 刚把生产库从 MySQL 迁到 PostgreSQL,业务方催着天亮前确认数据一致性。手工对账要写长脚本,表结构还不同。把两边导出的 CSV 各建一张临时表,写一联 JOIN 查差值,5 分钟出结果,不用等审批开数据库权限。
建表、插入、查询,一套 SQL 写完,发现表名拼错了。删表重来?不需要。打开这个页面,在浏览器里直接连一个 SQLite 数据库,执行任意 DDL 和 DML,结果即时返回。全部计算在本地完成,数据不上传服务器——适合调试数据模型、验证查询逻辑,或是临时分析一个 .db 文件,不必装任何客户端。
凌晨两点,DBA 刚把生产库从 MySQL 迁到 PostgreSQL,业务方催着天亮前确认数据一致性。手工对账要写长脚本,表结构还不同。把两边导出的 CSV 各建一张临时表,写一联 JOIN 查差值,5 分钟出结果,不用等审批开数据库权限。
运营要一份「过去 30 天活跃且未付费的用户清单」,数据分析师排期要三天。产品经理把埋点日志里筛选出的 3000 个 user_id 粘贴进 SQLite,写一句 SELECT WHERE last_login > date('now', '-30 days') AND pay_status = 0,直接在浏览器拿到结果,不等排期。
面试后端候选人时,对方说「这个查询用 GROUP_CONCAT 配合子查询就能实现」。面试官当场打开工具,把候选人说的 SQL 敲进去,建两张 10 行数据的 demo 表,跑一遍验证结果是否符合预期。不用开电脑上的数据库客户端,也不打断面试节奏。
从三个不同网页爬了 2000 条商品信息,价格字段有的带「¥」、有的带「元」、有的是纯数字。在工具里建一张临时表导入数据,写 UPDATE 语句用 REPLACE 和 TRIM 统一格式,再写 SELECT 检查异常值,比在 Excel 里拉公式快,且操作可复现。
教务老师要给 30 个班级排下学期的机房课,每个班每周 2 次课,机房只有 4 间,且不能和体育课冲突。把班级、机房、可用时段做成三张表,用 JOIN 和 NOT IN 查出所有可行组合,再按约束条件筛选,半小时排出无冲突的草表,比人工翻日历快得多。
| 输入 | 输出 | 说明 |
|---|---|---|
| CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT, age INTEGER); INSERT INTO users VALUES (1, 'Alice', 30), (2, 'Bob', 25); SELECT * FROM users; | id | name | age 1 | Alice| 30 2 | Bob | 25 | 常规:建表 + 插入 + 查询三步走,验证工具能否完整执行多语句 SQL 脚本 |
| SELECT 'Hello, world!' AS greeting; | greeting Hello, world! | 常规:无表查询,验证工具对纯表达式(字符串常量)的 SQL 支持 |
| CREATE TABLE t (a INTEGER); INSERT INTO t VALUES (NULL); SELECT * FROM t WHERE a IS NULL; | a NULL | 边界:NULL 值处理,验证 IS NULL 条件是否正常返回空行 |
| SELECT 1/0; | Error: division by zero | 边界:除零错误,验证工具是否抛出 SQLite 原生错误信息而非静默返回空 |
| SELECT 'abc' || 123; | abc123 | 边界:字符串拼接与隐式类型转换,验证 SQLite 自动将数字转为字符串的行为 |
| CREATE TABLE t (x TEXT); INSERT INTO t VALUES ('abc'); SELECT * FROM t WHERE x = 'ABC'; | x abc | 易错:SQLite 默认大小写不敏感(BINARY 除外),新手常误以为 'abc' ≠ 'ABC' 导致查询无结果 |
| SELECT datetime('now'); | 2025-04-08 14:30:15(示例值,实际为当前 UTC 时间) | 易错:datetime 函数返回 UTC 时间而非本地时间,用户常误以为得到的是浏览器时区时间 |
1.SQL 语句末尾缺少分号
SELECT * FROM users
SELECT * FROM ordersSELECT * FROM users;
SELECT * FROM orders;SQLite 要求每条完整语句以分号结束,否则解析器会认为语句未完成,导致后续语句被忽略或报错。
2.表名或列名用了 SQL 保留字未加引号
CREATE TABLE order (id INT, name TEXT)CREATE TABLE "order" (id INT, name TEXT);order 是 SQL 保留关键字(ORDER BY),直接用作表名会引发语法错误。用双引号括起来可避免冲突。
3.字符串值用了双引号而非单引号
SELECT * FROM users WHERE name = "Alice"SELECT * FROM users WHERE name = 'Alice';SQL 标准中,双引号用于标识符(表名/列名),字符串字面量必须用单引号。双引号包裹字符串在某些模式下会被当作标识符。
4.INSERT 语句的列数与值数不匹配
INSERT INTO users (id, name, age) VALUES (1, 'Bob')INSERT INTO users (id, name, age) VALUES (1, 'Bob', 25);SQLite 编译阶段会检查列数与值个数是否一致,不一致直接报错。多列时易遗漏某字段。
5.UPDATE 或 DELETE 忘记加 WHERE 条件
UPDATE users SET age = 30UPDATE users SET age = 30 WHERE id = 1;不加 WHERE 会更新/删除表中所有行,这是 SQL 新手最常犯的破坏性错误。养成先写 WHERE 再写 SET 的习惯。
6.字符串比较时忽略大小写敏感性
SELECT * FROM users WHERE name = 'alice' -- 期望匹配 'Alice'SELECT * FROM users WHERE name COLLATE NOCASE = 'alice';SQLite 默认比较是大小写敏感的(BINARY)。要忽略大小写需显式指定 COLLATE NOCASE 或使用 LIKE(默认不区分 ASCII 大小写)。
7.在 GROUP BY 中使用了未聚合的列
SELECT name, age, COUNT(*) FROM users GROUP BY ageSELECT age, COUNT(*) FROM users GROUP BY age;GROUP BY 后 SELECT 中的非聚合列必须出现在 GROUP BY 子句中,否则 SQLite 会随机取该列的值(取决于实现),结果不可预测。
8.误用 = 而非 == 或 IS 判断 NULL
SELECT * FROM users WHERE name = NULLSELECT * FROM users WHERE name IS NULL;SQL 中 NULL 表示未知值,任何与 NULL 的比较(=、<>)结果都是 NULL(假)。判断空值必须用 IS NULL 或 IS NOT NULL。
SELECT column1, aggregate_func(column2) FROM table_name WHERE condition GROUP BY column1 HAVING group_condition ORDER BY column3 LIMIT n;
column1分组或选择的列名aggregate_func聚合函数如 COUNT, SUM, AVGtable_name已创建的表名condition行级过滤条件group_condition分组后过滤条件column3排序依据列n返回行数上限表 sales 有 product, amount 两列。查询每种产品总销售额超过 100 的前 2 种产品:SELECT product, SUM(amount) AS total FROM sales GROUP BY product HAVING total > 100 ORDER BY total DESC LIMIT 2。假设数据:('A',50),('A',60),('B',30),('B',40),('C',200)。分组后 A=110, B=70, C=200;HAVING 过滤掉 B;排序后 C(200), A(110);LIMIT 2 返回 C 和 A。
本工具只接受手动输入或粘贴的 SQL 语句,不支持上传 .sql 文件。如果文件很大(超过几百 KB),浏览器可能因内存限制卡顿。建议用文本编辑器打开文件,复制建表语句和 INSERT 语句分批粘贴执行,每次执行不超过 10000 行。
SQLite 默认以 UTF-8 存储文本,如果粘贴的 SQL 语句本身不是 UTF-8 编码(比如从 Windows 记事本另存为 ANSI 的 .sql 文件),中文就会变成乱码。解决办法:把 SQL 语句用 UTF-8 编码重新保存,或用带编码转换的编辑器(如 VS Code、Notepad++)转成 UTF-8 再粘贴。本工具界面本身是 UTF-8,不负责转换外部编码。
查询结果默认只显示前 100 行,这是为了防止浏览器卡死。底部的「导出 CSV」按钮会导出全部查询结果(无行数限制),导出后再用 Excel 或文本编辑器查看完整数据。如果想在页面上看更多行,可以在 SQL 里加 LIMIT 500 自己控制返回条数。
最常见的原因是 INSERT 之后没有 COMMIT。SQLite 默认每个 INSERT 语句自动提交,但如果使用了 BEGIN...COMMIT 包裹多条 INSERT,必须手动执行 COMMIT 才能持久化。另外检查是否插到了不同表:建表语句和 INSERT 语句里的表名大小写要完全一致,SQLite 区分大小写。
不能。本工具是纯浏览器端运行,无法读取你电脑本地的 .db 或 .sqlite 文件。只能把 SQL 语句(建表、插入、查询)粘贴到输入框里执行。如果你有 .db 文件,建议先用 SQLite 命令行或 DB Browser 打开,把里面的结构用 .dump 导出成 SQL 文本,再粘贴到本工具里运行。
不能撤销。SQLite 不支持闪回或事务回滚已提交的 DDL(数据定义语言)操作。DROP TABLE 一旦执行,表结构和数据立即永久删除。建议在操作重要数据前先用 CREATE TABLE temp_xxx AS SELECT * FROM xxx 备份到临时表,或把建表语句先复制到记事本保存。
常见原因:表名拼写错误或大小写不一致(SQLite 对表名大小写敏感);表在当前数据库会话中还没创建(建表语句执行顺序不对);或者 JOIN 的表名之间忘了加逗号或 JOIN 关键字。建议先执行 .tables(本工具支持)查看当前所有表名,核对后再写 JOIN。
对于小于 10 万行的数据,速度差异几乎感觉不到。本工具底层用的是 WASM 编译的 SQLite,执行效率接近原生。但浏览器内存上限(通常 2GB)和 GC(垃圾回收)会导致超大结果集(百万行)的聚合查询比命令行慢 2-3 倍。如果处理几百万行数据,建议用命令行工具。
隐私保证所有计算与处理均在你的浏览器本地完成,输入数据不会上传服务器,也不会保存或共享。