【问题标题】:Creating SQL that's compatible with both SQLite and mysql with AUTO_INCREMENT使用 AUTO_INCREMENT 创建与 SQLite 和 mysql 兼容的 SQL
【发布时间】:2017-04-22 21:47:10
【问题描述】:

我有一个 mysql .sql 文件,我正在尝试使用 sqlite 内存数据库进行测试,使用相同的文件。

如果用户不存在则创建表 ( user_id INTEGER PRIMARY KEY AUTO_INCREMENT,

导入时出现错误

  • SQLITE_ERROR:靠近“AUTO_INCREMENT”:语法错误

这是documented here:

在 SQLite 中,声明为 INTEGER PRIMARY KEY 的列将自行自动递增。去掉 AUTOINCREMENT 关键字,然后试试。

我无法删除 AUTOINCREMENT,因为它是 mysql 所必需的。有什么建议吗?

【问题讨论】:

  • 尝试手动为多个数据库创建 SQL 令人抓狂,而且您最终会使用最小公分母。出于这个和其他原因,您最好使用 SQL 生成器库,一个好的生成器库会为您处理 SQL 方言。例如,Javascript 有Knex.js
  • @Schwern 我们已经在使用 Knew。我们拥有的一个 SQL 文件是在应用程序第一次启动时创建架构的文件。也许我们也应该为此迁移到 Knex。

标签: mysql sql sqlite


【解决方案1】:

我有一个解决方案。

MySQL 支持一种特殊的注释语法,当您想使用在较新版本的 MySQL 但不适用于较早版本的语法时。也许你已经在 mysqldump 输出中看到过这种东西:

CREATE TABLE `products` (
  `product_id` int NOT NULL,
  PRIMARY KEY (`product_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
/*!40101 SET character_set_client = @saved_cs_client */;

注意注释中的字符集语句,带有一个有趣的字符串!40101,意思是“如果MySQL的版本低于4.1.1,则忽略该字符串作为注释,否则将其作为SQL的一部分执行声明。”

而在 SQLite 中,注释的内部始终只是一个注释。

所以你可以这样定义你的表:

CREATE TABLE IF NOT EXISTS users ( 
  user_id INTEGER PRIMARY KEY /*!40101 AUTO_INCREMENT */,
   . . .

SQLite 将忽略 AUTO_INCREMENT,但 MySQL 会使用它,前提是您使用的是 4.1.1 或更高版本(几乎可以肯定)。

我刚刚使用 SQLite 3.8.5 和 MySQL 8.0.0-dmr 对此进行了测试,并且创建表在这两种情况下都有效。

INTEGER 可以,因为它是 MySQL 中 INT 的同义词。不要在 SQLite 中使用 INT,因为主键列不会自动递增,除非你真的使用类型 INTEGER

永远不要担心 MySQL 中 INT 的参数,比如 INT(11),这个数字并不意味着什么重要。

【讨论】:

  • 这解决了这个问题......并让我直接进入我们文件中的下一个问题,ENUM。我认为更好的长期解决方案确实是从静态 SQL 文件迁移到 Knex 迁移。
  • @ripper234 请参阅 stackoverflow.com/questions/362044/… 了解我对 ENUM 的看法。
  • 我同意...目前我只是想将 sql 语句迁移到 knex 而不改变它周围的整个世界:) 一次重构一个。
猜你喜欢
  • 2016-11-08
  • 2012-03-03
  • 2016-07-27
  • 1970-01-01
  • 2021-08-07
  • 1970-01-01
  • 2018-12-13
  • 2010-09-10
  • 2013-07-13
相关资源
最近更新 更多