Navicat 同步 MySQL 空间类型报错的根本原因是其不原生解析地理空间类型,将 POINT、POLYGON 等识别为 BLOB,导致建表缺失 SRID、插入报 Cannot convert string to geometry 等错误;推荐用 ST_AsText() 转 WKT 文本中转,再通过 ST_GeomFromText() 恢复,并显式指定 SRID。
同步 POINT、POLYGON 等空间类型时直接报错
navicat 本身不原生解析 mysql 的地理空间类型(如 point、linestring、geometry),它在结构同步或数据传输中会把这类字段识别为二进制 blob,导致建表语句缺失 srid、st_pointfromtext 等关键语法,或插入时抛出 cannot convert string to geometry 错误。
常见错误现象包括:
- 同步结构时报
Unknown column type 'geometry'或Invalid GIS data provided - 数据传输时某行卡住,日志显示
Truncated incorrect DOUBLE value - 目标表字段变成
VARBINARY(255),原始空间关系完全丢失
根本原因不是数据损坏,而是 Navicat 对空间类型的元数据读取能力有限——它依赖 INFORMATION_SCHEMA.COLUMNS,而 MySQL 5.7+ 才把空间类型作为一级类型暴露,旧版只返回 geometry 字符串且无精度/坐标系信息。
用 ST_AsText() 和 ST_GeomFromText() 做 WKT 文本中转
绕过二进制解析失败最稳的方式,是把空间值转成人类可读、跨版本兼容的 WKT(Well-Known Text)字符串再同步。这要求你在源库和目标库都支持标准函数,且字段允许临时改为 TEXT 类型。
实操步骤:
- 在源库导出前,用视图或临时表把空间字段转成文本:
SELECT id, ST_AsText(location) AS location_wkt FROM places - 目标表对应字段先设为
TEXT,同步完再执行:ALTER TABLE places MODIFY COLUMN location_wkt POINT SRID 4326 - 批量恢复空间值:
UPDATE places SET location = ST_GeomFromText(location_wkt, 4326) - 注意:WKT 不保留 SRID 元信息,
ST_GeomFromText()必须显式传入,否则默认为 0
这个方法对 MySQL 5.6+ 全适用,但会多一次全表扫描,大数据量建议加索引在 location_wkt 上加速更新。
升级 MySQL 到 8.0+ 并启用 ST_ 函数严格模式
MySQL 8.0 开始,空间函数全面重构,ST_AsText()、ST_GeomFromText() 等支持 SRID 绑定、坐标校验和更准的错误提示。Navicat 16.1+ 也相应增强了对 8.0 空间元数据的识别能力。
升级后需确认几件事:
- 检查
SHOW VARIABLES LIKE 'sql_mode'是否含STRICT_TRANS_TABLES,否则无效坐标(如POINT(999 999))会被静默截断 - 确认 Navicat 连接属性里勾选了
Use MySQL Native Password(尤其 MySQL 8.0 默认用caching_sha2_password) - 同步前手动执行
SELECT ST_SRID(location) FROM places LIMIT 1,确保所有空间字段有统一 SRID;混用不同 SRID 会导致ST_Distance()等函数结果异常
如果目标库暂时不能升级,至少把源库升级——你可以在源端用 ST_Transform() 统一投影,再导出 WKT,避免下游解析歧义。
跳过空间字段或用触发器拦截非法值
当同步仅用于业务数据比对、不关心地理精度时,最省事的是跳过空间字段。Navicat 不支持字段级黑名单,但可以利用其「保存为 SQL 文件」功能手动删减:
- 在同步向导最后一步选
Save as SQL File,打开生成的.sql - 删掉所有含
INSERT INTO ... (geom, ...)或UPDATE ... SET geom =的语句 - 运行前补一句:
SET SESSION sql_mode = 'NO_ENGINE_SUBSTITUTION';防止因空几何触发 strict 模式报错
若必须同步且数据质量差(比如存在 NULL、空字符串、坐标超出范围的 POINT),可在源表加触发器清洗:
DELIMITER $$
CREATE TRIGGER clean_geom_before_insert
BEFORE INSERT ON places
FOR EACH ROW
BEGIN
IF NEW.location IS NULL OR ST_IsValid(NEW.location) = 0 THEN
SET NEW.location = ST_GeomFromText('POINT(0 0)', 4326);
END IF;
END$$
DELIMITER ;
空间类型同步的复杂点不在语法,而在坐标系一致性、空值容忍度和 Navicat 缓存机制——它可能把上次同步失败时的半截元数据留在本地模型里,下次同步仍沿用,导致 SRID 被丢弃。遇到诡异问题,先删掉 Navicat 项目文件夹下的 *.ncx 模型缓存再试。











