1

Konu: SQL servere birden fazla kayıt tek komutla yollanabilir mi?

örneğin 3 fieldli 4 kayıtlı bir cursor var: cursor4sira
şimdiki bilgime göre yaptığım

Visual Fox Pro
m.lnh=SQLSTRINGCONNECT("xxx")

SCAN  && 4 kere SQLSERVER'e bilgi gidiyor
  SCATTER MEMVAR
  SQLECEC(m.lnH,"INSERT INTO [xx]..[sqldosya] (sqlbir,sqliki,sqlüç) VALUES (?m.bir,?m.iki,?m.üç)")
ENDS
SQLDISCONNECT(0)

SORU: yapmak istediğim; örneğin

Visual Fox Pro
SELE * FROM cursor4sira INTO ARRAY arraySQLeYollanacak

SQLEXEC(m.lnh, "ARRAYYOLLA(arraySQLeYollanacak)")


veya

Visual Fox Pro
SQLEXEC(m.lnh, "CURSORYOLLA(cursor4sira)")

tek komutla SQL'e kaydedeceğim bütün datayı yollayıp , gerisini STORED PROCEDURE ile halletmek . (yanıt XML mi acaba- nasıl)

VFP9 SP2

2

Re: SQL servere birden fazla kayıt tek komutla yollanabilir mi?

blockwrite olayı var sql server'da. text veya xml (sanırım başka dosya türlerini de destekliyor). ama hiç kullanmadım.

Haksızlıklar karşısında susanlar, dilsiz şeytanlardır!
www.metinemre.com

3

Re: SQL servere birden fazla kayıt tek komutla yollanabilir mi?

Merhabalar:) Birden fazla yolu var. Hangi yolun secilecegi bir kac faktore bagli:

a) SQL server versiyonu 2008' mi yoksa daha oncesi mi? SQL 2008'de tek bir insert ile bircok kayit insert edilebiliyor:

Visual Fox Pro
local array laData[1]

select f1,f2,f3 from myTable into array laData
if _Tally > 0
   local row,lcSQL
   set textmerge to memvar lcSQL noshow
   set textmerge on
   \\ insert into [xx]..[sqldosya] (sqlbir,sqliki,sqlüç) values
   for row = 1 to alen(laData,1)
         \ ( ?laData[<< m.row >>, 1], ?laData[<< m.row >>, 2], ?laData[<< m.row >>, 3]  )
         if m.row < alen(laData, 1)
             \\,
         endif
   endfor
   set textmerge to
   set textmerge off
   m.lnh=SQLSTRINGCONNECT("Driver={SQL Server Native Client 10.0};server=.\sql2008;Trusted_Connection=yes;Database=test")
   SQLExec(m.lnh, m.lcSQL) 
   SQLDISCONNECT(0)
endif

(eger .Net kullaniyor olsaydik bunun yerine dogrudan bir 'table'i parametre olarak gonderebiliyorduk:( VFP ile yapilabilir mi cok derinlemesine bakmadim).

Bu, kayit sayisi cok fazla degilse, tek seferde insert etmek icin kullanilabilecek bir yontem (SQL 2008).

2) SQL versiyonu ne olursa olsun kayit sayisi az mi cok mu. Az ise:

Visual Fox Pro
Local Array laData[1]

Select f1,f2,f3 From (_samples+'data\customer') Into Array laData
If _Tally > 0
  Local Row,lcSQL
  Set Textmerge To Memvar lcSQL Noshow
  Set Textmerge On
  For Row = 1 To Alen(laData,1)
       \ insert into [xx]..[sqldosya] (sqlbir,sqliki,sqlüç) values
       \\ ( ?laData[<< m.row >>, 1], ?laData[<< m.row >>, 2], ?laData[<< m.row >>, 3]  );
  Endfor
  Set Textmerge To
  Set Textmerge Off
  m.lnh=Sqlstringconnect("Driver={SQL Native Client};server=.\sql2008;Trusted_Connection=yes;Database=test")
  SQLExec(m.lnh, m.lcSQL)
  SQLDisconnect(0)
Endif

Bir baska yontem (bir kez compile + N kez insert ):

Visual Fox Pro
LOCAL lcSQL

lcSQL = 'INSERT INTO [xx]..[sqldosya] (sqlbir,sqliki,sqlüç) VALUES (?m.bir,?m.iki,?m.üç)'
 
m.lnh=SQLSTRINGCONNECT("Driver={SQL Server Native Client 10.0};server=.\sql2008;Trusted_Connection=yes;Database=test")
SQLPrepare(m.lnh, m.lcSQL) && Compile 
 
SCAN  && 4 kere SQLSERVER'e bilgi gidiyor
  SCATTER MEMVAR
  SQLExec(m.lnH) && compile edilmis kodu kullan
ENDS
SQLDISCONNECT(0)

Bu yontemler az kayitla efektif calisiyor. Diger bir yontem CursorAdapter kullanmak. CursorAdapter'in BatchUpdateCount propertysi var . 100 dersen (benim denemelerimde cok buyuk kurmanin bir faydasi olmuyor, bir yerden sonra ayni, 100 ortalama iyi bir deger gibi) tek seferde o 100 gondererek update ediyor (select ... where 1=2 ile baslarsan hepsi Insert olacak).

Parametre giden yontemlerde 3 field icin pratikte 700 kayit sinirin var (SQL server maximum parametre sayisi 2100 eger yanlis hatirlamiyorsam).

3) Eger kayit sayisi cok ise:
a) http://www.fox4um.com/topic/1214/sqlbulkcopy/

benim bugune kadar bulabildigim en efektif yontem. Gerekirse dll'i filan hazir gonderirim:)

b) VFP datasini text dosyasina copy to ile transfer edip SQL server'dan 'Bulk Copy' ile okumak (SQL server text dosyasina ulasabilmeli)

c) SQL server'da once bir linked server olusturmak (kodla olabilir - SQL server'a erisim haklarina bagli). Sonra da istenilen VFP dosyasindan query yapmak. Soyle birsey:

Visual Fox Pro
TEXT TO lcLinkedYarat noshow

EXEC sp_addlinkedserver
    @server = N'VFP_SERVER',  -- linked server adi
    @srvproduct=N'Visual FoxPro 9',  -- ne istersen olabilir
    @provider=N'VFPOLEDB',
    @datasrc=N'"C:\PROGRAM FILES\MICROSOFT VISUAL FOXPRO 9\Samples\data\testdata.dbc"'
ENDTEXT
 
* Bir kez yapmak gerekiyor
SQLEXEC(m.lnh, m.lcLinkedYarat)

VFP'den kodla yapmak yerine SQL server management kullansak da olurdu. Bir kez yapildi mi artik VF_SERVER diye VFP datasina ulasan bir kaynak var (northwind benzeri dataya insert - VFP"den select, SQL'e insert):

Visual Fox Pro
TEXT TO lcSQL noshow

insert mySQLTable (orderId, orderDate,shippedTo)
Select * From openquery(VFP_SERVER,
'Select
  order_ID,
Cast(Evl(order_date,Null) As DateTime) As order_Date,
TRIM(to_Name)
from customer')
ENDTEXT
 
SQLEXEC(m.lnh, m.lcSQL)

Not: Burada OpenQuery() icindeki SQL VFP'nin anlayacagi SQL, VFP tablosuna yapiliyor. Sadece basta ve sonda tirnak isareti var, gerisi normal ; kullanilmadan yazilabiliyor.

d) XmlBulkCopy, SQL Server'in For XML gibi baska yontemlerde var ama bana hem yavas geldi hem de ben beceremedim cok karmasik, birinde calisiyor digerinde calismiyor, yazmasi da cok zor geldi:

4 Son düzenleyen, ugurlu2001 (11.12.2009 14:21:05)

Re: SQL servere birden fazla kayıt tek komutla yollanabilir mi?

Üstad bir soruda ben sorsam?

Peki SQL Servar 'a, bir yerine , birbiriyle ilgili bir kaç ( sayısı değişebilir ) cursor yollasak. Bu cursorleri bir Stored Procedure içinden kullanmak istesek:
(FaturaNo, FaturaDetay, ÜrünDetay) .. gibi

Yani ali Abinin sorusunu şu şekilde sormuş olsam :
Select * From Cursor1 Into Cursor Crs1
Select * From Cursor2 Into Cursor Crs2
Select * From Cursor3 Into Cursor Crs3
Select * From Cursor4 Into Cursor Crs4

SQLEXEC(m.lnh, "CURSORYOLLA(Crs1)","CURSORYOLLA(Crs2)","CURSORYOLLA(Crs3)","CURSORYOLLA(Crs4)")

Birde fikir edinmek için soruyorum :
Bir tek XML dosyası içerisine, cursorleri yerleştirip, parametre olarak XML i kullanmak daha mı mantıklı. (Cursorlerde az sayıda kayıt olduğunu varsayarak),

Uğur
-------------------------------------------------------------------------------------------------------------
Hayat bir bisiklete binmek gibidir. Pedalı çevirmeye devam ettiğiniz sürece düşmezsiniz. Claude Peppeer
Kusuru söylenmeyen adam, ayıbını hüner sanır.  Türk Atasözü

5

Re: SQL servere birden fazla kayıt tek komutla yollanabilir mi?

Çetin,
öncelikle çok teşekkürler. 1. metod aradığım galiba.
"kayit sayisi cok fazla degilse" den anladığım örneğin tablo uzunluğu x alan sayısı diyelim ki 500 den az olanlar gibi oldu.
Ayrıca insert değil de sqlserver tarafında bir cursor yaratmaya çalışıyorum.

Derdim database integrityden dolayı datayı bir kere set olarak yolladım mı sqlserver tarafında bütün işlemleri yapayım. - daha önce yazdığım başlıkta SQLde SCANi keşfettim ya ! :]

önerdiğin 2. metodta sqlservere 1 kere gibi gidiyor gözükse galiba döngü kadar gidiyor, ya da ben mi yanılıyorum.

3lerde ise yollanacak data clientta olunca, çok kullanıcılı ortamda servera değişik adlarla kaydedip Sqlservere okutma karmaşası çıkıyor galiba.
yani sqlservere dosya adını parametre olarak göndermek gerekiyor galiba.

VFP9 SP2

6

Re: SQL servere birden fazla kayıt tek komutla yollanabilir mi?

2. metodda 2 yontem var. Ilkinde VFP tarafinda bir defada N tane insert komutu yazilip tek seferde godneriliyor. SQL server'a giden kabaca:

insert into xx..yy (f1,f2,f3) values (1,2,3);
insert into xx..yy (f1,f2,f3) values (4,5,6);
insert into xx..yy (f1,f2,f3) values (7,8,9);

gibi. Bu komple tek 'batch' olarak gidiyor (tek SQLExec() ). SQL tarafinda ise 3 insert.

Ikinci metodda ise insert VFP tarafinda bir tane, once compile ediliyor, compile edilmis kod her bir insert icin cagiriliyor (SQL server'a giden komutlar once compile ediliyor - SQL 2000'den yana caching nedeniyle pek de esprisi kalmadi bu yontemin).

Bu yontemler parametre ile calistigindan bir kerede gonderilebilecek kayit sayisi:
kayitSayisi * alanSayisi = max 2100 sekilde
500 field varsa bir seferde 4 insert.

3'te gecici dosyalar kullanilabilir, isimler cakismaz ya da 3-a'da data client'in kendi dizinlerinden alindigi icin cakisma da yok. 3 serisinin avantaji en hizli yontemler olmalari.

7

Re: SQL servere birden fazla kayıt tek komutla yollanabilir mi?

ugurlu2001 yazdı:

Üstad bir soruda ben sorsam?

Peki SQL Servar 'a, bir yerine , birbiriyle ilgili bir kaç ( sayısı değişebilir ) cursor yollasak. Bu cursorleri bir Stored Procedure içinden kullanmak istesek:
(FaturaNo, FaturaDetay, ÜrünDetay) .. gibi

Yani ali Abinin sorusunu şu şekilde sormuş olsam :
Select * From Cursor1 Into Cursor Crs1
Select * From Cursor2 Into Cursor Crs2
Select * From Cursor3 Into Cursor Crs3
Select * From Cursor4 Into Cursor Crs4

SQLEXEC(m.lnh, "CURSORYOLLA(Crs1)","CURSORYOLLA(Crs2)","CURSORYOLLA(Crs3)","CURSORYOLLA(Crs4)")

Birde fikir edinmek için soruyorum :
Bir tek XML dosyası içerisine, cursorleri yerleştirip, parametre olarak XML i kullanmak daha mı mantıklı. (Cursorlerde az sayıda kayıt olduğunu varsayarak),

Ugur,
Bu dun gozumden kacmis.

SQL server'a cursor yollamak demek datayi zaten SQL server'da insert etmek demek. Gecici tablo kullanimi pek tavsiye edilen birsey degil (performans acisindan). Oradan da asil tabloya insert edeceksin, isi daha da yavaslatir. Ancak demek istedigin SQL2008'in yeni tablo parametresini kullanmak ise VFP ile yapilabilir mi, yapilirsa nasil yapilir hic fikrim yok.

XML kullanmayi tavsiye etmem, cunku XML hemen hemen her zaman daha cok verinin gidip-gelmesini gerektiriyor + XML'in cevrim islemleri isi daha da yavaslatiyor. XML kucuk data icin olur. XML kayit basina gereksiz sekilde field adlarini tekrarlayan bir yontem - ilk ciktiginda amaci simdiki gibi data transferi degildi ondan herhalde oyle gereksiz tekrarlari.

8

Re: SQL servere birden fazla kayıt tek komutla yollanabilir mi?

Çetin,
Uğur ile aynı soruyu kelimelerin yerini değiştirerek gene soracağım affola:

Ben datayı bir dataset olarak bir SQLserver tarafında bir cursora (veya geçici bir kütüğe)  yüklemek istiyorum. 1. metodla OK, zaten en fazla 10 kayıt x 2 alan (tekstilId,adet) falan gidiyor
Derdim sonraki işlemleri SQLserver tarafında yapıp -3-4 tane tableda insert ve update ve delete yapacağım.
Yani peşpeşe VFP komutu olarak yaptığımda connection yüzünden aksama olursa database integrityyi bozulur diye korkuyorum...
BEGIN END ROLLBACK muhabbetine gene connection olarak girmek istemiyorum. (Hani Türk filimlerinde filmin manasını gözardı edip "sonunda kahraman öldü mü" diye görmek isteriz ya- o sendrom)
O nedenle VFP tarafından gelen bir INSERT değil de SQL tarafında bir cursor arıyorum. Devamını STORED PROCEDUR ile trigger falan halletmeyi düşünüyorum....

VFP9 SP2

9

Re: SQL servere birden fazla kayıt tek komutla yollanabilir mi?

O zaman Ugur'un dedigi gecerli:) # kullanarak gecici bir tablo (VFP terimiyle cursor) yaratabilirsin. SQL server acisindan onun normal tablodan hicbir farki yok, connection aktif oldugu surece kullanabilirsin, kapaninca otomatikman SQL server kaldirir ( ya da sana gerekli ise arada Drop Table ile sen kapatabilirsin - bu tablolar Temp database'de yaratiliyor ama teknik detay). Ornek gonderecegim simdi ama bu bilgisayari kapatmak zorundayim. Baska yerden bir sure sonra gonderiyorum:)

10