0

Having trouble getting code below to work. The idea is to loop through 3 arrays parallelly and per iteration get 3 values to insert in database.

The insertion works, but the loops never end and inserts duplicate rows.

How should this be done?

/Paul

readarray rows1 < /tmp/tempfile1
readarray rows2 < /tmp/tempfile2
readarray rows3 < /tmp/tempfile3

for i in "${rows1[@]}"; do
    for j in "${rows2[@]}"; do
            for k in "${rows3[@]}"; do

mysql --user=$DB_USER --password=$DB_PASSWD $DB_NAME << EOF
INSERT INTO $TABLE (\`column1\`,\`column2\`,\`column3\`) VALUES ("$i","$j","$k");
EOF

done
done
done
John Kugelman
  • 349,597
  • 67
  • 533
  • 578
Paul Bergström
  • 253
  • 1
  • 2
  • 14
  • 2
    Nested loops are for cartesian products, not parallel loops. – Barmar Oct 28 '21 at 20:42
  • Tangentially, you want `readarray -t` otherwise you'll keep the newlines. – glenn jackman Oct 28 '21 at 20:44
  • This is calling mysql `n1 * n2 * n3` times. You'd be much better served building up a string (or file) containing all the inserts, and then you can invoke mysql once. – glenn jackman Oct 28 '21 at 20:46
  • See ["Iterate over two arrays simultaneously in bash"](https://stackoverflow.com/questions/17403498/iterate-over-two-arrays-simultaneously-in-bash) (you have three, but the same principle applies). – Gordon Davisson Oct 28 '21 at 20:48

1 Answers1

3

Loop over the array indexes, and use that to index all 3 arrays.

for index in "${!row1[@]}"; do
    i=${row1[index]}
    j=${row2[index]}
    k=${row3[index]}
    echo "INSERT INTO $TABLE (\`column1\`,\`column2\`,\`column3\`) VALUES ('$i','$j','$k');"
done | mysql --user=$DB_USER --password=$DB_PASSWD $DB_NAME

It might be better to create a CSV file from your input files, and use that with LOAD DATA INFILE, rather than doing a separate INSERT for each row.

Barmar
  • 741,623
  • 53
  • 500
  • 612