SQL - Text alandan Numeric alana aktarma nasıl yapılır ?

Diğer veritabanları ve SQL komutlarıyla ilgli sorularınızı sorabilirsiniz. Delphi tarafındaki sorularınızı lütfen Programlama forumunda sorunuz.
Cevapla
Kullanıcı avatarı
mrmarman
Üye
Mesajlar: 4741
Kayıt: 09 Ara 2003 08:13
Konum: İstanbul
İletişim:

SQL - Text alandan Numeric alana aktarma nasıl yapılır ?

Mesaj gönderen mrmarman »

Selamlar...

- Kaynak veritabanı, kullanıcı tarafından kullanılan eski bir Access veritabanı. Bende mevcut değil. Verilerin gizliliği gerekçesiyle inceleme şansım olamıyor.

- ADO ile yeni bir Access veritabanına aktarım yapılacak. Text tipinde olan alanlardan birisi hesaplamada kullanılmak üzere yeni veritabanında Numeric olarak tanımlandı ve buna aktarılacak.

- Aktarma işlemi için basit bir SQL INSERT INTO satırım var...

Kod: Tümünü seç

  With TAdoQuery.Create(Nil) do
  begin
    ConnectionString := Format(sBaglantiString, [YeniDosyaAdi]);
    SQL.Clear;
    SQL.Add('INSERT INTO Tablo1 ( Alan1_String  ,Alan2_Numeric )          ');
    SQL.Add('SELECT               Eski1_String  ,''0''+Trim(Eski2_String) ');
    SQL.Add('FROM EskiTablo IN ' + QuotedStr(EskiDosyaAdi)                 );
    ExecSQL;
    Free;
  end;
- Düne kadar hep yukardaki kod ve türevlerini kullandım. Ta ki bugün başlıktaki hata ile karşılaşıldığını öğrenene kadar. Telefonla inceleme yapmalarını istediğimde numeriğe dönüşecek alan içeriğinde bazı kayıtlarda "var", "yok" gibi daha başkaları var mı bilemediğin metinsel girdiler olduğunu öğrendim. Bunlar biliniyor olsaydı UPDATE ederek önce bunları temizlerdim ama durum elvermiyor.

- Aslında Numeric bir alana String bir alandan aktarma yapılabiliyor. Mevcut string değer rakamsal ifade içeriyorsa onlar numeric alana otomatik dönüşüyorlardı.

- Yukardaki örnekte TRIM ettiğimde boşluklar atılıyor, Null kalmasın diye başına '0' da ekleyip öyle gönderiyorum sorun yok ama string ifadelerle karşılaştığında "Ölçüt ifadesi veri türü uyuşmazlığı" hatasını alıyorum.

- Bunu aşmak için nasıl bir sorgu kullanabilirim içinden çıkamadım.

- Delphi fonksiyonlarından VAL() fonksiyonu gibi hata olsa da hatalı sonucu 0'a çeken bir fonksiyon SQL için de var mıdır ?

- Sıralı aktarma yapmak da oldukça uzun zaman alacağından tercih etmiyorum.
En son mrmarman tarafından 18 Haz 2006 01:14 tarihinde düzenlendi, toplamda 1 kere düzenlendi.
Resim
Resim ....Resim
Kullanıcı avatarı
mrmarman
Üye
Mesajlar: 4741
Kayıt: 09 Ara 2003 08:13
Konum: İstanbul
İletişim:

Mesaj gönderen mrmarman »

Tekrar merhaba...

- Çözüm olarak basit düşünmeyi tercih edip şöyle bir uygulamaya girdim. :idea: Hızı da fena olmadı. Umarım ana veritabanında da aynı performansı gösterir.

- Öncelikle veritabanının bir kopyası alınıyor ve bu kopya üzerinde işlem yapılıyor.

- Alan içeriğinde 26 adet harf sırasıyla sorgulanarak, içeriğinde bu harflerden herhangi biri varsa alan değeri tümüyle '0' set ediliyor.

Kod: Tümünü seç

Var
 HarfSay : Integer;
begin
 With AdoQuery.Create(Nil) do
 begin
   For HarfSay := 97 to 122 do // a..z tüm harfler...
   begin
     SQL.Clear;
     SQL.Add('UPDATE EskiTablo IN ' + QuotedStr(EskiDosyaAdi) );
     SQL.Add('SET Eski2_String = ''0''                       ');
     SQL.Add('WHERE Eski2_String Like '+QuotedStr('%'+Chr(HarfSay)+'%') );
     ExecSql;
   end;
   Free;
 end;
end;
- Yine de SQL bilgim adına direkt string alandaki numeric ifade dönüşümünde hata oluştuğunda 0 döndüren bir fonksiyon varsa bildirirseniz sevinirim. Sorunum şimdilik çözüldü. 8)
Resim
Resim ....Resim
onaydin
Üye
Mesajlar: 202
Kayıt: 07 Şub 2006 02:30

Mesaj gönderen onaydin »

Soruyu tam anlamamış olabilirim.
Bir alan içindeki ifadenin sayısal bir değer olup olmadığını anlamak için upper(alan_metin) = lower(alan_metin)
şeklinde bir ifade kullanıyorum böyle olunca sayısal ifadeler doğru sonuç dönderiyor aksi durumda diğerleri listelenmiyor.
Kullanıcı avatarı
mrmarman
Üye
Mesajlar: 4741
Kayıt: 09 Ara 2003 08:13
Konum: İstanbul
İletişim:

Mesaj gönderen mrmarman »

@onaydın

- Yaklaşımın çok güzel. Her ne kadar presibi anlamasam da sonuç kısmen çözüme ulaştı. :idea: Şöyle ki...

- Yeni kodu şu şekilde derledim... ADO için UPPER ve LOWER yerine UCASE ve LCASE kullandım... :!:

Kod: Tümünü seç

  With TAdoQuery.Create(Nil) do
  begin
    ConnectionString := Format(sBaglantiString, [YeniDosyaAdi]);
    SQL.Clear;
    SQL.Add('INSERT INTO Tablo1 ( Alan1_String  ,Alan2_Numeric )           ');
    SQL.Add('SELECT Eski1_String  ,UCASE(Eski2_String)=LCASE(Eski2_String) ');
    SQL.Add('FROM EskiTablo IN ' + QuotedStr(EskiDosyaAdi)                  );
    ExecSQL;
    Free;
  end;
- Sonuç kısmen tatmin edici. içeriğinde virgül olan kayıtlar tamsayı olarak doğru aktarılmış ama sadece 1, 2 veya 3 haneden oluşan rakamlar (1000'den küçük rakamlar yani virgül ayracı bulunmayanlar) "-1" olarak kabul edilmiş. :?:

ResimResim

- Bunu "=" değil de "<>" şeklinde fark olarak güncellediğimde yine virgüllü rakamlar düzgün aktarılmış, virgül içermeyen tamsayı değerler ise bu sefer "-1" yerine "0" değeri almış oluyor... :?:

- Bu durumda sormak istediğim konu, nasıl oluyor da bu boolean eşitlik rakam döndürebiliyor. Bunu çözümlersem eşitliği hepsi virgül olacak şekilde bozabilirim. :?: :?: :?:

- Keza denedim. Kodda

Kod: Tümünü seç

UCASE(Eski2_String)=LCASE(Eski2_String)
kısımlarını forced bir şekilde başına bir adet 0 ve virgül ekleyip (sonuçta soldaki sıfır etkisiz olacağından ihmal edilebilir bir değişiklik kabul ediyordum)

Kod: Tümünü seç

UCASE(''0,''+Eski2_String)=LCASE(''0,''+Eski2_String)
şeklinde güncelledim. :shock:

- Garip bir şekilde sonuç hiç değişmedi. Sanki ben bu eklemeyi hiç yapmamışım gibi davranıp eski şekilde sonuç döndürdü. :(

- Bu konuda bir fikriniz var mı ? Konu ilginç bir hal aldı açıkçası. En azından benim için... :roll:
Resim
Resim ....Resim
fduman
Moderator
Mesajlar: 2749
Kayıt: 17 Ara 2004 12:02
Konum: Ankara

Mesaj gönderen fduman »

mrmarman yazdı: - Yine de SQL bilgim adına direkt string alandaki numeric ifade dönüşümünde hata oluştuğunda 0 döndüren bir fonksiyon varsa bildirirseniz sevinirim.
Böyle bir func olduğunu zannetmiyorum. Bunu yapabilmek için exception benzeri bir yapı veya bir stored proc kullanmak gerekiyor. Tek satırlık bir SQL'de böyle bir yapı hiç görmedim. Bence şu an uyguladığın çözüm gayette iyi olmuş.

Görüşürüz.
onaydin
Üye
Mesajlar: 202
Kayıt: 07 Şub 2006 02:30

Mesaj gönderen onaydin »

Yukarda söylediğim mantık accesste çalışmıyor olabilir ama firebird dahil birçok veritabanında tek satırlık bir sql le geçiştirilebilecek bir durumdur.
Kullanıcı avatarı
ofenX
Üye
Mesajlar: 397
Kayıt: 09 Nis 2005 10:24
Konum: Diyarbakır
İletişim:

Mesaj gönderen ofenX »

Merhaba,
Mssql deki isnumeric fonksiyonu işinize yaramazmı acaba?
Bununla ilgili bir örneği aşağıdaki linkte vermiştim.
viewtopic.php?t=11647

Önce numeric olanları aktarır sonra numeric olmayanları tespit edip sıfır yaparsınız.

Kolay gelsin.
http://www.aysbergbilgisayar.com
Logo Go özel eğitim, web tasarım, teknik servis
Kullanıcı avatarı
mrmarman
Üye
Mesajlar: 4741
Kayıt: 09 Ara 2003 08:13
Konum: İstanbul
İletişim:

Mesaj gönderen mrmarman »

@ofenX

- Basite indirgemek için ilk aklıma gelen fikri denemiştim. a'dan z'ye harf döngüsü kontrolü. IsNumeric çalışıyor. Beni 26 tane SQL sorgusundan kurtardın bunu teke indirgedin, teşekkürler..

- Bu döngü veya ön SQL sorgusuna ihtiyaç olmadan @onaydin'ın önerisi gibi direkt ana SQL içinde nasıl kullanabilirim. Bu konuda fikrin var mı ? Çok sevinirim.

- Ek olarak, her ikinizin önerilerini de birarada denemeye çalıştım.

Kod: Tümünü seç

TRIM(M_VoteCount) AND IsNumeric(TRIM(M_VoteCount))
- Sonuç yine -1 veya 0 şeklinde...

- Elde etmek istediğim sorguyu yine saçma bir örnek ile açayım...

Kod: Tümünü seç

    SQL.Add('SELECT Eski1_String  ,IsNumeric(Eski2_String) <then>(Eski2_String) '); 
- Tekrar her ikinize de teşekkürler..
Resim
Resim ....Resim
Kullanıcı avatarı
ofenX
Üye
Mesajlar: 397
Kayıt: 09 Nis 2005 10:24
Konum: Diyarbakır
İletişim:

Mesaj gönderen ofenX »

Merhaba,
Aşağıdaki gibi bir kullanım bende çalıştı.

Kod: Tümünü seç


INSERT INTO MRARMAN2 (LR,RAKAM)

SELECT LR,

case ISNUMERIC(STR)
when 0     THEN 0    

  ELSE   CONVERT (INT ,STR )    END 


from MRARMAN
MRARMAN table ında
  • LR STR
    -- -------
    1 1254
    2 1A54
    3 12
    4 142
    5 A142
    6 665
değerleri vardı. MRARMAN2 Tablesine
  • LR RAKAM
    ----- --------
    1 1254
    2 0
    3 12
    4 142
    5 0
    6 665
olarak aktardı.

Bir deneyin. olmazsa başka bir yola bakarız.
http://www.aysbergbilgisayar.com
Logo Go özel eğitim, web tasarım, teknik servis
Kullanıcı avatarı
mrmarman
Üye
Mesajlar: 4741
Kayıt: 09 Ara 2003 08:13
Konum: İstanbul
İletişim:

Mesaj gönderen mrmarman »

Selam...

- EUREKA :idea:

- Arkadaşlar müjde... Şu meşhur IF sorgusunu buldum sonunda... :lol:

Kod: Tümünü seç

SQL.Add('SELECT Eski1_String  ,IIF(IsNumeric(Eski2_String), Eski2_String, ''0'') ');
- İşte budur ... Oh yaa yağlarım eridi doğrusu.. Zaten çözüm üretmiştik ama böyle bir çözüm tek adımda işi bitiriyor.

- Zaten başlığı yeniden takip ederseniz alt metin olarak neden böyle bir IF sorgusunun konmadığı konusunda gizli eleştirimi ve aslında var da ben bulamıyorum sorgusunu hissedeceksiniz. :oops:

- Vakit ayırdığınız için teşekkürler. Sayenizde yeni bir çok şey öğredim.
Resim
Resim ....Resim
Kullanıcı avatarı
rsimsek
Admin
Mesajlar: 4482
Kayıt: 10 Haz 2003 01:48
Konum: İstanbul

Mesaj gönderen rsimsek »

Hocam IIF(Koşul, True, False) şeklindeki fonksiyon Clipper ile yazarken çok sık kullandığım bir if fonksiyondu. Doğrusu aklıma geldi fakat access in destekleyip desteklemediğinden emin olamadım :? @ofenx in çözüm önerisi de fena değil :wink:
Bilgiyi paylaşarak artıralım! Hayatı kolaylaştıralım!!
Kullanıcı avatarı
mrmarman
Üye
Mesajlar: 4741
Kayıt: 09 Ara 2003 08:13
Konum: İstanbul
İletişim:

Mesaj gönderen mrmarman »

@ofenx'in önerisi de çok güzel. Katılıyorum. 8)

- Zaten ADO'daki kurgu bu tip olmadığından araştırırken vesile oldu da IIF sorgusunu buldum. Neye niyet neye kısmet... :idea:
Resim
Resim ....Resim
Cevapla