我正在尝试在 RoR 项目 MySql 数据库中创建函数和存储过程,我需要这些对象来从客户实际运行的旧平台导入历史数据......
嗯, 我在任务中创建了一堆 rake 函数,将它们链接到顶部预填充一些服务表并在尝试从旧版本网站开始数据导入之前操作所有迁移。
我也尝试过逐条处理记录,从源头读取,进行一些必要的计算以适应新平台的结构,并尝试将它们存储回新数据库中,但我发现了一些奇怪的行为数据库引擎。 我对一组有限的数据进行了测试(提取的记录限制为20行!),读取一切正常,但无法完成写入操作,它随机挂起(注意,根本没有错误)看起来真的要被冻结,卡点总是不同的(可能是记录1/20或3、5、11或者可能很少完整!)
所以,我改变了数据加载方式,直接使用mysql数据库内的存储过程进行操作,成功了!在不到 15 秒的时间内读取、处理和存储超过 30k 条记录!!
现在,当我们在生产服务器上上线时,将使这个自动的内部耙子任务开始运行......我希望避免任何手动操作,只是为了降低“人为”错误率......
第一步是在“新”mysql 数据库中创建函数和存储过程...
我有这个脚本(它在 mysql 工作台中运行良好,用于创建函数):
USE APERWeb_development;
DROP function IF EXISTS APERWeb_development.prov_id;
DELIMITER $$
USE APERWeb_development$$
CREATE DEFINER=`root`@`localhost` FUNCTION prov_id(prov char(2)) RETURNS bigint
READS SQL DATA
DETERMINISTIC
BEGIN
DECLARE pvid BIGINT;
SELECT p.id INTO pvid FROM APERWeb_development.provinces AS p WHERE p.Prov = prov;
RETURN pvid;
END$$
DELIMITER ;
如果我将其另存为“create-func.sql”并将其加载到 Rails 控制台中,效果也很好:
rails dbconsole < lib/sql/create-func.sql
为了从 rake 任务中完成此传递,我尝试过这种方式,逐行执行脚本
mysql_script = File.open("#{Rails.root}/lib/sql/create-func.sql").read
mysql_script.split('/;$/').each do |sql_statement|
ActiveRecord::Base.connection.execute(sql_statement)
end
但是运行 rake 任务,结果是这样的:
.......
rake aborted!
ActiveRecord::StatementInvalid: Mysql2::Error: 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 'DROP function IF EXISTS APERWeb_production.prov_id;
DELIMITER $$
USE APERWeb_d' at line 2
.......
如果有人知道更好的方法(纠正,任何“工作方法”!)从 rake 任务内部针对 mysql 数据库引擎执行这种脚本...... 任何建议将不胜感激!!
谢谢 弗朗西斯科
于2023年11月8日编辑 正如斯马西建议的那样......
要尝试这种方式:
create_prod_id_function =<<-SQL
USE APERWeb_development;
DROP function IF EXISTS APERWeb_development.prov_id;
DELIMITER $$
USE APERWeb_development$$
CREATE DEFINER=`root`@`localhost` FUNCTION prov_id(prov char(2)) RETURNS bigint
READS SQL DATA
DETERMINISTIC
BEGIN
DECLARE pvid BIGINT;
SELECT p.id INTO pvid FROM APERWeb_development.provinces AS p WHERE p.Prov = prov;
RETURN pvid;
END$$
DELIMITER ;
SQL
ActiveRecord::Base.connection.execute(create_prod_id_function)
结果又是一个错误:
......
ActiveRecord::StatementInvalid: Mysql2::Error: 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 'DROP function IF EXISTS APERWeb_development.prov_id;
DELIMITER $$
' at line 2
......
尝试将最后一行更改为...
ActiveRecord::Base.connection.exec_query(create_prod_id_function)
执行过程中出现完全相同的错误
还有其他建议吗??