sql >> Database >  >> RDS >> Mysql

Batch-invoeging met tabel met veel kolommen met Anorm

Ik ga voor optie B. Ik ben niet erg bekend met BatchSql sinds de laatste keer dat ik het controleerde, voert het gewoon een bootlading met query's achter elkaar uit, wat erg traag is. Ik raad aan om alles in één query samen te voegen. Het is iets omslachtiger, maar veel sneller om een ​​enkele zoekopdracht met duizend invoegingen uit te voeren dan duizend enkele invoegingen.

Laten we voor het gemak zeggen dat u Seq . heeft van

case class Test(val1: Int, val2: Option[Long], val3: Option[String])

Dan zou je je zoekopdracht als volgt kunnen opbouwen:

val values: Seq[Test] = Seq(....)

/* Index your sequence for later, to map to inserts and parameters alike */
val indexedValues = values.zipWithIndex

/* Create the portion of the insert statement with placeholders, each with a unique index */
val rows = indexValues.map{ case (value, i) =>
    s"({val1_${i}}, {val2_${i}}, {val3_${i}})"
}.mkString(",")

/* Create the NamedParameters for each `value` in the sequence, each with their unique index in the token, and flatten them together */
val parameters = indexedValues.flatMap{ case(value, i) =>
    Seq(
        NamedParameter(s"val1_${i}" -> value.val1),
        NamedParameter(s"val2_${i}" -> value.val2),
        NamedParameter(s"val3_${i}" -> value.val3)
    ) 
}

/* Execute the insert statement, applying the aggregated parameters */
SQL("INSERT INTO table1 (col1, col2, col3) VALUES " + rows)
    .on(parameters: _ *)
    .executeInsert()

Opmerkingen:

U moet die values . controleren is niet leeg voordat u doorgaat, omdat het een ongeldige SQL-instructie zou genereren als dat wel het geval was.

Afhankelijk van het aantal rijen en kolommen dat u invoegt, zullen uiteindelijk de token-parsers die de voorbereide instructie hebben gemaakt, vertragen van het enorme aantal tokens dat moet worden geparseerd (en de tekenreeksgrootte). Ik heb dit opgemerkt na een paar honderd rijen met meerdere kolommen. Dit kan enigszins worden verholpen. Omdat Scala een sterk getypte taal is, is Int en Long vormen geen bedreiging voor SQL-injectie. U kunt uw SQL-instructies voorbereiden met behulp van tekenreeksinterpolatie/aaneenschakeling voor alleen die kolommen en de onveilige kolommen binden met NamedParameter normaal gesproken. Dat zou het aantal tokens verminderen dat moet worden geparseerd.



  1. #1136 - Kolomtelling komt niet overeen met waardetelling op rij 1

  2. Geen toegang tot het veld via de slaapstand in de Oracle-database op verschillende gebruikersruimten met alleen geselecteerde privileges

  3. Een kolom hernoemen in SQL

  4. hoe correct if-statement te gebruiken postgresql