问题:

我试图将新列添加到具有数千万行的表中,而不会阻止它。

我知道这里有一些选项,并且我已经给ALTER TABLE尝试了NULL值和默认值,但是这花费了很长时间(不可行)并锁定了表。

因此,我试图编写一个迁移脚本,该脚本将原始表的结构复制到新表中,将新列添加到该新表中,然后将旧表数据缓慢迁移到新表中。

我的问题是与Knex有关,尽管在数据副本上。

我正在本地测试,以下查询在Sequel Pro中的MySQL 5.6.34版中运行完全正常,但在Knex中却得到了You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '

knex.schema.raw(`
  SELECT @prevMaxIdMovedRecord;
  SELECT @newMaxIdMovedRecord;
  SELECT maxIdMoved FROM migration_status
    ORDER BY maxIdMoved DESC
    INTO @prevMaxIdMovedRecord;

  INSERT IGNORE INTO table_copy (field1, newField1)
  SELECT t.field1, 1 FROM table t
    WHERE t.id BETWEEN @prevMaxIdMovedRecord AND @prevMaxIdMovedRecord + 50000;

  SELECT id FROM table_copy
    ORDER BY id DESC
    LIMIT 1
    INTO @newMaxIdMovedRecord;

  INSERT INTO migration_status (maxIdMoved)
    VALUES (@newMaxIdMovedRecord);

  DELIMITER ;
`)


这里有什么专家可以协助您吗?我看不到Knex允许您在Knexfile.js中指定MySQL版本,我想知道语法版本之间是否可能不匹配。我在新表等方面的所有其他命令都可以正常工作...

谢谢

最佳答案

默认情况下,MySQL驱动程序在单个查询中将不接受多个语句。您可以用一个简单的Node程序演示这一点:

const mysql = require('mysql')

connection = mysql.createConnection({
    host: 'localhost',
    user: 'youruser',
    password: 'yourpassword',
    database: 'yourdb',
    multipleStatements: true
})
connection.connect()

connection.query('SELECT 1+1; SELECT 2+2;', function(err, results) {
    if (err) {
        throw err
    }

    console.log(results[0], results[1])
})

connection.end()


如果将multipleStatements设置为false,则应该看到错误。尽管multipleStatements可以通过knexfile.js传递给驱动程序,

 {
    client: "mysql",
    connection: {
        // ... other options ...
        multipleStatements: true
    }
}


并且您可以尝试这样做,我建议您使用事务,因为在一个大表上像这样在一个查询中执行多条语句充其量似乎很脆弱。有关简介,请参见docs

10-04 22:25
查看更多