FB/IB'de SQLDialect'e göre alanların DataType tanımı nedir ?

Firebird ve Interbase veritabanları ve SQL komutlarıyla ilgli sorularınızı sorabilirsiniz. Delphi tarafındaki sorularınızı lütfen Programlama forumunda sorunuz.
fduman
Moderator
Mesajlar: 2749
Kayıt: 17 Ara 2004 12:02
Konum: Ankara

FB/IB'de SQLDialect'e göre alanların DataType tanımı nedir ?

Mesaj gönderen fduman »

// EDIT by @mrmcop //
- Başlığı ben açtım ama taşırken ilk mesaj @coderlord'unkiydi. Sanki o açmış gibi oldu. Kusura bakmayın... :oops:
+++++++++++++++++++++++++++++++++++++++++++++++
mrmcop yazdı: @coderlord Cidden açmamı ister misiniz ? Ben şaka diye algılamıştım. Yarışma adına bir olumsuzluk olmasın.. ?
Evet kodları cidden açmanı isterdim. Tabii sana kalmış birşey. Gerçi madem açacaksın sonunda, şimdi açman daha güzel olur. Ben yarışma için negatif bir etki yaratacak birşey göremiyorum. Senin kodunu kullanacak arkadaşlar olacaktır. Amaç bunları engellemekse açık kaynak kod yarışması hiç düzenlenmesin o halde. Olay budur çünkü. Zaten yapılmış olan üzerinde uğraşmamak. Herneyse sizin takdirinize kalmış.
Kullanıcı avatarı
mrmarman
Üye
Mesajlar: 4741
Kayıt: 09 Ara 2003 08:13
Konum: İstanbul
İletişim:

Mesaj gönderen mrmarman »

- Yarışma için katılımcıların başlangıç noktası olması fikrine katılmıyorum. Günahıyla sevabıyla benim projem diyebilmeliler. -şahsi fikrim- Boş bir form açıp şimdi neyle başlayayım demek zevkine gölge düşürmeyi istemem. :wink:

- İlerleyen zamanlarda zaten takılınan noktalar sorulacaktır. İşte bu zamanlarda kısım kısım açmak, soru soruldukça neyi neden yaptığımı makale şeklinde açıklamak şimdilik en doğrusu gibi geliyor... :roll:

- Ayrıca FireBird'i ben de yeni öğreniyorum. Bazı ikilemleri yaşıyorum. Örneğin NUMERIC alanları inceledin mi ? Sen daha iyi bilirsin... Bak önce girizgah, sonra bir soru ve takip eden cevap... :lol: :lol: :lol:

- InterBase6 Language Referance - System Table ve View kısmındaki RDB$FIELDS'ın fieldlerinden RDB$FIELD_SUB_TYPE için;

- Blob, Char ve Integer'lere ait farklılıkları/istisnaları belirtmeye yarar ifadesi kullanılmış ve devam edilmiş.(Used to distinguish types of Blobs, CHARs, and integers)

- 1. ve 2. istisnalar şimdilik ilgilendirmiyor BLOB ve CHAR alanlaradır.

- 3. istisna: Eğer RDB$FIELD_TYPE değeri 7 (SMALLINT), 8 (INTEGER), veya 16 (INT64) ise original declaration için yeni CASE şudur...

- Eğer RDB$FIELD_SUB_TYPE değeri
0 veya NULL ise RDB$FIELD_TYPE neyse odur.
1 ise NUMERIC'dir (Dialect'e baktım ve ona göre Precision ve Scale okudum)
2 ise DECIMAL'dir (Dialect'e baktım ve ona göre Precision ve Scale okudum)

SORU:
- Bir alan var (Veritabanı :EMPLOYEE.GDB Tablo:SALES AlanAdı :TOTAL_VALUE)
- Bu alan Field_Type değeri 8 SubType değeri 0
- EMS ve IBExpert ile ile baktığımda ise bu şartlara uyan (SQLDialect 1) örnek veritabanındaki alan açılımı NUMERIC(9, 2) olarak bildirdiğini görüyorum. Bende DECIMAL(9, 2) çıkıyor. Gerekli güncellemeyi yapıcam ama atladığım nokta neresi ?

CEVAP:
- Büyük bir ihtimalle Dialect 1'de DECIMAL yok, NUMERIC var. Kontrol edicem. Bu farkı şimdilik ihmal ediyorum daha sonra dönücem... :idea:

- İfade edebilmiş miyim... Bu sayede kodları şimdi açarsam belki de hata'ya sevkedicem. Bunu da istemiyorum.

- Bu arada yukardaki sorum ve cevabım doğru mudur ? :lol: :lol: SQLDialect'e göre FieldListesi olan bir site bulamadım... Gören duyan varsa yazdın lütfen :)
Resim
Resim ....Resim
fduman
Moderator
Mesajlar: 2749
Kayıt: 17 Ara 2004 12:02
Konum: Ankara

Mesaj gönderen fduman »

FB VT yapısı ile daha önce ilgilenmedim. Bu sayede biraz araştıralım dedim.

Firebird resmi sitesinde http://firebird.sourceforge.net/index.p ... #q0000.dat linkinde diyor ki:
SQL Item Dialect 3 Dialect 2 * Dialect 1 **
NUMERIC(11,*) 64 bit int 64 bit int (with warning?) double precision
Yani dialect 1 de double precision olarak saklanıyor. Bunun da field type ı 27.

Claudio Valderamma nın sitesinde bir açıklama yer almış.

http://www.cvalde.net/document/extracti ... rom_ib.htm

IB Expert denemelerinde dialect 1 de DECIMAL tanımlanan alanların NUMERIC olarak gösterildiği görülüyor. Tablomda 2 numeric ve bir double precision alan var.

Bir sorgu çalıştırıyorum.

Kod: Tümünü seç

SELECT a.RDB$RELATION_NAME, c.RDB$FIELD_TYPE,  b.RDB$FIELD_NAME, b.RDB$FIELD_ID, d.RDB$TYPE_NAME,
c.RDB$FIELD_LENGTH, c.RDB$FIELD_SCALE
FROM RDB$RELATIONS a
INNER JOIN RDB$RELATION_FIELDS b
ON a.RDB$RELATION_NAME = b.RDB$RELATION_NAME
INNER JOIN RDB$FIELDS c
ON b.RDB$FIELD_SOURCE = c.RDB$FIELD_NAME
INNER JOIN RDB$TYPES d
ON c.RDB$FIELD_TYPE = d.RDB$TYPE
WHERE a.RDB$SYSTEM_FLAG = 0
AND d.RDB$FIELD_NAME = 'RDB$FIELD_TYPE'
ORDER BY a.RDB$RELATION_NAME, b.RDB$FIELD_ID
Sonuçlarda field type ve 27, name double precision olarak dönüyor. O halde IB Expert bu alanın numeric tanımlandığını nereden anlıyor? Field scale'ine bakıyor. 0 ise double prec. 0 dan farklı ise numeric diyerek alanı isimlendiriyor.
fduman
Moderator
Mesajlar: 2749
Kayıt: 17 Ara 2004 12:02
Konum: Ankara

Mesaj gönderen fduman »

Dialect 3 de alan tipini belirlemek kolay.

Kod: Tümünü seç

SELECT a.RDB$RELATION_NAME, c.RDB$FIELD_TYPE, c.RDB$FIELD_SUB_TYPE, b.RDB$FIELD_NAME, b.RDB$FIELD_ID, d.RDB$TYPE_NAME,
c.RDB$FIELD_LENGTH, c.RDB$FIELD_SCALE
FROM RDB$RELATIONS a
INNER JOIN RDB$RELATION_FIELDS b
ON a.RDB$RELATION_NAME = b.RDB$RELATION_NAME
INNER JOIN RDB$FIELDS c
ON b.RDB$FIELD_SOURCE = c.RDB$FIELD_NAME
INNER JOIN RDB$TYPES d
ON c.RDB$FIELD_TYPE = d.RDB$TYPE
WHERE a.RDB$SYSTEM_FLAG = 0
AND d.RDB$FIELD_NAME = 'RDB$FIELD_TYPE'
ORDER BY a.RDB$RELATION_NAME, b.RDB$FIELD_ID
select e bir de sub_type ekliyorum. Herbirinin sub type ları istenen şekilde geliyor ve ayrım yapılabiliyor.

Dialect 1 de sorguya sub type eklendiğinde, sub type lar null olarak döndüğünden bu şekilde bir ayrım mümkün görünmüyor.
Kullanıcı avatarı
mrmarman
Üye
Mesajlar: 4741
Kayıt: 09 Ara 2003 08:13
Konum: İstanbul
İletişim:

Mesaj gönderen mrmarman »

- Vakit ayırmana sevindim.. :)

Field_Scale'e bakıp yorumladığı aşikar, bunun farkındayım. Ben de bir çok örneğini yakalım ama, asıl sorum şuydu; NUMERIC yazmayı DECIMAL'e neden tercih ediyor ?

- Örnek olarak yazıyorum yanlış olabilir, SQLDialect 1'de mutlaka NUMERIC, 3'de DECIMAL yazılır gibi bir kaynak arıyorum...
Resim
Resim ....Resim
fduman
Moderator
Mesajlar: 2749
Kayıt: 17 Ara 2004 12:02
Konum: Ankara

Mesaj gönderen fduman »

Zannedersem bu yazım numeric ve decimal alanlar arasındaki farktan kaynaklanıyor.

http://firebird.sourceforge.net/manual/ ... types.html linkinde şöyle diyor.
A subtle difference in the way NUMERIC and DECIMAL behave in Firebird to bear in mind is that the NUMERIC definition means exactly the precision requested (total number of digits), while DECIMAL mean at least the request precision (the digits to the right of the decimal symbol, however, are maintained exactly).
ve dialect 1 de bu alan tipi numeric gibi davranıyor. ;)
Kullanıcı avatarı
mrmarman
Üye
Mesajlar: 4741
Kayıt: 09 Ara 2003 08:13
Konum: İstanbul
İletişim:

Mesaj gönderen mrmarman »

Ek olarak tablosunda da ...
6.5 - numeric - NUMERIC - In MS SQL, decimal and numeric are synonims.


- Eş anlamlı deyip işin içinden çıkmış.. :lol: :lol: :lol:


// Edit // Farkında olmadan konuyu OffTopic'e sürüklüyordum... Herksten özür... :oops:
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 »

Yeni soru o zaman şu...(projemden bir inci 8) )
- Şu yapı sence geçerli mi ?

Kod: Tümünü seç

Function  TForm1.TipDetayi(Field_Type, Field_Sub_Type, Field_Length, Field_Precision, Field_Scale : Integer ) : String;
begin
  Result := '';
  Case Field_Type OF
    8 : // 'INTEGER';
        If IBDataBase1.SQLDialect = 3 then
        begin
          case Field_Sub_Type of
            0 : Result :=  'INTEGER';
            1 : Result :=  Format('NUMERIC (%d, %d)',[Field_Precision, Abs(Field_Scale)] );
            2 : Result :=  Format('DECIMAL (%d, %d)',[Field_Precision, Abs(Field_Scale)] );
          end; // Case
        end
        else // Dialect 3 değilse
        if Field_Scale <> 0 then
        begin
          If IBDataBase1.SQLDialect = 1
            then Result :=  Format('NUMERIC (%d, %d)',[9, Abs(Field_Scale)] ) // EMS, IBExpert, SQLHammer'den feyz alıyoruz Dial1 ise NUMERIC olsun
            else Result :=  Format('DECIMAL (%d, %d)',[9, Abs(Field_Scale)] );
        end
        else Result :=  'INTEGER';
    27: // 'DOUBLE';
        If Abs(Field_Scale) <> 0 then
        begin
          If IBDataBase1.SQLDialect = 1 // Yeni Dialect çıkarsa şimdiden uyumlu olduk :)))))
            then Result :=  Format('NUMERIC (%d, %d)',[15, Abs(Field_Scale)] )  // EMS, IBExpert, SQLHammer'den feyz alıyoruz Dial1 ise NUMERIC olsun
            else Result :=  Format('DECIMAL (%d, %d)',[15, Abs(Field_Scale)] );
        end
        else Result :=  'DOUBLE PRECISION';
  end; // Case
  Result := Format('%s /* (Tip:%d, SubType:%d) */',[Result, Field_Type, Field_Sub_Type] );
end;
Sonuç :
Resim
Resim
Resim ....Resim
fduman
Moderator
Mesajlar: 2749
Kayıt: 17 Ara 2004 12:02
Konum: Ankara

Mesaj gönderen fduman »

mrmcop yazdı:

Kod: Tümünü seç

Function  TForm1.TipDetayi(Field_Type, Field_Sub_Type, Field_Length, Field_Precision, Field_Scale : Integer ) : String;
begin
  Result := '';
  Case Field_Type OF
    8 : // 'INTEGER';
        If IBDataBase1.SQLDialect = 3 then
        begin
          case Field_Sub_Type of
            0 : Result :=  'INTEGER';
            1 : Result :=  Format('NUMERIC (%d, %d)',[Field_Precision, Abs(Field_Scale)] );
            2 : Result :=  Format('DECIMAL (%d, %d)',[Field_Precision, Abs(Field_Scale)] );
          end; // Case
        end
        else // Dialect 3 değilse
        if Field_Scale <> 0 then
        begin
          If IBDataBase1.SQLDialect = 1
            then Result :=  Format('NUMERIC (%d, %d)',[9, Abs(Field_Scale)] ) // EMS, IBExpert, SQLHammer'den feyz alıyoruz Dial1 ise NUMERIC olsun
            else Result :=  Format('DECIMAL (%d, %d)',[9, Abs(Field_Scale)] 
Kodun burasında bir hata var sanki. Gerçi çalıştırmadım gözümle trace ediyorum. :) Dialect 3 değilse aralığına girdiğinde bir de şöyle bir if statement var.

Kod: Tümünü seç

If IBDataBase1.SQLDialect = 1  .... else ....
burada zaten dialect 3 değilse'nin içinde olduğumuzdan hiçbirzaman else koşulu gerçekleşmeyecek ve

Kod: Tümünü seç

Result :=  Format('DECIMAL (%d, %d)',[9, Abs(Field_Scale)]
kodu çalıştırılmayacak.

İncelemeye devam ediyorum...
fduman
Moderator
Mesajlar: 2749
Kayıt: 17 Ara 2004 12:02
Konum: Ankara

Mesaj gönderen fduman »

mrmcop yazdı:

Kod: Tümünü seç

Function  TForm1.TipDetayi(Field_Type, Field_Sub_Type, Field_Length, Field_Precision, Field_Scale : Integer ) : String;
begin
  Result := '';
  Case Field_Type OF
    8 : // 'INTEGER';
        If IBDataBase1.SQLDialect = 3 then
        begin
          case Field_Sub_Type of
            0 : Result :=  'INTEGER';
            1 : Result :=  Format('NUMERIC (%d, %d)',[Field_Precision, Abs(Field_Scale)] );
            2 : Result :=  Format('DECIMAL (%d, %d)',[Field_Precision, Abs(Field_Scale)] );
          end; // Case
        end
        else // Dialect 3 değilse
Buradan sonraki bölüme gerek var mı? Dialect 1 de zaten NUMERIC alanlarda field type 8 değil 27 oluyor. Yani bir sonraki 27'li case ifadesinde bu iş halledilecek ve büyük ihtimalle buradaki kodun hiçbirzaman çalıştırılmayacak.

Buna göre düzenlersek:

Kod: Tümünü seç

Function  TForm1.TipDetayi(Field_Type, Field_Sub_Type, Field_Length, Field_Precision, Field_Scale : Integer ) : String;
begin
  Result := '';
  Case Field_Type OF
    8 : // 'INTEGER';
        If IBDataBase1.SQLDialect = 3 then
        begin
          case Field_Sub_Type of
            0 : Result :=  'INTEGER';
            1 : Result :=  Format('NUMERIC (%d, %d)',[Field_Precision, Abs(Field_Scale)] );
            2 : Result :=  Format('DECIMAL (%d, %d)',[Field_Precision, Abs(Field_Scale)] );
          end; // Case
        end;
    27: // 'DOUBLE';
        If Abs(Field_Scale) <> 0 then
        begin
          If IBDataBase1.SQLDialect = 1 // Yeni Dialect çıkarsa şimdiden uyumlu olduk :)))))
            then Result :=  Format('NUMERIC (%d, %d)',[15, Abs(Field_Scale)] )  // EMS, IBExpert, SQLHammer'den feyz alıyoruz Dial1 ise NUMERIC olsun
            else Result :=  Format('DECIMAL (%d, %d)',[15, Abs(Field_Scale)] );
        end
        else Result :=  'DOUBLE PRECISION';
  end; // Case
  Result := Format('%s /* (Tip:%d, SubType:%d) */',[Result, Field_Type, Field_Sub_Type] );
end;
Kod nihai olarak bu şekle dönüşüyor. Hatam varsa affola. Gözle debug bu kadar oluyor. :)
Kullanıcı avatarı
mrmarman
Üye
Mesajlar: 4741
Kayıt: 09 Ara 2003 08:13
Konum: İstanbul
İletişim:

Mesaj gönderen mrmarman »

SQLDialect 3 olmayan hepsi ELSE bloğu içinde..

Kod: Tümünü seç

else // Dialect 3 değilse 
        if Field_Scale <> 0 then 
        begin 
          If IBDataBase1.SQLDialect = 1 
            then Result :=  Format('NUMERIC (%d, %d)',[9, Abs(Field_Scale)] ) 
            else Result :=  Format('DECIMAL (%d, %d)',[9, Abs(Field_Scale)] ); 
        end 
        else Result :=  'INTEGER'; 


Orada da If ile Field_Scale <> 0 kontrolü var yani bir anlamda karşılığı şu...

Kod: Tümünü seç

        else // Dialect 3 değilse
        CASE Field_Scale OF
        0 : Result :=  'INTEGER'
        else
        begin
          If IBDataBase1.SQLDialect = 1
            then Result :=  Format('NUMERIC (%d, %d)',[9, Abs(Field_Scale)] ) // EMS, IBExpert, SQLHammer'den feyz alıyoruz Dial1 ise NUMERIC olsun
            else Result :=  Format('DECIMAL (%d, %d)',[9, Abs(Field_Scale)] );
        end; // Case
.. Yani Dialect 3 ve 1 değilse yine DECIMAL kalsın... Diğer bu iki dialect ile ilgili bir bilgi edinirsem edit etmesi kolay olsun istedim... Geleceğe yatırım yani :)


// EDIT //

- Haa anladım.. Zaten o ihtimalde 8 hiç olmayacak diyorsun mantıklı tabii ki....
Resim
Resim ....Resim
fduman
Moderator
Mesajlar: 2749
Kayıt: 17 Ara 2004 12:02
Konum: Ankara

Mesaj gönderen fduman »

@mrmcop anlatamadım. Seninkinden bir önceki mesaja bakarsan zaten o bölümü kaldırman gerekli. Çünkü işletilmeyecek.

Benim anlatmak istediğim şu.

Kod: Tümünü seç

else // Dialect 3 değilse 
{   // Biraz C syntax'ı kullanıyorum müsaadeyle böylesi daha okunaklı
  CASE Field_Scale OF
  {
      0 : Result :=  'INTEGER'
      else
        If IBDataBase1.SQLDialect = 1 then 
          Result :=  Format('NUMERIC (%d, %d)',[9, Abs(Field_Scale)] )                                            
        else 
           // *** !!!!! Bu bölüm hiçbirzaman çalıştırılmaz çünkü zaten Dialect 3
          // değilse!! bölümündesin, yani dialect burada her zaman 1 dir !!!! ***
           Result :=  Format('DECIMAL (%d, %d)',[9, Abs(Field_Scale)] );
      end; // Case 
} // // Dialect 3 değilse son.
Anlatmak istediğimi kodun içine yazdım. :)
Kullanıcı avatarı
mrmarman
Üye
Mesajlar: 4741
Kayıt: 09 Ara 2003 08:13
Konum: İstanbul
İletişim:

Mesaj gönderen mrmarman »

Haa bir soru ... Type 8 Dielct 1 olanlar ne olacak
Örnek
Table:SALES
Field:TOTAL_VALUE
Resim
Resim ....Resim
fduman
Moderator
Mesajlar: 2749
Kayıt: 17 Ara 2004 12:02
Konum: Ankara

Mesaj gönderen fduman »

Yok "8" olacak ancak sadece dialect 3 için olan bölümü:

Kod: Tümünü seç

// 'INTEGER';
        If IBDataBase1.SQLDialect = 3 then
        begin
          case Field_Sub_Type of
            0 : Result :=  'INTEGER';
            1 : Result :=  Format('NUMERIC (%d, %d)',[Field_Precision, Abs(Field_Scale)] );
            2 : Result :=  Format('DECIMAL (%d, %d)',[Field_Precision, Abs(Field_Scale)] );
          end; // Case
        end; 
Bu kısım yani. :)
fduman
Moderator
Mesajlar: 2749
Kayıt: 17 Ara 2004 12:02
Konum: Ankara

Mesaj gönderen fduman »

IB Expert'te senin alanın benzerini dialect 1 de NUMERIC (9,2) olarak tanımladığımda:

FIELD_TYPE = 8
SUB_TYPE = 1

olarak sorgu geri dönüyor.

Senin sonuçta aynı alan için sub type 0 görünüyor. Burada birşey var. Dialect 1 için demek 8 i de katacağız. Hatta şimdi denedim smallint type olan 7 nin de case içinde yer alması gerekli. Çünkü NUMERIC(1,1) in tipi 7 olarak dönüyor.
Cevapla