[SQLite]Prepared Statements en union hoe te combineren

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • Gomez12
  • Registratie: Maart 2001
  • Laatst online: 17-10-2023
Voor een sqlite project ben ik momenteel aan het kijken hoe de code te verbeteren.

Nu zou ik heel graag prepared statements gebruiken, maar ik loop even tegen een probleempje aan.

De applicatie / sqlitekoppeling kent geen daadwerkelijke transacties, daarom wordt er zoveel mogelijk in 1 query gestopt (query's zijn duur)

Maar nu is er bijv een multiple insert query die als volgt is :
SQL:
1
2
3
4
5
6
insert into tablea (a,b)
select "val1" as a, "val2" as b
union
select "val3","val2"
union 
select "val5","val2"

versimpelde code

En na wat meetwerk heb ik situaties gezien waarin er dus rustig 1000 unions plaatsvinden in deze query (string concatination for president ;)). Even voor de grap die 1000 unions uitgeschreven naar 1000 prepared statements en die tegen de database gerund, maar dan ga je van millisecondes opeens naar minuten vanwege index-bijwerkingen etc.

Hoe kan je zo'n soort query via prepared statements schrijven? Want ik weet van te voren niet echt iets, je krijgt een array toegeworpen vanuit de applicatie en die moet opgeslagen worden

Acties:
  • 0 Henk 'm!

  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
Geen idee, maar werkt zoiets (uit de losse pols) niet?

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
myArray = [["a", "b"], ["c", "d"], ["e", "f"], ["g", "h"]];

cmd = new SqlCmd();
qry = 'insert into tablea (a,b) values '

for (int i=0; i<myArray.length; i++) {
  qry += 'select @val' + i + '_a as a, @val' + i + '_b as b';
  if (i < myArray.length - 1) qry += ' union '
  cmd.Parameters.Add("@val' + i + '_a", myArray(i, 0);
  cmd.Parameters.Add("@val' + i + '_b", myArray(i, 1);
}

cmd.Query = qry;
cmd.Execute();


versimpelde code :P

[ Voor 10% gewijzigd door RobIII op 21-05-2013 20:53 . Reden: Values vergeten :P ]

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


Acties:
  • 0 Henk 'm!

  • P.O. Box
  • Registratie: Augustus 2005
  • Niet online
disclaimer: geen ervaring met SQLlite
in hoevrre is de code versimpeld? zijn de select statement eigenlijk selects uit een andere tabel, of zijn het allemaal echt waarde die je als parameter wilt meegeven? want in dat laatste geval lijkt :
SQL:
1
2
insert into tablea (a,b) 
VALUES ("val1", "val2"), ("val3", "val2"), ("val4", "val2");

een oplossing

Acties:
  • 0 Henk 'm!

  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
P.O. Box schreef op dinsdag 21 mei 2013 @ 19:39:
disclaimer: geen ervaring met SQLlite
in hoevrre is de code versimpeld? zijn de select statement eigenlijk selects uit een andere tabel,
Volgens mij probeert 'ie een array "in 1 actie" weg te schrijven (ik zal 't geen transactie noemen :P )
Gomez12 schreef op dinsdag 21 mei 2013 @ 19:13:
Want ik weet van te voren niet echt iets, je krijgt een array toegeworpen vanuit de applicatie en die moet opgeslagen worden
P.O. Box schreef op dinsdag 21 mei 2013 @ 19:39:
of zijn het allemaal echt waarde die je als parameter wilt meegeven? want in dat laatste geval lijkt :
SQL:
1
2
insert into tablea (a,b) 
VALUES ("val1", "val2"), ("val3", "val2"), ("val4", "val2");

een oplossing
Dat kan, als ik de documentatie goed lees, ook. [edit] En een korte test bevestigt dat :P [/edit] Dat kun je de union uit mijn voorbeeld simpelweg achterwege laten en er een komma van maken.
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
myArray = [["a", "b"], ["c", "d"], ["e", "f"], ["g", "h"]];

cmd = new SqlCmd();
qry = 'insert into tablea (a,b) values '

for (int i=0; i<myArray.length; i++) {
  qry += '(@val' + i + '_a as a, @val' + i + '_b as b)';
  if (i < myArray.length - 1) qry += ', '
  cmd.Parameters.Add("@val' + i + '_a", myArray(i, 0);
  cmd.Parameters.Add("@val' + i + '_b", myArray(i, 1);
}

cmd.Query = qry;
cmd.Execute();


Overigens, SQLite kent wél transacties, dus weet je heel zeker dat dit onmogelijk is of wordt gemaakt (door die applicatie ofzo)?

[ Voor 7% gewijzigd door RobIII op 21-05-2013 21:02 ]

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


Acties:
  • 0 Henk 'm!

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 04:30
Gomez12 schreef op dinsdag 21 mei 2013 @ 19:13:
De applicatie / sqlitekoppeling kent geen daadwerkelijke transacties, daarom wordt er zoveel mogelijk in 1 query gestopt (query's zijn duur)
SQL statements zijn niet duur — transacties wel.

De juiste plek om het probleem op te lossen is dus om je insert statements te bundelen in één transactie. Statements met duizenden paramaters bouwen is maar een onhandige kludge om meerdere updates in één transactie te stoppen, en is waarschijnlijk niet eens erg snel (aangezien je een idioot grote statement met debiel veel parameters moet opbouwen).