Я плохо разбираюсь ни в одном из языков, поэтому, пожалуйста, потерпите меня. Я пытаюсь вытащить полную таблицу из 100 строк из удаленной базы данных MySQL в Google Sheet. Мне удалось разобраться во всех проблемах, которые у меня были с этим, но, наконец, я застрял. Кажется, ошибка «Недопустимое значение часа», которую я получаю из запроса SQL во время цикла, является основной проблемой.
Один из столбцов в базе данных MySQL - это «продолжительность», и, к сожалению, он может содержать длительности большечем 23:59:59. У меня есть доступ только для вызова процедуры и я не могу вносить изменения в таблицу. Я получаю
«недопустимое значение часа»
, когда строка достигает длительности более 24 часов (например, 70:00:00) . Я попытался упростить ситуацию, используя try-catch, чтобы пропустить ошибку и продолжить запись в Google Sheet, но затем я получаю
"количество столбцов в данных, не соответствующее числустолбцы в диапазоне. Данные имеют X, но диапазон имеет Y "
ошибка в последней строке sheet.getRange ().
Я также не могу понять, какпередать несколько операторов при выполнении запроса MySQL. Я пытался понять addBatch и пару других вещей, но это становится слишком сложным для меня. Может быть, есть более простое решение с запросом, или, может быть, это единственное решение, потому что оно могло бы работать, если бы я мог также добавить запрос CONCAT после запроса CALL, чтобы преобразовать столбец «duration» в строку перед тем, как данные попадут в цикл.
Код ниже был обновлен, чтобы включить решение:
function getData3(query, sheetName) {
//MySQL (MariaDB) connection and statements.
var user = '';
var userPwd = '';
var url = 'jdbc:mysql://remote.server.example.com/database_name';
var conn = Jdbc.getConnection(url, user, userPwd);
var stmt2 = conn.createStatement();
stmt2.setMaxRows(100);
var rs2 = stmt2.executeQuery('CALL spdAdminGetPIREPS(api_key)');
//Logger.log(rs2)
//Function to convert raw binary data to string to be used for durations >23:59:59.
function byteArrToString(byteArr){
return Utilities.newBlob(byteArr).getDataAsString();
}
//Setting up spreadsheet, results array, and cell range.
var doc = SpreadsheetApp.openById("id");
var sheet = doc.getSheetByName("sheet_name");
var results = [];
var cell = doc.getRange('a1');
var row = 0;
//Loop to get column names.
cols = rs2.getMetaData();
colNames = [];
for (i = 1; i <= cols.getColumnCount(); i++ ) {
//Logger.log(cols.getColumnName(i));
colNames.push(cols.getColumnName(i));
}
results.push(colNames);
//Loop to get row data, catch type errors due to duration >23:59:59 and fix it.
var rowCount = 1;
while(rs2.next()) {
curRow = rs2.getMetaData();
rowData = [];
for (i = 1; i <= curRow.getColumnCount(); i++) {
try {
rowData.push(rs2.getString(i));
} catch (e){
var bytes = rs2.getBytes(i);
rowData.push(byteArrToString(bytes)); //Pushes converted raw binary data as string using function defined above.
//Logger.log(JSON.stringify(rs2.getBytes(i))); //To see the raw binary data returned by getBytes() for durations >23:59:59 that throw an error.
continue;
}
}
results.push(rowData);
rowCount++;
}
//Write data to sheet.
sheet.getRange(1, 1, rowCount, cols.getColumnCount()).clearContent();
sheet.getRange(1, 1, rowCount, cols.getColumnCount()).setValues(results);
//Close result set, conn, and statement.
//Logger.log(results);
rs2.close();
stmt.close();
conn.close();
}
Я знаю два отдельных утверждения, и все выглядят нелепо, нокажется, что они работают, потому что я больше не получаю ошибку «нет базы данных» с запросом. Более простой однострочный JDBC-коннектор не работал для меня, поэтому текущий формат для подключения к серверу MySQL (Mariadb).
Если в таблице нет длительностей более 24 часов, код работаети успешно записывает всю таблицу в Google Sheet.
Для суммирования:
Если я не использую try-catch, цикл останавливается с ошибкой. Если я использую try-catch и continue, я получаю ошибку несоответствия количества столбцов.
Конечная цель - вызвать процедуру и записать всю таблицу в Google Sheet. Пропуск проблемных ячеек, с которыми я, вероятно, могу работать, но я бы определенно хотел получить все данные. Я мог бы упустить что-то тривиальное здесь, но любое направление или помощь будут оценены. Заранее спасибо!
ОБНОВЛЕНИЕ: Я нашел этот вопрос, на который дан ответ, но не могу понять, как использовать его в моем случае. Я думаю, что если я смогу пропустить несколько запросов, я смог бы отправить запрос CONCAT
после запроса CALL
, чтобы преобразовать столбец "duration" из Datetime
(я полагаю) в string
.
ОБНОВЛЕНИЕ 2: @ Решение TheMaster для try-catch
помогло пропустить проблемную ячейку и продолжить запись остальных. Я хотел бы найти способ преобразовать все длительности (весь столбец или те >23:59:59
) в string
, чтобы захватить все данные.
ОБНОВЛЕНИЕ 3: На основании предложений @ TheMaster, использование getInt()
вместо getString()
частично работает, возвращая час, но не минуты (например, возвращает 34
, если продолжительность 34:22:00
). Нужен способ конвертировать при использовании getString()
.
ОБНОВЛЕНИЕ 4 (отредактировано): Используя getBytes()
, возвращаемые значения:[51,52,58,52,56,58,48,48]
для 34:48:00
[51,55,58,48,48,58,48,48]
для 37:00:00
[56,55,58,48,48,58,48,48]
для 87:00:00
[49,53,49,58,51,53,58,48,48]
для 151:35:00
Что значит:[48,49,50,51,52,53,54,55,56,57,58]
соответствует [0,1,2,3,4,5,6,7,8,9,:]
. Как я могу включить это преобразование? Используя getLong()
, возвращаемые значения:34
для 34:48:00
, преобразовано в длительность -> 816:00
37
для 37:00:00
, преобразовано в длительность -> 888:00
87
для 87:00:00
, преобразовано в длительность -> 2088:00
ФИНАЛ ОБНОВЛЕНИЯ: @ Модифицированный ответ TheMaster решил проблему, получив необработанные двоичные данные и преобразовав их в строку на длительность >23:59:59
. Код выше был обновлен, чтобы отразить все модификации;это работает как написано выше.