在下面的代码片段中,插入具有静态值的多行。如何在一个事务中将多行动态插入到扳手数据库中?
function writeUsingDml(instanceId, databaseId, projectId) {
const {Spanner} = require('@google-cloud/spanner');
const spanner = new Spanner({
projectId: projectId,
});
const instance = spanner.instance(instanceId);
const database = instance.database(databaseId);
database.runTransaction(async (err, transaction) => {
if (err) {
console.error(err);
return;
}
try {
const rowCount = await transaction.runUpdate({
sql: `INSERT Singers (SingerId, FirstName, LastName) VALUES
(12, 'Melissa', 'Garcia'),
(13, 'Russell', 'Morales'),
(14, 'Jacqueline', 'Long'),
(15, 'Dylan', 'Shaw')`,
});
console.log(`${rowCount} records inserted.`);
await transaction.commit();
} catch (err) {
console.error('ERROR:', err);
} finally {
database.close();
}
});
}
现在,我将按如下所示动态插入一行,并将其扩展到多行
var sqlString = "Insert " + tName
var cNames = "( "
var cValues = "( "
for(var col in cols) {
cNames = cNames + col + ", " ;
const cValue = cols[col];
if (typeof cValue == 'string' || cValue instanceof String){
cValues = cValues + "'" + cValue + "', "
}else{
cValues = cValues + cValue + ", ";
}
}
return sqlString + cNames + ") values " + cValues + ")";
答案 0 :(得分:1)
如果要插入许多行,则使用BatchTransaction.insert可能会更容易 https://cloud.google.com/nodejs/docs/reference/spanner/2.1.x/BatchTransaction#insert
database.runTransaction(async (err, transaction) => {
if (err) {
console.error(err);
return;
}
try {
var itemsToInsert = [
{ SingerId: 12, FirstName: 'Mellissa', LastName: 'Garcia' },
{ SingerId: 13, FirstName: 'Russell', LastName: 'Morales' },
{ SingerId: 14, FirstName: 'Jacqueline', LastName: 'Long' },
{ SingerId: 15, FirstName: 'Dylan', LastName: 'Shaw' },
]
transaction.insert('Singers', itemsToInsert);;
await transaction.commit();
console.log(`${itemsToInsert.length} records inserted.`);
} catch (err) {
console.error('ERROR:', err);
} finally {
database.close();
}
});
但是,如果要使用DML,则可以以编程方式编写SQL语句。下面将构建插入语句。我没有运行您的版本,但我认为它可能存在与尾随逗号有关的语法错误。
function buildSqlInsert(tableName, columnNames, rows) {
var sqlString = "INSERT " + tableName + " (" + columnNames.join(', ') + ") VALUES \n";
// add each row being careful to match the column order with columnNames
rows.forEach(row => {
sqlString += "(";
columnNames.forEach(columnName => {
var columnValue = row[columnName]
// strings should be quoted
if (typeof columnValue == 'string' || columnValue instanceof String) {
columnValue = "'" + columnValue + "'";
}
sqlString += columnValue + ", ";
});
// trim added chars.
sqlString = sqlString.substring(0, sqlString.length - 2);
sqlString += "),\n"
});
// trim added comma/newline
sqlString = sqlString.substring(0, sqlString.length - 2);
return sqlString
}
insertStatement = buildSqlInsert('Singers', Object.keys(itemsToInsert[0]), itemsToInsert)
const rowCount = await transaction.runUpdate({
sql: insertStatement,
});
答案 1 :(得分:0)
您还可以将要插入的行绑定到结构数组参数,并在插入语句中使用它,如下所示:
INSERT INTO Singers(SingerId, FirstName, LastName)
SELECT * FROM UNNEST(@struct_array_param)
其中@struct_array_param
是包含STRUCTS
(元组)数组的绑定参数。除了简洁,安全的SQL语法外,使用绑定参数还具有其他优势,即能够对同一插入语句(具有不同绑定值)的多次执行使用相同的缓存查询计划。