Autor Téma: UniDac batch Insert  (Přečteno 342 krát)

Offline PetrB0

  • Nováček
  • *
  • Příspěvků: 33
  • Karma: 1
    • Verze Delphi: Delphi XE2
UniDac batch Insert
« kdy: 10-10-2018, 16:05:42 »
Ahoj,
používám komponenty UniDac pro přístup k Oracle.
Pro import dat jsem vytvořil paměťovou tabulku vtSeznam:TVirtualTable (má stejná pole jako cílová tabulka), kterou naplňuji importovanými daty.
Poté chci tato data přenést do databáze (do tabulky utCil:TUniTable, která má vytvořená pole odpovídající tabulce v DB). Na stránkách devart jsem našel tento příklad : https://www.devart.com/unidac/docs/batchops.htm, který jsem si upravil ke svému účelu. Podle příkladu jsem  přenosu použil QPrenosDat:TUniQuery

Rutina vypadá takto:
Kód: Delphi [Vybrat]
  1. Var
  2.      S : String;
  3.      I : Integer;
  4.      J : Integer;
  5. Begin
  6.   vtSeznam.First;
  7.   S:='';
  8.  
  9.   for I := 0 to utCil.FieldCount-1 do   //Vytvoří seznam parametrů (:Par0,...,:ParN)
  10.     S:=Spoj(S,Format(':Par%d',[I]),',');
  11.  
  12.   qPrenosDat.SQL.Text:='insert into '+utCil.TableName+' values ('+S+')';
  13.  
  14.   for I := 0 to utCil.FieldCount-1 do  //Parametrům dej správné typy
  15.    qPrenosDat.Params[I].DataType:=utCil.Fields[I].DataType;
  16.  
  17.   qPrenosDat.Params.ValueCount:=vtSeznam.RecordCount;
  18.   for I := 0 to qPrenosDat.Params.ValueCount-1 do
  19.    begin
  20.     for J := 0 to qPrenosDat.ParamCount-1 do
  21.      if vtSeznam.Fields[J].isNull then qPrenosDat.Params[J][I].isNull:=True
  22.                                            Else qPrenosDat.Params[J][I].Value:=vtSeznam.Fields[J].Value;
  23.     vtSeznam.Next;
  24.    end;
  25.   qPrenosDat.Execute(qPrenosDat.Params.ValueCount);
  26.  

Pokud chci převést jeden řádek (nastavím qPrenosDat.Params.ValueCount:=1), tak to funguje. V případě, že načtu celou dávku (cca 32T řádků) a dám její přenos, nebo načtu celou a chci přenést pouze jeden záznam ( qPrenosDat.Execute(1); ), tak mi to hodí chybu "Can not access a DML array as a single value".
O této chybě jsem našel na netu cca 4 roky starou zmínku. Problém byl v použití této funkce spolu s TUniSQLMonitor. Při jeho vypnutí k chybě nedocházelo. Já jej ovšem nepoužívám.
Nevíte někdo, v čem by mohla být chyba? Mě to připadá, že namísto dávky to na celá data přistupuje jako na jeden řádek, ale nenašel jsem nikde, jak to nastavit.

Díky

Offline Stanislav Hruška

  • Padawan
  • ******
  • Příspěvků: 3651
  • Karma: 35
    • Verze Delphi: XE7 professional
Re:UniDac batch Insert
« Odpověď #1 kdy: 10-10-2018, 19:33:35 »
UniDac nepoužívam a tak si môžem len tipnúť. Skúsil si aj tento zápis podľa návodu?
Kód: Delphi [Vybrat]
  1. // insert first 500 rows
  2. UniQuery1.Execute(500, 0);
  3. // insert next 500 rows
  4. UniQuery1.Execute(500, 500);
Alebo to rozsekať na niekoľko častí. Dajme tomu po 10 000 riadkoch. 32T riadkov je nejako veľa.
Delphi XE7, FireBird
Expert na kladenie nejasne formulovaných otázok.

Offline Stanislav Hruška

  • Padawan
  • ******
  • Příspěvků: 3651
  • Karma: 35
    • Verze Delphi: XE7 professional
Re:UniDac batch Insert
« Odpověď #2 kdy: 10-10-2018, 19:36:30 »
Hm, ja som predpokladal, že 32T = 32 tera. Ale to môže byť aj 32 tisíc :). Ale aj tak...
Delphi XE7, FireBird
Expert na kladenie nejasne formulovaných otázok.

Offline PetrB0

  • Nováček
  • *
  • Příspěvků: 33
  • Karma: 1
    • Verze Delphi: Delphi XE2
Re:UniDac batch Insert
« Odpověď #3 kdy: 10-10-2018, 22:32:26 »
Právě že jsem zkoušel:
1) načíst komplet data, převést vše  - hodilo chybu (Execute(32000))
2) načíst komplet data, převést jeden řádek - hodilo chybu (Execute(1))
3) načíst první řádek a převést jej - proběhlo....

Tak nevím. Zatím jsem to obešel přes VirtualSQL, které umí poslat data mezi dvěma tabulkami, ale to je relativně pomalé. Asi 1000ř/s, ale moc jsem to zatím neladil. U toho Batch přenosu slibovali cca 30tis/s.

Díky za reakci

Offline Delfin

  • Guru
  • *****
  • Příspěvků: 1367
  • Karma: 57
  • SW konzultant
    • Verze Delphi: 2009, Tokyo
Re:UniDac batch Insert
« Odpověď #4 kdy: 11-10-2018, 01:41:57 »
Proc nevyuzit TCRBatchMove?
I'm a soldier, so don't panic! I know the underground! I like WTFPL license! No more Google, go duck, go!

Offline PetrB0

  • Nováček
  • *
  • Příspěvků: 33
  • Karma: 1
    • Verze Delphi: Delphi XE2
Re:UniDac batch Insert
« Odpověď #5 kdy: 11-10-2018, 10:58:34 »
Asi to tak udělám, ale zarazilo mne, že mi nefunguje ten jejich příklad.

Offline PetrB0

  • Nováček
  • *
  • Příspěvků: 33
  • Karma: 1
    • Verze Delphi: Delphi XE2
Re:UniDac batch Insert
« Odpověď #6 kdy: 11-10-2018, 22:40:30 »
Tak mám variantu jak s TVirtualSQL, tak i s TCRBatchMove. Obojí trvá prakticky stejně, cca 35s.

Díky za reakce.

Pb

Offline Delfin

  • Guru
  • *****
  • Příspěvků: 1367
  • Karma: 57
  • SW konzultant
    • Verze Delphi: 2009, Tokyo
Re:UniDac batch Insert
« Odpověď #7 kdy: 11-10-2018, 23:58:00 »
Tak mám variantu jak s TVirtualSQL, tak i s TCRBatchMove. Obojí trvá prakticky stejně, cca 35s.

Díky za reakce.

Pb

TCRBatchMove je presne pro tuto ulohu.
I'm a soldier, so don't panic! I know the underground! I like WTFPL license! No more Google, go duck, go!

 

S rychlou odpovědí můžete používat BB kódy a emotikony jako v běžném okně pro odpověď, ale daleko rychleji.

Jméno: E-mail:
Ověření:
Datový typ v Delphi, který má True a False: