如何将多行动态插入Google Cloud Spaner

时间:2018-12-21 16:39:36

标签: node.js google-cloud-platform bulkinsert google-cloud-spanner

在下面的代码片段中,插入具有静态值的多行。如何在一个事务中将多行动态插入到扳手数据库中?

 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 + ")";

2 个答案:

答案 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语法外,使用绑定参数还具有其他优势,即能够对同一插入语句(具有不同绑定值)的多次执行使用相同的缓存查询计划。