1

Konu: Son zamanlarda gordugum en iyi kodlardan birisi

Benim isime cok yaradi. Aciklamalarina girmeden ve unutmadan paylasayim istedim - farkederseniz daha kodu duzenlemeyi bitirmedim bile ama cok iyi unutmadan koyayim buraya;)

Jeff Moden'e giyabinda tesekkur ediyorum.

Visual Fox Pro
start=SECONDS()

LOCAL ARRAY aArrayParm[50000]
FOR ix = 1 TO 50000
    aArrayParm[m.ix] = m.ix
endfor
 
TEXT TO lcSplitter noshow
--
--"Monster" Split in SQL Server 2005
--Passing Parameters as (almost) 1, 2, and 3 Dimensional Arrays
--By Jeff Moden, 2008/05/22
--
 
CREATE procedure #splitter @Parameter VARCHAR(MAX)
as 
--===== Add start and end commas to the Parameter so we can handle     
-- all the elements the same way   
SET @Parameter = ','+@Parameter +','
;
WITH cteTally AS(
--==== Create a Tally CTE from 1 to whatever the length     
-- of the parameter is
SELECT TOP (LEN(@Parameter))       
    ROW_NUMBER() OVER (ORDER BY t1.Object_ID) AS N   
    FROM Master.sys.All_Columns t1 
    CROSS JOIN Master.sys.All_Columns t2
)
SELECT ROW_NUMBER() OVER (ORDER BY N) AS Number,       
    SUBSTRING(@Parameter,N+1,CHARINDEX(',',@Parameter,N+1)-N-1) AS Value
FROM cteTally 
    WHERE N < LEN(@Parameter) AND SUBSTRING(@Parameter,N,1) = ','
--Notice how we find the comma
ENDTEXT
 
loConnection = Createobject('AdoDb.Connection')
loConnection.ConnectionString = "Provider=SQLNCLI.1;Integrated Security=SSPI;Persist Security Info=False;"+;
  "Initial Catalog=AccuFRCC;Data Source=193.140.148.171\sqlexpress;"
loConnection.Open()
 
Local loCommand As ADODB.Command
loCommand = Createobject('AdoDb.Command')
loCommand.ActiveConnection = loConnection
 
loCommand.CommandText=m.lcSplitter
loCommand.Execute()
 
 
                lcCurType = Type('aArrayParm[1]')
                IF m.lcCurType $ 'DT'
                    FOR ix = 1 TO ALEN(aArrayParm)
                        aArrayParm[m.ix] = IIF(m.lcCurType = 'D',;
                        TRANSFORM(DTOC(aArrayParm[m.ix],1),'@R 9999/99/99'),;
                        TRANSFORM(TTOC(aArrayParm[m.ix],1),'@R 9999/99/99 99:99:99'))
                    endfor
                endif
                lcValueList = ''
*                lcPrePostFix = Iif(Type('aArrayParm[1]') = 'C', "'",'')
                For ix=1 To Alen(aArrayParm)
                    lcValueList = m.lcValueList + ;
                        IIF(m.ix>1,',','') + ;
                        TEXTMERGE('<<aArrayParm[m.ix]>>')
                Endfor
*                lcValueList = m.lcValueList + ')'
 
*!*                    If Lower(m.lcValueList) == '.null.'
*!*                        lcValueList = 'null'
*!*                    Endif
 
*!*                    tcCmd = Strtran(m.tcCmd,'(?)',m.lcValueList,1,1)
 
 
loCommand.CommandType = 4
loCommand.Parameters.Append( loCommand.CreateParameter("@parameter",201,1,-1, m.lcValueList ))
loCommand.CommandText = '#splitter'
 
oRS = loCommand.Execute
? SECONDS()-m.start, oRS.RecordCount, LEN(m.lcValueList)
 
ShowRS(oRS)
oRS.Close()
loConnection.Close()

2

Re: Son zamanlarda gordugum en iyi kodlardan birisi

Kod gerçekten çok güzel olmuş.
Bı kod bana farklı şeyler yapabileceğimi düşündürdü big_smile
Bu kodu bizimle paylaştığın için ben de sana teşekkür ederim smile

/o---------------------o\
     www.haser.com
\o---------------------o/

3

Re: Son zamanlarda gordugum en iyi kodlardan birisi

hmm bu kod ne işe yarıyor???

split filan birşeyler yazıyor ama... neyi bölüyor???

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

4

Re: Son zamanlarda gordugum en iyi kodlardan birisi

Kod tamamlanmadi ama o haliyle de bende calisir calismaz postaladim. Yaptigi virgulle ayrilmis bir listeyi tablo haline cevirmek.

'Ali,Veli,49.Elli'

1,Ali
2,Veli
3,49
4,Elli

Oluyor. (VFPnin alines()'i gibi) Benim derdim SQL server icin:

SQL
SELECT * FROM tablo WHERE alanadi IN (1,2,3,5)


gibi kodlari optimize yazabilmek (daha iyi bir fikri olan varsa soylesin bulamadim ben).

Dogrudan

select * from tablo where alanadi in (1,2,3,5)

gondermekte problem yok ama liste cok uzunsa SQL server'dan timeout sansi cok artiyor. Onun icin sunun gibi birsey yapmak istedim:

Visual Fox Pro
loConnection = Createobject('AdoDb.Connection')

loConnection.ConnectionString = "Provider=SQLNCLI.1;Integrated Security=SSPI;Persist Security Info=False;"+;
  "Initial Catalog=Northwind;Data Source=.;"
loConnection.Open()
 
Local loCommand As ADODB.Command
loCommand = Createobject('AdoDb.Command')
loCommand.ActiveConnection = loConnection
 
TEXT TO loCommand.CommandText noshow
CREATE TABLE #IdList ([id] int);
INSERT INTO #IdList VALUES (1);
INSERT INTO #IdList VALUES (2);
INSERT INTO #IdList VALUES (3);
INSERT INTO #IdList VALUES (5);
ENDTEXT
loCommand.Execute
 
TEXT TO loCommand.CommandText noshow
select * from Products INNER JOIN #IDList ON Products.ProductID = #IDList.[id];
ENDTEXT
 
 
oRS = loCommand.Execute
 
LOCAL oCa as Cursoradapter
oCa = CREATEOBJECT('Cursoradapter')
oCA.Alias = 'result'
oCA.DataSourceType = "ADO"
oCA.DataSource = oRS
oCA.MapBinary = .T.
oCA.MapVarchar = .T.
oCA.CursorFill(.f.,.f.,0,oRS)
 
SELECT result
browse
 
oRS.Close()
loConnection.Close()


Bu guzel calisiyor ve yaratilan temp tablo ile SQL serverda inner join ya da in (select ...) filan yapmak efekti. Problem uzun listelerin uzun:

Visual Fox Pro
INSERT INTO #IdList VALUES (1);

INSERT INTO #IdList VALUES (2);
...

koduna ihtiyac duymasiydi (nede olsa networkte bir sekilde once SQL servera bilgi gitmesi gerekiyor - in (1,2,3,5...) )

Simdi ise '1,2,3,5,...' seklinde tek bir string gonderip SQL serverda (server side) onun tabloya donusmesi cok daha fazla isime geliyor, hem giden data daha az hem de gittiginde tablonun olusmasi daha hizli:)

5

Re: Son zamanlarda gordugum en iyi kodlardan birisi

teşekkürler... şu an lazım değil. ileride lazım olur bu sefer de bulamam. HDD'me kaydetsem HDD'de olduğunu hatırlamam. ya da yerini bulamam... sad

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

6

Re: Son zamanlarda gordugum en iyi kodlardan birisi

Çetin,
Senin yazdığın "In" ile ilgili kısımdan çok kendi projemde özel durumlarımla ilgili kısımları yeniden optimize edebileceğimi görmüştüm. Ancak "In" ifadesinden bahsedince sana sormak istediğim bir şey geldi aklıma wink Aşağıdaki kodlardan hangisi daha performanslıdır? (ya da ikisinide aynı mı?)

Select * From TabloAdi Where SahaAdi = 3 Or SahaAdi = 5 Or SahaAdi = 6
veya
Select * From TabloAdi Where SahaAdi In (3, 5, 6)

/o---------------------o\
     www.haser.com
\o---------------------o/

7

Re: Son zamanlarda gordugum en iyi kodlardan birisi

Cok zor bir soru:) Ilk bakista ilki diyecegim ama bilemiyorum acikcasi.

In (3,5,6) uzun listelerde gocuyor, uzun listelerde or' da yazilmaz:) Sanirim bun da cevabi 'yeni kod':) Kisa listelerde perfonmans farki zaten olculemeyecek boyutlarda olur gibi geliyor.

8

Re: Son zamanlarda gordugum en iyi kodlardan birisi

Anlaşıldı teşekkür ederim smile

/o---------------------o\
     www.haser.com
\o---------------------o/