Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/solr/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Mysql 谷歌应用程序脚本360秒超出时间限制解决问题_Mysql_Google Apps Script_Jdbc - Fatal编程技术网

Mysql 谷歌应用程序脚本360秒超出时间限制解决问题

Mysql 谷歌应用程序脚本360秒超出时间限制解决问题,mysql,google-apps-script,jdbc,Mysql,Google Apps Script,Jdbc,编码将GoogleSheets数据导入MySQL表,并尝试绕过360秒执行限制。我使用的是批处理执行,即使这样也无助于导入具有较大数据的工作表。在谷歌应用程序脚本中,有没有一种方法可以在350秒或记录数(以先到者为准)时中断,并让下一次执行从中断的地方重新开始 var address = 'database_IP_address'; var rootPwd = 'root_password'; var user = 'user_name'; var userPwd = 'user_passwor

编码将GoogleSheets数据导入MySQL表,并尝试绕过360秒执行限制。我使用的是批处理执行,即使这样也无助于导入具有较大数据的工作表。在谷歌应用程序脚本中,有没有一种方法可以在350秒或记录数(以先到者为准)时中断,并让下一次执行从中断的地方重新开始

var address = 'database_IP_address';
var rootPwd = 'root_password';
var user = 'user_name';
var userPwd = 'user_password';
var db = 'database_name';

var root = 'root';
var instanceUrl = 'jdbc:mysql://' + address;
var dbUrl = instanceUrl + '/' + db;

function googleSheetsToMySQL() {   

  var RecId;
  var Code;
  var ProductDescription;
  var Price;

  var dbconnection = Jdbc.getConnection(dbUrl, root, rootPwd);
  var statement = dbconnection.createStatement();
  var googlesheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('product'); 
  var data = googlesheet.getDataRange().getValues();  

dbconnection.setAutoCommit(false)

for (var i = 1; i < data.length; i++) {
RecId = data[i][0];
Code = data[i][1];
ProductDescription = data[i][2];
Price = data[i][3];

var sql = "{call [dbo].[sp_googlesheetstotable](?,?,?,?)}";
statement = dbconnection.prepareCall(sql);
statement.setString(1, RecId);
statement.setString(2, Code);
statement.setString(3, ProductDescription);
statement.setString(4, Price);
statement.addBatch()
statement.executeBatch()
}

dbconnection.commit()
var address='database_IP_address';
var rootPwd='root_password';
var user='user_name';
var userPwd='user_password';
var db='数据库名称';
变量根='根';
var instanceUrl='jdbc:mysql://'+地址;
var dbUrl=instanceUrl+'/'+db;
函数googleSheetsToMySQL(){
变量RecId;
var代码;
var产品描述;
var价格;
var dbconnection=Jdbc.getConnection(dbUrl、root、rootPwd);
var statement=dbconnection.createStatement();
var googlesheet=SpreadsheetApp.getActiveSpreadsheet().getSheetByName(“产品”);
var data=googlesheet.getDataRange().getValues();
dbconnection.setAutoCommit(false)
对于(变量i=1;i
在这种情况下,我要做的是创建一个空表,允许我存储数据库的起始ID,然后我在脚本上设置一个触发器,使其每10分钟运行一次。为此,只需单击GAS editor中播放按钮左侧的小时钟图标

比如说,我有一个包含1000条记录的数据库,每次触发器运行脚本时,我都要提取100条记录。我会创建一个工作表,比如说“Sheet1”,并将
0
最初放在单元格A1中

在GAS中,我会让脚本在每次运行时获得A1的值:

var ss = SpreadsheetApp.openById("XXXXX");
var sheet = ss.getSheetByName("Sheet1");
var a1 = sheet.getRange("A1").getValue();
var a1 = parseInt(a1);
var last_row = a1+100;
那么您的SQL语句应该类似于以下查询:

"SELECT * FROM `table` WHERE `id` >= '"+a1+"' AND `id` < '"+last_row+"'"

当脚本再次运行时(通过触发器),它将接受新值
100
,添加
100
(使其成为
200
),查询表中大于或等于100和小于200的结果,并相应地显示它们。

是的,只要问题是由循环进程引起的,这是很容易做到的。如果没有循环,则会有点棘手;如果是单个操作,则不可能。幸运的是,您的操作似乎是第一种

本质上,我们首先需要知道脚本何时开始,所以我们需要

var startTime = new Date();
获取开始时间。接下来,我们需要检查每次迭代后的时间,因此在
for
循环中,我们会添加(我个人会先声明变量,这里没有var,但这只是我的风格偏好)

这告诉我们scrip已经执行了多长时间。如果你想变得有趣,你可以检查你的循环平均花费了多长时间,并检查是否还有足够的时间,但一般来说,给它一些时间来执行截断就足够了。然后你需要做一些事情。首先,你希望通过使用

PropertiesService.getScriptProperties().setProperty(key, value)
其中,
key
是属性的名称,
value
是您希望存储的对象。如果它是一个数组,请确保使用
JSON
对其进行字符串化。您还需要创建一个触发器,从停止的位置触发。请阅读更多相关内容。当然,您可以先创建一个触发器,然后在此处存储属性没问题

以下是在我的脚本中执行此段的函数示例:

function autoTrigger(passProperties, sysKeys) {  
  var sysProperties = new systemProperties();

  if (typeof sysKeys === 'undefined' || sysKeys === null) {
    sysKeys = new systemKeys();
  }

  var triggerID = ScriptApp.newTrigger('stateRebuild')
                           .timeBased()
                           .after(60000)
                           .create()
                           .getUniqueId();

  Logger.log('~~~ RESTART TRIGGER CREATED ~~~');

//-------------------------------------------------------------------------------------------------
// In order to properly retrieve the time later, it is stored in milliseconds
  passProperties.timeframe.start = passProperties.timeframe.start.getTime();
  passProperties.timeframe.end = passProperties.timeframe.end.getTime();
//-------------------------------------------------------------------------------------------------

//-------------------------------------------------------------------------------------------------
// Properties are stored in User Properties using JSON
  PropertiesService.getUserProperties()
                   .setProperty(sysKeys.startup.rebuildCache, JSON.stringify(passProperties));
//-------------------------------------------------------------------------------------------------

  Logger.log('~~~ CURRENT PROPERTIES STORED ~~~');
  return triggerID;
}
现在,您必须停止脚本。您可以使用
throw
执行此操作。我是这样做的:

if (typeof execProperties.nextPageId !== 'undefined' && execProperties.nextPageId) {
  if (isTimeUp(startTime, Math.max(averageExec, execTime)) === true) {
    autoTrigger(execProperties);
    throw new Error('Script reseting');
  }
}
我会留一分钟以防万一

function isTimeUp(start, need) {  
  var cutoff = 500000 // in miliseconds (5 minutes)
  var now = new Date();
  return cutoff - (now.getTime() - start.getTime()) < need; 
}
函数isTimeUp(启动,需要){
var截止=500000//毫秒(5分钟)
var now=新日期();
返回截断-(now.getTime()-start.getTime())
请注意,在我的例子中,脚本没有调用相同的函数,因为有一个不同的启动过程。您需要做的是调整脚本以获取存储在属性中的值。您可以进一步读取属性。因此,如果您的脚本可以找到属性,您需要做的是删除触发器,检索var启用并清除所有这些属性,然后一直跳到循环。这可以通过几个
if
语句轻松完成

希望这有帮助

if (typeof execProperties.nextPageId !== 'undefined' && execProperties.nextPageId) {
  if (isTimeUp(startTime, Math.max(averageExec, execTime)) === true) {
    autoTrigger(execProperties);
    throw new Error('Script reseting');
  }
}
function isTimeUp(start, need) {  
  var cutoff = 500000 // in miliseconds (5 minutes)
  var now = new Date();
  return cutoff - (now.getTime() - start.getTime()) < need; 
}