SQL Database'de numeric ve float alan kullanım problemi

Delphi'de kod yazma ile ilgili sorularınızı bu foruma yazabilirsiniz.
Cevapla
mmg
Üye
Mesajlar: 128
Kayıt: 20 Haz 2014 12:47

SQL Database'de numeric ve float alan kullanım problemi

Mesaj gönderen mmg »

Merhabalar,

Daha öncede gündeme getirmiştim fakat tam bir sonuç alamadığım bir problemim devam ediyor, yardımlarınızı rica ediyorum.

Delphi 10.2 ve ADO bağlantı ile SQLEXPRESS kullanıyorum.

Sayısal alanlarda "Numeric" alan tipini kullanmak istiyorum fakat yaşadığım problemlerden dolayı mecburen "Float" ala tipini kullanmak zorunda kaldım. Bu problemleri aşağıda anlatmaya çalıştım, yardımlarınızı rica ediyorum.

Tabloda "Numeric" alan tipi seçersem ve 0.0217885 sayısını uygulamamdan tabloya kaydedersem eğer 0.02179 olarak kaydediyor ve ondalık kısmı yuvarlıyor. Tabloda alan tipi "Numeric(28,10)" olarak tanımlıdır. Aynı değeri tabloya elimle girersem eğer hiç bir problem olmuyor. Bu problem ADO ile ilgili olabilir mi ? Eğer öyle ise bir çözümü var mıdır ?

Forumda daha önce sorduğumda "ertank" arkadaşımız yuvarlamadan kaydetmesi için aşağıda ki gibi (UPDATE kod bloğundaki gibi) bir yöntem kullanmamı önermişti. Kaydederken "DataType" belirtmemi önermişti. Bende deneme yaptım bu yöntemi ve arkadaşımızın dediği gibi gerçekten sayısı tabloya olduğu gibi doğru bir şekilde yuvarlamadan kaydetti. Bu denemede ben tabloya bir değişken tanımlayarak o değişkenin değerini kaydettim. Bu çalıştı.

Fakat, Aşağıda kod blokta görüldüğü şekilde bir tabloda ki numeric tipinde ki "FIYAT" alanına başka bir tablodaki yine numeric tipindeki "FIYAT" alanını aktarmak istediğimde derlerken aşağıda görülen hatayı veriyor. Stok tablosundaki "FIYAT" analının tipide "Numeric", "DM1.ST_LISTE" tablosundaki "FIYAT" alanının tipide "Numeric" olmasına rağmen bu hatayı niçin veriyor olabilir ?

UPDATE:

Kod: Tümünü seç

    DM1.ST_STOK.Close;
    DM1.ST_STOK.SQL.CLEAR;
    DM1.ST_STOK.SQL.Add('UPDATE STOK SET FIYAT= :vFIYAT');
    DM1.ST_STOK.SQL.Add('WHERE STOK_NO= :vSTOK_NO');
    DM1.ST_STOK.Parameters.ParamByName('vSTOK_NO').value:= vSTOK_NO; 
    DM1.ST_STOK.Parameters.ParamByName('vFIYAT').DataType:= ftFloat;
    DM1.ST_STOK.Parameters.ParamByName('vFIYAT').Value:= DM1.ST_LISTEFIYAT.Value;
    DM1.ST_STOK.ExecSQL;
HATA:

Kod: Tümünü seç

[dcc32 Error] U_LISTE_BRW.pas(1492): E2010 Incompatible types: 'Variant' and 'TBcd'
Hatası veriyor.

Bu problemi aşamadığım için mecburen sayısal alanlar için alan tipi olarak "Float" seçmek zorunda kaldım. Bugüne kadar iyi kötü geldik fakat şimdide "Float" alan tipinde bir problem çıktı karşıma.

0.000001 sayısını uygulamamdan tabloya kaydedince tabloda değeri "1E-06" şeklinde gösteriyor. Aynı değeri tabloya elimle girincede bir şey değişmiyor yine "1E-06" şeklinde gösteriyor. Alan değerini database'de göremiyorum fakat uygulama ekranında doğru olarak görüyorum. İlginç olan aynı ondalık basamak sayısına sahip farklı sayılarda tabloda değer doğru olarak gözüküyor. Örneğin 6.525232 değerini uygulamadan kaydedip database de doğru olarak görebiliyorum. "1E-06" olarak tabloda durduğu için bu alanı uygulamada bir hesaplamada kullanmak istediğim zaman kullanamıyorum. Değeri görmüyor hesaplamada. Böylece "Float" alan tipini serüveninin de sonuna gelmiş oldum. Doğrudan database'de de bu rakamı girince aynı problemi gördüğüm için bu problemin ADO ile bir ilgili olduğunu düşünmüyorum. Sebebi ne olabilir ? Bir çözümü var mıdır ?

SQL ve ADO kullanan arkadaşlarım siz sayısal alanlar için "Numeric" alan tipini nasıl kullanıyorsunuz ? Sizler virgülden sonraki ondalık basamakları nasıl kaydedebiliyorsunuz, ben neden kaydedemiyorum, bir yerde eksik bir şeyler mi var ? Bir ayar mı yapılması gerekiyor ? Bunu gerçekten çok merak ediyorum. Çoğunluğun kullandığı SQL ve ADO ile hiç bir sorun yaşanmadan bu sayısal işlemler yapılabilirken ben neden "Numeric" alan tipini kullanamıyorum, veya "Float" alan tipinde bu saçma problemi neden yaşıyorum. Ben sayısal alanlarda "Float" yerine "Numeric" alan tipini kullanmak istiyorum aslında fakat problemlerden dolayı kullanamıyorum. Ustalarımızın yardım ve önerilerini rica ediyorum.
Kullanıcı avatarı
tuna
Üye
Mesajlar: 300
Kayıt: 07 Tem 2008 04:39
Konum: İstanbul

Re: SQL Database'de numeric ve float alan kullanım problemi

Mesaj gönderen tuna »

Merhaba. Parasal işlemler için numeric kullanılmaz.
Ben ado ve mssql ile yıllardır proje geliştiriyorum.
Fakat numeric ile hiçbir işlem yapmadım.
Şöyle bir örnek vereyim LOGO Yazılım bile sql tablolarında parasal işlemleri yazacağı alanlarda FLOAT kullanır.
Numeric alanlar belli bir değere kadar veri alır sonrasını yuvarayarak keser.
mmg
Üye
Mesajlar: 128
Kayıt: 20 Haz 2014 12:47

Re: SQL Database'de numeric ve float alan kullanım problemi

Mesaj gönderen mmg »

Merhaba,

Peki Float kulanayım da zaten yukarda detaylı olarak anlattığım mecburiyetten dolayı Float kullanıyorum fakat Float ile yaşadığım yukarda belirttiğim problemi nasıl aşabilirim ?
Kullanıcı avatarı
freeman35
Admin
Mesajlar: 2380
Kayıt: 12 Haz 2003 04:05
Konum: merkez camii yanı

Re: SQL Database'de numeric ve float alan kullanım problemi

Mesaj gönderen freeman35 »

Gözünü seveyim firebird :)
Mikro yazılım evine yazdığım eklentiler haricinde hiç mikisql kullanmadım. Bir iki tavsiyem olacak. Öncelikle "DM1.ST_LISTEFIYAT.Value;" Field ları değişkenler üzerinden kullanma, fieldbyname ile Tfield üzerinden eriş. Diğeri mümkün olduğunca variant tip kullanma. pascal belirsizliği pek sevmez. Ne olduğunu bildiğin şeyi neden belirsiz deyip, tekrar tekrar denersin ki? Bu yüzden şu ado da parametre classına neden ısrarla asxxx diye eklemezler anlamış değilim.
Bir diğer konu ise "elle girmek" ne demek anlamadım??
"1E-06" şeklinde sayı görmek format ile alakalı olabilir, Displayformat verip bakamayı denedin mi?
DM1.ST_STOK.SQL.Add('UPDATE STOK SET FIYAT= :vFIYAT');
DM1.ST_STOK.SQL.Add('WHERE STOK_NO= :vSTOK_NO');

yerine
DM1.ST_STOK.SQL.Add('select FIYAT from STOK');
DM1.ST_STOK.SQL.Add('WHERE STOK_NO= :vSTOK_NO');
DM1.ST_STOK.Open;
DM1.ST_STOK.Edit;
DM1.ST_STOK.FieldByName('FIYAT').AsFloat:= DM1.ST_LISTE.FieldByName('FIYAT').Asfloat
DM1.ST_STOK.Post;
dene.
Ayrıca db de float olmasının nasıl bir dez avantajı var? numaric ile kısıtlamak ne sağlıyacak? Ben ısrarla float kullanma taraftarıyım, sonuçlar hasas olarak alınır. Göstermek istenirken display format ile formatlayabiliyorsam neden db de kısıtlı yazayım ki?
kolay gele
ZAGOR TENAY TÜRK'tür... TÜRK kalacak...
Zoru başarırım, İmkansız zaman alır
FreeMan 35.5

Soru sormaya üşenmiyorsan, sorunun çözümünü yazmaya da üşenme !!!
Kullanıcı avatarı
tuna
Üye
Mesajlar: 300
Kayıt: 07 Tem 2008 04:39
Konum: İstanbul

Re: SQL Database'de numeric ve float alan kullanım problemi

Mesaj gönderen tuna »

mmg yazdı: 27 Eki 2020 06:54 Merhaba,

Peki Float kulanayım da zaten yukarda detaylı olarak anlattığım mecburiyetten dolayı Float kullanıyorum fakat Float ile yaşadığım yukarda belirttiğim problemi nasıl aşabilirim ?

Float ile 0,000001 sayısının saklanması konusunda hiçbir problem yoktur.
Siz sql management studio ile baktığınız da bu şekilde görmeniz gayet doğal. Çünk managament studionun gösterim şekli öyle.
Kaldıki siz bu verileri management studio ile değil yazdığınız programdan görüntüleyeceksiniz.
Float alanının sorunsuz çalıştığını anlamak için
select Floatalanadınız*1000 from tabloadınız sorgusunu çalıştırın hesap yapıp sonucu size verecektir.
Yada yazılımınızdaki grid nesnesinden sonuca bakın yine 0,000001 değerini göreceksinizdir.
ertank
Kıdemli Üye
Mesajlar: 1716
Kayıt: 12 Eyl 2015 12:45

Re: SQL Database'de numeric ve float alan kullanım problemi

Mesaj gönderen ertank »

mmg yazdı: 25 Eki 2020 07:44 Sayısal alanlarda "Numeric" alan tipini kullanmak istiyorum
Bunu yapmanızda bir engel yok bildiğim kadarıyla.
mmg yazdı: 25 Eki 2020 07:44 HATA:

Kod: Tümünü seç

[dcc32 Error] U_LISTE_BRW.pas(1492): E2010 Incompatible types: 'Variant' and 'TBcd'
Hatası veriyor.
Aşağıdaki şekilde denediğimde sorunsuz şekilde veritabanında değer güncellemesi yapıldı.

Kod: Tümünü seç

  ADOCommand1.CommandText := 'UPDATE STOK SET FIYAT= :vFIYAT WHERE STOK_NO= :vSTOK_NO';
  ADOCommand1.Parameters.ParamByName('vFIYAT').DataType := ftString;
  ADOCommand1.Parameters.ParamByName('vSTOK_NO').DataType := ftCurrency;

  ADOCommand1.Parameters.ParamByName('vSTOK_NO').Value := '2';
  ADOCommand1.Parameters.ParamByName('vFIYAT').Value := '0.56789';
  ADOCommand1.Execute();
Benim test tablom aşağıdaki şekilde tanımlanmış durumda

Kod: Tümünü seç

CREATE TABLE STOK(
	STOK_NO varchar(10),
	FIYAT numeric(18, 4)
);
vFIYAT alanı numeric(18,4) olarak tanımlı olduğu için değeri otomatik olarak veritabanı tarafından 0.5679 olarak kayıt edildi. 4 haneye yuvarlama yaptı.
mmg yazdı: 25 Eki 2020 07:44 SQL ve ADO kullanan arkadaşlarım siz sayısal alanlar için "Numeric" alan tipini nasıl kullanıyorsunuz?
Her ne kadar yukarıda nasıl kullanılabileceğine dair örnek vermiş olsam da benim tavsiyem mümkün ise veritabanı erişim bileşenlerinizi değiştirmeniz. Bileşen olarak tavsiye sırası ile SDAC, UniDAC, FireDAC içinden birini tercih edebilirsiniz. ADO bileşenlerini şahsen pek tercih etmem ve zorunda kalmadıkça kullanmam. Yukarıdaki tüm bileşenler aşağıdaki kullanım şekillerini destekler

Kod: Tümünü seç

  Bilesen.ParamByName('vFIYAT').AsCurrency := Currency_Degiskeni_ya_da_Degerin_Kendisi;
  Bilesen.ParamByName('vFIYAT').AsBCD := BCD_Degiskeni_ya_da_Degerin_Kendisi;
Bilesen.ParamByName('vFIYAT').Value şeklinde veri atama ve okuması yapmanızı tavsiye etmem. Derleme zamanında bulabileceğiniz hataları bu şekildeki kullanımlarda tespit etmeniz mümkün olmaz. Çalışma zamanında da anlam veremediğiniz hatalar ile karşılaşırsınız. Birçok kişinin bir sebepten ".Value" şeklinde kullanım yaptığını görüyorum.

".Value" şeklindeki kullanım arka planda Variant veri türü ile işlem yapmak anlamına geliyor. Şahsen mümkün olduğunca Variant kullanmaktan kaçınırım. ADO bileşenleri ise tam aksine tüm işlemleri Variant veri türü ile yapıyor gibi gözüküyor.
mmg
Üye
Mesajlar: 128
Kayıt: 20 Haz 2014 12:47

Re: SQL Database'de numeric ve float alan kullanım problemi

Mesaj gönderen mmg »

ertank, çok teşekkürler, çok net anladım. İlk fırsatta ADO bileşenini bırakıp önerdiğiniz farklı bağlantı bileşenlerinden birine geçeceğim. Şu an bana Delphi'de hazır olduğu için FireDAC bileşeni yakın duruyor. Bileşen değiştirme konusu açıkçası beni düşündürüyor biraz, çok kolay olmayacak gibi düşünüyorum. Önerebileceğiniz bir yöntem var mı ?
Cevapla