Запись данных в Firebird, получение типизированных данных

Алексей Лашин
Дата: 06.01.2013 17:59:22
Подскажите, пожалуйста.
вопрос в следующем: долго записываются данные в FB, сразу оговорюсь, необходимо заливать таблички в среднем по 300 000 записей из DBF в FB.
выкладываю код, не судите строго:
Алексей Лашин
Дата: 06.01.2013 18:02:56
Local lcSQLStringConnection, lnSQLHandleConnection
lcSQLStringConnection=""
lnSQLHandleConnection=0

lcSQLStringConnection="Driver={Firebird/InterBase(r) driver};Dbname=D:\dbTfoms22\TEST.FDB;CHARSET=WIN1251;PWD=10203040;UID=SYSDBA;Role=RDB$ADMIN;Client=D:\dbTfoms22\fbclient.dll;"

lnSQLHandleConnection=Sqlstringconnect(lcSQLStringConnection,.t.)

If lnSQLHandleConnection>0
Local lcSQL, ldDr


Create Table "D:\akkb\err.dbf" (nomrec numeric(20,2), errrec numeric(20,0))
Use "D:\akkb\rr.dbf" In 0 Again Alias rrlocal Exclusive

Local lnErr
lnErr=0

lcSQL=""
lcSQL='insert into RR (ku,kod_fil,kpl,dn,dk,datapost,datapostst,fam,im,ot,dr,koddoc,'+;
'sdoc,ndoc,is_chld,fam2,im2,ot2,dr2,pol2,mr,nib,allslu,nomslu,otd,ss,nc,ct,kk,kdp,kd,'+;
'kdr,cl,clr,clo,ishod,spec,appendix,oper,do_oper,vidstac,pol,vtravm,subotd,clomt,str_pens,'+;
'kkr,kod_smo,vpolis,spolis,npolis,resalt,np,adrg,prmp,stand,date_pr,doc,dateoutst)'+;
' values '+;
'(?laArrayFields(1),?laArrayFields(2),?laArrayFields(3),?laArrayFields(4),?laArrayFields(5),'+;
'?laArrayFields(6),?laArrayFields(7),?laArrayFields(8),?laArrayFields(9),?laArrayFields(10),'+;
'?laArrayFields(11),?laArrayFields(12),?laArrayFields(13),?laArrayFields(14),?laArrayFields(15),'+;
'?laArrayFields(16),?laArrayFields(17),?laArrayFields(18),?laArrayFields(19),?laArrayFields(20),'+;
'?laArrayFields(21),?laArrayFields(22),?laArrayFields(23),?laArrayFields(24),?laArrayFields(25),'+;
'?laArrayFields(26),?laArrayFields(27),?laArrayFields(28),?laArrayFields(29),?laArrayFields(30),'+;
'?laArrayFields(31),?laArrayFields(32),?laArrayFields(33),?laArrayFields(34),?laArrayFields(35),'+;
'?laArrayFields(36),?laArrayFields(37),?laArrayFields(38),?laArrayFields(39),?laArrayFields(40),'+;
'?laArrayFields(41),?laArrayFields(42),?laArrayFields(43),?laArrayFields(44),?laArrayFields(45),'+;
'?laArrayFields(46),?laArrayFields(47),?laArrayFields(48),?laArrayFields(49),?laArrayFields(50),'+;
'?laArrayFields(51),?laArrayFields(52),?laArrayFields(53),?laArrayFields(54),?laArrayFields(55),'+;
'?laArrayFields(56),?laArrayFields(57),?laArrayFields(58),?laArrayFields(59))'

Local lnPreapare,lnBegin,lnEnd

Store 0 To lnBegin,lnEnd

lnBegin=Seconds()

lnPreapare=Sqlprepare(lnSQLHandleConnection,lcSQL)

If lnPreapare>0

Local laArrayFields(1),lnRec,lnAllRec

lnRec=0
lnAllRec=0

Select rrlocal
lnAllRec=Reccount("rrlocal")

Scan
lnRec=Recno("rrlocal")
* Wait Window "Запись данных ... обработка записи: "+Alltrim(Str(lnRec))+" из "+Alltrim(Str(lnAllRec)) Nowait Noclear
Scatter Fields Like * To laArrayFields

For lnI=1 To Alen(laArrayFields)
Do Case
Case (Type("laArrayFields(lnI)")=="D" and Empty(laArrayFields(lnI))) Or (Type("laArrayFields(lnI)")=="C" and Empty(laArrayFields(lnI)))
laArrayFields(lnI)=.NULL.
Case Type("laArrayFields(lnI)")=="N" and Empty(laArrayFields(lnI))
laArrayFields(lnI)=0
Endcase
Endfor

lnErr=0
lnErr=Sqlexec(lnSQLHandleConnection)

If lnErr<0
Local laErr(1)
=Aerror(laErr)
Insert Into err (nomrec,errrec) Values (Recno("rrlocal"),lnErr)
Endif

Endscan
* Wait Clear

lnEnd=Seconds()
Messagebox(lnEnd-lnBegin,0,'')

Else
Messagebox("Запрос не препарирован!",0,"")
Endif

Local lnCloseConnect
lnCloseConnect=0

lnCloseConnect=Sqldisconnect(lnSQLHandleConnection)

If lnCloseConnect<0
Messagebox("Соединение не закрыто!",0,"")
Else
Messagebox("Соединение успешно закрыто!",0,"")
Endif
Else
Messagebox("Связь с источником данных не установлена!",0,"")
Endif

Собственно этот кусок кода производит запись в таблицу FB за 14 - 18 минут (5 раз тестировал)
можно ли как-то ускорить процесс?
Алексей Лашин
Дата: 06.01.2013 18:09:40
И вопрос по поводу получения курсора необходимой структуры, может чего не догоняю, но
Sqlexec(lnSQLHandleConnection,"Select Cast(ku as numeric(6,0)) as ku from RR where RR.Dr=?ldDr","TmpCur")

Select TmpCur
Browse
Copy To "D:\akkb\tt.dbf" Type fox2x

захожу в сохранённую табличку и вижу моё поле Ku Numeric(11,0)

Это как так получается? разъясните пжалста...
tanglir
Дата: 06.01.2013 18:09:48
Алексей Лашин, это вопрос скорее в форум по ФБ. На скорую руку нашлось вот что:
/topic/913534
/topic/295217

ЗЫ. Хотел написать "выбрасывайте свой массив в csv, потом грузите чем-то наподобие load data / bulk insert"/ Каково же было моё удивление, когда оказалось, что в ФБ ничего подобного нет. Ну или есть, но тогда оно хорошо спрятано, за пять минут на найти :)
tanglir
Дата: 06.01.2013 18:11:48
Алексей Лашин
Это как так получается?
Это причуды одбц-драйвера... Если хотите раз и навсегда это пресечь, то кроме курсорадаптеров с заранее прописанным cursorschema вариантов афаик нет.
Алексей Лашин
Дата: 06.01.2013 18:20:05
Спасибо большое tanglir
Буду разбираться.
По поводу причуд с ODBC я подозревал, но не думал что так вот не повезёт)))
FB_User
Дата: 06.01.2013 18:58:08
Если заливка через ODBC

1. смотрите в сторону Execute Block
2. включите явное управление транзакциями (SQLSetProp) и коммитите явно (SQLCommit) после вставки n-го кол-ва записей (в зависимости от ситуации это может быть от сотен до десятков тысяч)

Если не требуется именно через драйвер, то смотреть в сторону External Table, или использовать что-то навроде IB DataPump.
Алексей Лашин
Дата: 09.01.2013 10:39:49
Спасибо, FB_User
Почитаю про внешние таблицы и про иб блоки