{"id":151,"date":"2019-09-30T22:14:40","date_gmt":"2019-09-30T19:14:40","guid":{"rendered":"http:\/\/www.potansif.com\/?p=151"},"modified":"2019-09-30T22:14:40","modified_gmt":"2019-09-30T19:14:40","slug":"sql-server-tablo-degiskeni-kullanimi-running-total-yuruyen-bakiye-ornegi","status":"publish","type":"post","link":"http:\/\/www.potansif.com\/?p=151","title":{"rendered":"SQL Server : Tablo De\u011fi\u015fkeni Kullan\u0131m\u0131 (Running Total, Y\u00fcr\u00fcyen Bakiye \u00d6rne\u011fi)"},"content":{"rendered":"<p>Merhaba,<\/p>\n<p>\u0130\u015f\/g\u00fc\u00e7 derken ister istemez biraz ara vermek zorunda kald\u0131m. Tabi bunlara ek olarak &#8220;bahar yorgunlu\u011funun da&#8221; biraz etkisi olmad\u0131 de\u011fil&#8230; \u00c7ok uzatmadan sadede geleyim;<br \/>\n<!--more--><br \/>\nBu yaz\u0131m\u0131zda SQL Server&#8217;da tablo tipindeki de\u011fi\u015fkenleri irdelemeye, onlar\u0131 anlamaya \u00e7al\u0131\u015faca\u011f\u0131m ve nas\u0131l kullan\u0131ld\u0131\u011f\u0131na dair \u00f6rnekler verece\u011fim. Bu \u00f6rneklemelerde ise forumda son zamanlarda s\u0131k\u00e7a duymaya ba\u015flad\u0131\u011f\u0131m\u0131z &#8220;y\u00fcr\u00fcyen toplam&#8221;, &#8220;devreden toplam&#8221;, &#8220;K\u00fcm\u00fclatif toplam&#8221;, &#8220;running total&#8221; gibi adlarla bildi\u011fimiz fakat daha \u00e7ok cari hesap ekstrelerinde g\u00f6sterdi\u011fimiz devreden bakiye hesaplamaya dair \u00f6rnekler vermeye \u00e7al\u0131\u015faca\u011f\u0131m. \u00d6rnekleri karma\u015f\u0131kla\u015ft\u0131rmadan, en basit nas\u0131l olur y\u00f6n\u00fcnde tercihler kullanaca\u011f\u0131m. Ba\u015flayal\u0131m;<\/p>\n<h1>Tablo De\u011fi\u015fkeni Nedir?<\/h1>\n<p>Tablo de\u011fi\u015fkenleri, di\u011fer de\u011fi\u015fkenlerden farkl\u0131 olarak veriyi bir de\u011fi\u015fken i\u00e7erisinde tablo olarak tutar. Bilindik, s\u0131radan tablolarda veya temp tablolarda yapt\u0131\u011f\u0131n\u0131z bir \u00e7ok i\u015flemi tablo de\u011fi\u015fkenlerinde de rahatl\u0131kla yapabilirsiniz. Fakat hem normal, hem de temp tablolardan baz\u0131 noktalarda farkl\u0131la\u015ft\u0131\u011f\u0131n\u0131 ve yap\u0131sal olarak asl\u0131nda bunlar\u0131n birer de\u011fi\u015fken oldu\u011funu unutmamal\u0131y\u0131z.<\/p>\n<p>Microsoft, SQL Server 2000&#8217;den itibaren tablo de\u011fi\u015fkenlerini temp tablolara (san\u0131r\u0131m) bir alternatif olu\u015fturmas\u0131 maksad\u0131yla tan\u0131tt\u0131. Fakat s\u0131rf alternatif olsun diye bunu yapmak i\u015fg\u00fczarl\u0131k olurdu, o nedenle buradaki n\u00fcans\u0131n &#8220;performans odakl\u0131&#8221; oldu\u011funu belirtmek isterim. \u00c7o\u011fu durumda bir tablo de\u011fi\u015fkeni ikiz karde\u015fi olan temp tablolardan \u00e7ok daha h\u0131zl\u0131d\u0131r. Bunun temel sebebi tablo de\u011fi\u015fkenlerinin &#8220;neredeyse&#8221; (ve hatta mecbur kalmad\u0131klar\u0131 s\u00fcrece) hi\u00e7 bir \u015fekilde disk ile ha\u015f\u0131r ne\u015fir olmamas\u0131 ve t\u00fcm s\u00fcrecin bellek \u00fczerinde ger\u00e7ekle\u015ftirilmesinden kaynaklanmaktad\u0131r. Buna ek olarak arka tarafta, yap\u0131sal anlamda (bir temp tabloya nazaran) daha az sistem de\u011fi\u015fkeni tutmas\u0131 nedeniyle tablo de\u011fi\u015fkenleri, temp tablolara nazaran \u00e7ok daha optimize edilmi\u015f bir yap\u0131ya sahiptir. Daha optimize olmalar\u0131n\u0131n temel sebebini ise bellek y\u00f6netimi ve performans oda\u011f\u0131 a\u00e7\u0131s\u0131ndan de\u011ferlendirmek gerekir&#8230; \u00d6zetleyecek olursak Tablo De\u011fi\u015fkenleri, bellekte i\u015flem g\u00f6ren optimize edilmi\u015f bir \u00e7e\u015fit temp tablodur.<\/p>\n<p>Tablo de\u011fi\u015fkeninin nas\u0131l tan\u0131mland\u0131\u011f\u0131 ile ilgili ufak bir \u00f6rnek verelim, \u00f6rne\u011fimiz running total i\u00e7in de bir temel te\u015fkil etsin bu arada;<\/p>\n<pre><code>DECLARE&nbsp; &nbsp;@TabloDegiskeni TABLE&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;--&gt; Bir tablo de\u011fi\u015fkeni tan\u0131ml\u0131yoruz.&nbsp;\n( ID&nbsp; &nbsp; &nbsp; INT&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;IDENTITY(1,1) --&gt; S\u0131ral\u0131 artan bir alan tan\u0131ml\u0131yoruz. \u0130\u00e7i resen (kendili\u011finden (otomatik) ) olarak ard\u0131\u015f\u0131k dolacakt\u0131r...\n, Tarih&nbsp; &nbsp;DATETIME&nbsp; &nbsp; &nbsp; &nbsp; NULL&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; --&gt; Val\u00f6r tarihini ifade eder.\n, Islem&nbsp; &nbsp;VARCHAR(255)&nbsp; &nbsp; NULL&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; --&gt; A\u00e7\u0131klamay\u0131 ifade eder.\n, Tutar&nbsp; &nbsp;MONEY&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;NULL&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; --&gt; \u0130\u015flem tutar\u0131n\u0131 ifade eder.\n, Bakiye&nbsp; MONEY&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;NULL&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; --&gt; \u015e\u0130MD\u0130L\u0130K BO\u015e, BU KISMI \u0130LER\u0130DE HESAPLATACA\u011eIZ...\n)\n<\/code><\/pre>\n<h1>Kapsam\u0131 ve \u00d6zel Durumlar<\/h1>\n<p>Tablo de\u011fi\u015fkenlerinin bellekte i\u015flem g\u00f6rd\u00fc\u011f\u00fcnden s\u00f6zettik, peki i\u015fleyece\u011fimiz veriler bellekten daha fazla yer kapl\u0131yorsa o zaman ne olacak? \u015eahsen tercihim o t\u00fcr durumlarda tablo de\u011fi\u015fkenini de\u011fil, temp tablonun kullan\u0131lmas\u0131 gerekti\u011fi y\u00f6n\u00fcndedir. Verinin bellekten daha fazla yer kaplad\u0131\u011f\u0131 durumlarda do\u011fal olarak, SQL Server ister istemez diske eri\u015fim sa\u011flamak zorunda kalacakt\u0131r. Haliyle performans da temp tablo seviyesine kadar d\u00fc\u015fecektir. Bunda bir behis g\u00f6remeyebilirsiniz fakat bu durumun (yani b\u00fcy\u00fck bir sql sorgusunun disk ile ha\u015f\u0131r ne\u015fir olmaya ba\u015flamas\u0131 durumunun) a\u011f\u0131r bir yan etkisi daha vard\u0131r. \u00d6zellikle bellekten daha b\u00fcy\u00fck verileri s\u00fcrekli i\u015flemeye \u00e7al\u0131\u015ft\u0131\u011f\u0131n\u0131zda sunucunun genel performans\u0131n\u0131n da etkilendi\u011fini g\u00f6zlemleyebilirsiniz. O nedenle bu uyar\u0131m\u0131 sadece tablo de\u011fi\u015fkenleri i\u00e7in de\u011fil, t\u00fcm query&#8217;leriniz i\u00e7in temel bir kural olarak benimsemelisiniz.<\/p>\n<p>SQL Server&#8217;daki di\u011fer veri t\u00fcrlerinin bir \u00e7o\u011funun aksine bir tablo de\u011fi\u015fkenini giri\u015f\/\u00e7\u0131k\u0131\u015f parametresi olarak kullanamazs\u0131n\u0131z. Malesef, Yani bir fonksiyona veya sakl\u0131 yordama parametre olarak bunlar\u0131 veremezsiniz. Fakat kullan\u0131c\u0131 tan\u0131ml\u0131 tablo de\u011ferli bir fonksiyondan tablo de\u011fi\u015fkeni d\u00f6nd\u00fcrebilirsiniz. (Ki bu konu ile ilgili bir \u00f6rne\u011fi ba\u015fka bir yaz\u0131mda vermi\u015ftim; http:\/\/www.delphican.com\/sql-server-tablolar-icin-parametrik-sirali-alan-listesi.html )<\/p>\n<p>Buna ek olarak tablo de\u011fi\u015fkenini olu\u015ftururken varl\u0131\u011f\u0131n\u0131 kontrol etmenize de gerek yoktur. Bu biraz yan\u0131lt\u0131c\u0131 bir ifade oldu san\u0131r\u0131m; Yani mesela bir temp tabloyu olu\u015fturmadan \u00f6nce biz veya ba\u015fka bir kullan\u0131c\u0131 ayn\u0131 isimle bir temp tablo \u00fcretmi\u015f mi \u00fcretmemi\u015f mi normalde bakmam\u0131z gerekir, fakat tablo de\u011fi\u015fkeninde b\u00f6yle bir durum s\u00f6zkonusu de\u011fildir. Tablo de\u011fi\u015fkeni kullan\u0131ld\u0131\u011f\u0131 yerde kendili\u011finden SQL Server taraf\u0131ndan yok edilir. Otomatik bir garbage collection durumu s\u00f6z konusudur.<\/p>\n<h1>Performans<\/h1>\n<p>Tan\u0131m a\u00e7\u0131s\u0131ndan bir Tablo de\u011fi\u015fkeninin (temp tabloya nazaran) k\u0131s\u0131tl\u0131 bir kapsam\u0131 vard\u0131r dolay\u0131s\u0131yla SQL Server&#8217;a optimizasyon a\u00e7\u0131s\u0131ndan geni\u015f bir hareket alan\u0131 sa\u011flar. Yani SQL Server tablo de\u011fi\u015fkenini temp tablodan daha \u00e7ok sever de diyebiliriz&#8230;<\/p>\n<p>\u0130yi tan\u0131mlanm\u0131\u015f kapsam\u0131 nedeniyle tablo de\u011fi\u015fkenleri temp tablolara nazaran daha az sistem kayna\u011f\u0131na ihtiya\u00e7 duyar. Tablo de\u011fi\u015fkenini birebir, do\u011frudan etkileyen i\u015flemler ise daha \u00e7ok UPDATE s\u00fcrecinde bask\u0131n haldedir. Tablo de\u011fi\u015fkeninin bu davran\u0131\u015f\u0131n\u0131n bir yan etkisi olarak stored procedure&#8217;lerde tablo de\u011fi\u015fkenleri kullan\u0131ld\u0131\u011f\u0131nda prosed\u00fcr\u00fcn yeniden derlenmesini gerektirecek durumlar da olu\u015fabilir. Sakl\u0131 yordamlar a\u00e7\u0131s\u0131ndan bu pek de istenen bir durum de\u011fildir. Sakl\u0131 Yordamlar\u0131n (Stored Procedure) neden yeniden derlenebilece\u011fine dair \u00e7\u00f6z\u00fcmleri de i\u00e7eren daha fazla bilgi i\u00e7in a\u015fa\u011f\u0131daki linke g\u00f6z atabilirsiniz;<\/p>\n<p><a href=\"https:\/\/www.sqlshack.com\/frequent-query-recompilations-sql-query-performance-killer-detection\/\">https:\/\/www.sqlshack.com\/frequent-query-recompilations-sql-query-performance-killer-detection\/<\/a><\/p>\n<h1>K\u0131s\u0131tlamalar ve istisnalar<\/h1>\n<p>Tablo de\u011fi\u015fkenleri i\u00e7in &#8220;ALTER TABLE&#8221;, &#8220;SELECT INTO&#8221; ve &#8220;INSERT EXEC&#8221; gibi ifadeler kullanamay\u0131z.<\/p>\n<p>SQL Server 2014&#8217;den \u00f6nceki s\u00fcr\u00fcmleri i\u00e7in Tablo de\u011fi\u015fkenlerinde Non-Clusteded indeks olu\u015fturamay\u0131z. Fakat Index, Primary Key veya UNIQUE index&#8217;leri bu amaca uygun \u015fekilde kullanmay\u0131 &#8220;deneyebilirsiniz&#8221;. Bununla birlikte SQL Server 2014 CTP1 ve sonraki s\u00fcr\u00fcmler i\u00e7in ise b\u00f6yle bir k\u0131s\u0131tlama yoktur. Ki\u015fisel tercihim ise non clustered indeksi bir tablo de\u011fi\u015fkeninde kullanmaman\u0131n kullanmaktan \u00e7ok da k\u00e2rl\u0131 olmad\u0131\u011f\u0131n\u0131 g\u00f6steriyor. Takdir sizin, isteyen kullan\u0131r isteyen kullanmaz. Kullanmak isteseydik \u015f\u00f6yle bir \u015fey yapmam\u0131z gerekirdi;<\/p>\n<pre><code>DECLARE &nbsp; @TabloDegiskeni TABLE\n( ID&nbsp; &nbsp; &nbsp; INT&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;IDENTITY(1,1)\n, Tarih&nbsp; &nbsp;DATETIME&nbsp; &nbsp; &nbsp; &nbsp; NULL\n, Islem&nbsp; &nbsp;VARCHAR(255)&nbsp; &nbsp; NULL\n, Tutar&nbsp; &nbsp;MONEY&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;NULL\n, Bakiye&nbsp; MONEY&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;NULL\n, INDEX IX_TabloDegiskeniIndeksi NONCLUSTERED(Tarih, Islem desc) &nbsp; --&gt; NON CLUSTERED \u0130NDEKS TANIMI\n)\n<\/code><\/pre>\n<p>Bir k\u0131s\u0131tlama m\u0131 yoksa performansa dair bir nimet mi bilemem, nereden bakt\u0131\u011f\u0131n\u0131za g\u00f6re bu de\u011fi\u015fir fakat SQL Server, tablo de\u011fi\u015fkenleri i\u00e7in istatistikler de tutmaz. Sonu\u00e7 olarak SQL Server, tablo de\u011fi\u015fkeni ile ilgili sorguyu en iyi nas\u0131l \u00e7al\u0131\u015ft\u0131rabilece\u011fine dair bir \u00e7aba i\u00e7ine girmez&#8230; Zira buna gerek de olmayabilir. Bunun temel sebebi tablo de\u011fi\u015fkeninin dar bir kapsama sahip olmas\u0131 olabilir \u00e7\u00fcnk\u00fc bu tip de\u011fi\u015fkenler \u00e7ok spesifik ama\u00e7lar i\u00e7in tan\u0131mlan\u0131rlar ve genel ge\u00e7er kullan\u0131mlar i\u00e7in pek de uygun de\u011fildirler. Bu elzem bir durum ise temp tablo kullanmay\u0131 tercih edebilirsiniz.<\/p>\n<p>Tablo De\u011fi\u015fkenleri Transaction&#8217;lardan da etkilenmez! Bu performans a\u00e7\u0131s\u0131ndan bir avantaj olsa da &#8220;veri g\u00fcvenilirli\u011fi&#8221; (hesaplaman\u0131n do\u011frulu) a\u00e7\u0131s\u0131ndan \u00e7ok tehlikeli bir davran\u0131\u015ft\u0131r. Bu davran\u0131\u015ftan haberdar de\u011filseniz hatan\u0131n nereden kaynakland\u0131\u011f\u0131n\u0131 bulmak i\u00e7in ger\u00e7ekten \u00e7ok zaman kaybedersiniz&#8230;<\/p>\n<h1>Basit Bir \u00d6rnek<\/h1>\n<p>Bu kadar teorik bilgiden sonra biraz da \u00f6rneklemelerle devam edelim, a\u00e7\u0131klamalar \u00f6rne\u011fin i\u00e7inde devam edecek;<\/p>\n<pre><code>DECLARE&nbsp; &nbsp;@TabloDegiskeni&nbsp; &nbsp;TABLE&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;--&gt; Bir tablo de\u011fi\u015fkeni tan\u0131ml\u0131yoruz.&nbsp;\n(\n&nbsp; &nbsp; ID&nbsp; &nbsp; &nbsp; INT&nbsp; &nbsp; IDENTITY(1,1)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; --&gt; S\u0131ral\u0131 artan bir alan tan\u0131ml\u0131yoruz. \u0130\u00e7i resen (kendili\u011finden (otomatik) ) dolacakt\u0131r...\n--&gt; ID&nbsp; &nbsp; &nbsp; INT&nbsp; &nbsp; IDENTITY(1,1) PRIMARY KEY&nbsp; --&gt; VEYA ! bu alan\u0131 hem s\u0131ral\u0131 hem de birincil anahtar olarak da tan\u0131mlayabilirdik...\n, Tarih&nbsp; &nbsp; &nbsp;DATETIME&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; NULL&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; --&gt; \u0130\u015flemin ger\u00e7ekle\u015fti\u011fi g\u00fcn\u00fc ifade eder.\n, Islem&nbsp; &nbsp; &nbsp;VARCHAR(255)&nbsp; &nbsp; &nbsp; NULL&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; --&gt; \u0130\u015flemin A\u00e7\u0131klamas\u0131n\u0131 ifade eder.\n, Tutar&nbsp; &nbsp; &nbsp;MONEY&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;NULL&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; --&gt; \u0130\u015flem tutar\u0131n\u0131 ifade eder.\n, Bakiye&nbsp; &nbsp; MONEY&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;NULL&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; --&gt; \u015e\u0130MD\u0130L\u0130K BO\u015e, BU KISMI UPDATE SIRASINDA HESAPLATACA\u011eIZ...\n, INDEX IX_TabloDegiskeniIndeksi NONCLUSTERED(Tarih, Islem desc)&nbsp;\n)\n\n--&gt; BEGIN TRANSACTION&nbsp; --&gt; ETK\u0130S\u0130ZD\u0130R, tablo de\u011fi\u015fkenleri bundan etkilenmez (yani bu sat\u0131r\u0131 bu \u00f6rnek \u00f6zelinde silmeniz i\u00e7in hi\u00e7 bir engel yok...)\n\nINSERT INTO @TabloDegiskeni (Tarih, Islem, Tutar)&nbsp; &nbsp; --&gt; Tarih, A\u00e7\u0131klama ve i\u015flem tutar\u0131n\u0131 tablo de\u011fi\u015fkenimize dolduruyoruz...\n&nbsp; VALUES&nbsp; ( '2017-01-06', 'Tahsilat'&nbsp; ,&nbsp; 100 )\n&nbsp; &nbsp; &nbsp; &nbsp; , ( '2017-02-05', 'Tahsilat'&nbsp; ,&nbsp; 110 )\n&nbsp; &nbsp; &nbsp; &nbsp; , ( '2017-03-04', '\u00d6deme'&nbsp; &nbsp; &nbsp;, -150 )\n&nbsp; &nbsp; &nbsp; &nbsp; , ( '2017-04-03', '\u00d6deme'&nbsp; &nbsp; &nbsp;,&nbsp; -50 )\n&nbsp; &nbsp; &nbsp; &nbsp; , ( '2017-05-02', 'Tahsilat'&nbsp; ,&nbsp; 360 )\n&nbsp; &nbsp; &nbsp; &nbsp; , ( '2017-06-01', '\u00d6deme'&nbsp; &nbsp; &nbsp;, -150 )&nbsp; --&gt; Verilerin tarihe g\u00f6re s\u0131ral\u0131 oldu\u011funa dikkat edin. (Sadece devreden bakiye a\u00e7\u0131s\u0131ndan bir \u00f6nemi vard\u0131r)\n\nDECLARE @Devreden&nbsp; &nbsp; &nbsp;MONEY = 0;&nbsp; &nbsp;--&gt; Her bir update i\u015flemi s\u0131ras\u0131nda bu de\u011fi\u015fken bize bir \u00f6nceki update i\u015fleminde elde kalan bakiyeyi unutmammam\u0131z\u0131 sa\u011flayacak.\n\nUPDATE&nbsp; @TabloDegiskeni\nSET&nbsp; &nbsp; &nbsp;@Devreden = Bakiye = @Devreden + ISNULL(Tutar, 0)\n--&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ^&nbsp; &nbsp; &nbsp; &nbsp; ^&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;^&nbsp; &nbsp;&lt;-- E\u015fittir ifadelerine dikkat edelim. --&gt; ROLLBACK TRANSACTION&nbsp; --&gt; ETK\u0130S\u0130ZD\u0130R, tablo de\u011fi\u015fkenleri bundan etkilenmez, e\u011fer etkilenseydi a\u015fa\u011f\u0131daki select ifadesinde tablonun bo\u015f gelmesi gerekirdi... (yani bu sat\u0131r\u0131 bu \u00f6rnek \u00f6zelinde silmeniz i\u00e7in hi\u00e7 bir engel yok...)\n\nSELECT&nbsp; * FROM @TabloDegiskeni\n<\/code><\/pre>\n<p>\u00d6rne\u011fimizin sonucunda olu\u015facak olan tablo ise a\u015fa\u011f\u0131daki gibi olacakt\u0131r;<\/p>\n<pre>ID&nbsp; Tarih&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Islem&nbsp; &nbsp; &nbsp; &nbsp; Tutar&nbsp; &nbsp; Bakiye\n--&nbsp; -----------------------&nbsp; &nbsp;--------&nbsp; &nbsp;-------&nbsp; &nbsp; ------\n1&nbsp; &nbsp;2017-01-06 00:00:00.000&nbsp; &nbsp;Tahsilat&nbsp; &nbsp; 100,00&nbsp; &nbsp; 100,00\n2&nbsp; &nbsp;2017-02-05 00:00:00.000&nbsp; &nbsp;Tahsilat&nbsp; &nbsp; 110,00&nbsp; &nbsp; 210,00\n3&nbsp; &nbsp;2017-03-04 00:00:00.000&nbsp; &nbsp;\u00d6deme&nbsp; &nbsp; &nbsp; -150,00&nbsp; &nbsp; &nbsp;60,00\n4&nbsp; &nbsp;2017-04-03 00:00:00.000&nbsp; &nbsp;\u00d6deme&nbsp; &nbsp; &nbsp; &nbsp;-50,00&nbsp; &nbsp; &nbsp;10,00\n5&nbsp; &nbsp;2017-05-02 00:00:00.000&nbsp; &nbsp;Tahsilat&nbsp; &nbsp; 360,00&nbsp; &nbsp; 370,00\n6&nbsp; &nbsp;2017-06-01 00:00:00.000&nbsp; &nbsp;\u00d6deme&nbsp; &nbsp; &nbsp; -150,00&nbsp; &nbsp; 220,00\n<\/pre>\n<p>Kod \u00f6rne\u011fimizde devreden bakiyeyi hesaplarken pek s\u0131k kar\u015f\u0131la\u015f\u0131lmayan bir tekni\u011fi kulland\u0131m. Bu tekni\u011fin bir benzerini MySQL&#8217;de de kullanabilirsiniz. K\u0131saca teknikten bahsetmek gerekirse SQL Server verileri g\u00fcncellerken (e\u011fer bu bir tablo ise) i\u015fleme tepeden, tablonun en ba\u015f\u0131ndan, yani etkilenecek olan kay\u0131tlar\u0131n en ba\u015f\u0131ndan s\u00fcrece ba\u015flar ve a\u015fa\u011f\u0131ya do\u011fru &#8220;s\u0131rayla&#8221; ilerler. &#8220;@Devreden&#8221; de\u011fi\u015fkeni de bu noktada devreye giriyor. Biz bakiye s\u00fctununu hesaplarken;<\/p>\n<pre><code>UPDATE&nbsp; @TabloDegiskeni\nSET&nbsp; &nbsp; &nbsp;@Devreden = Bakiye = @Devreden + ISNULL(Tutar, 0)\n<\/code><\/pre>\n<p>Yukar\u0131daki sat\u0131rda asl\u0131nda \u015funu s\u00f6ylemi\u015f oluyoruz; @Devreden ile Tutar alan\u0131n\u0131 topla, sonucu Bakiye alan\u0131na yaz. Bakiye alan\u0131n\u0131n yeni de\u011ferini de @Devreden de\u011fi\u015fkenine aktar. demi\u015f oluyoruz.<\/p>\n<p>Devreden Bakiye, Y\u00fcr\u00fcyen Bakiye, Running Total kavram\u0131yla veya hesaplamalar\u0131yla ilgili bir \u00e7ok \u015fey s\u00f6ylenebilir, bir \u00e7ok farkl\u0131 teknik uygulanabilir, yukar\u0131daki \u00f6rne\u011fi bunlardan sadece birisi olarak de\u011ferlendirebilirsiniz.<\/p>\n<h1>Tablo De\u011fi\u015fkeni mi, Ge\u00e7ici Tablo mu?<\/h1>\n<p>Ben, \u015fahsen temp tabloyu veya tablo de\u011fi\u015fkenini nerede kullanaca\u011f\u0131m\u0131 \u015funlara g\u00f6re belirliyorum (Fakat \u00f6nerilere de her zaman a\u00e7\u0131\u011f\u0131m);<\/p>\n<ul>\n<li>Sonu\u00e7 k\u00fcmesinin boyutu, kaplad\u0131\u011f\u0131 \/ kaplayaca\u011f\u0131 alan \u00e7ok yer kapl\u0131yor mu? E\u011fer \u00f6yleyse temp tablo kullanmak sunucunun performans\u0131n\u0131 d\u00fc\u015f\u00fcrmeden sonu\u00e7 k\u00fcmesiyle ba\u015f etmenin en kolay yoludur. B\u00f6yle bir durumda tablo de\u011fi\u015fkeni yerine temp tablo kullanmay\u0131 daha \u00e7ok tercih ederim.<\/li>\n<li>\u00dcretece\u011fim \u00e7\u00f6z\u00fcm\u00fc Stored Procedure kullanarak m\u0131 ger\u00e7ekle\u015ftirece\u011fim? E\u011fer Stored POrocedure kullanacaksam yine temp tabloyu tablo de\u011fi\u015fkenine tercih ederim.<\/li>\n<li>Transaction&#8217;a ihtiyac\u0131m var m\u0131? Varsa yine temp tablo&#8230;<\/li>\n<\/ul>\n<p>Bunlar\u0131n d\u0131\u015f\u0131ndaki durumlarda ge\u00e7ici bir tablo kullanmam gerekiyorsa her zaman tablo de\u011fi\u015fkenini tercih ederim. Dolay\u0131s\u0131yla Tablo De\u011fi\u015fkeni cand\u0131r, Temp tablodan \u00e7ok daha basit, \u00e7ok daha h\u0131zl\u0131 ve ba\u015fetmesi \u00e7ok daha kolayd\u0131r.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Bu yaz\u0131m\u0131zda SQL Server&#8217;da tablo tipindeki de\u011fi\u015fkenleri irdelemeye, onlar\u0131 anlamaya \u00e7al\u0131\u015faca\u011f\u0131m ve nas\u0131l kullan\u0131ld\u0131\u011f\u0131na dair \u00f6rnekler verece\u011fim. Bu \u00f6rneklemelerde ise forumda son zamanlarda s\u0131k\u00e7a duymaya ba\u015flad\u0131\u011f\u0131m\u0131z &#8220;y\u00fcr\u00fcyen toplam&#8221;, &#8220;devreden toplam&#8221;, &#8220;K\u00fcm\u00fclatif toplam&#8221;, &#8220;running total&#8221; gibi adlarla bildi\u011fimiz fakat daha \u00e7ok cari hesap ekstrelerinde g\u00f6sterdi\u011fimiz devreden bakiye hesaplamaya dair \u00f6rnekler vermeye \u00e7al\u0131\u015faca\u011f\u0131m. \u00d6rnekleri karma\u015f\u0131kla\u015ft\u0131rmadan, en basit nas\u0131l olur y\u00f6n\u00fcnde tercihler kullanaca\u011f\u0131m. Ba\u015flayal\u0131m<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[3],"tags":[16,15,11,13,7,14],"class_list":["post-151","post","type-post","status-publish","format-standard","hentry","category-blog","tag-cari-hesap","tag-devreden-bakiye","tag-programlama","tag-running-total","tag-sql-server","tag-table-valued-function"],"_links":{"self":[{"href":"http:\/\/www.potansif.com\/index.php?rest_route=\/wp\/v2\/posts\/151","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/www.potansif.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.potansif.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.potansif.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/www.potansif.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=151"}],"version-history":[{"count":1,"href":"http:\/\/www.potansif.com\/index.php?rest_route=\/wp\/v2\/posts\/151\/revisions"}],"predecessor-version":[{"id":152,"href":"http:\/\/www.potansif.com\/index.php?rest_route=\/wp\/v2\/posts\/151\/revisions\/152"}],"wp:attachment":[{"href":"http:\/\/www.potansif.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=151"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.potansif.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=151"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.potansif.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=151"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}