- Forumda buna ilişkin bir kaç soru mevcut ancak gösterdiğimiz metodik yol ile çözüm üretemeyenler için kod yardımı yapalım istedim.
- Aşağıdaki sistem kendimce geliştirdiğim otomatik alan ekleme / düzenleme sistemi. DivXTurk projem için geliştirdim ancak tüm projelerimde bunu kullanıyorum.
Özelliği : TEK NOKTADAN Tip tanımı yapmak ve herhangi bir tarihte tanımlardaki değişikliği kontrol ederek kendiliğinden tablo yapısının otomatik güncellenmesini sağlamak.
- ADO ile örnekledim. Ancak SQL universal bir kod çözümü olduğundan her türlü veritabanında uygulama özgürlüğünüz daima mevcut.
- İlk dikkat edilmesi gereken şey, Tip tanımlarının satır bazında standardını sağlamaktır. Aşağıda bir tablo tanım örneği veriyorum. Dikkat ederseniz ilk ve son satırı silersek geriye tipler ve uzunlukları kalıyor. Bu ilerde işimize yarayacak..
Kod: Tümünü seç
Procedure TipTanimlari_Tablo1( Liste:TStrings );
const
FieldTanimi = '%s %s(%d),';
FieldTanimiDate = '%s %s,';
begin
With Liste do begin
Clear;
Add('CREATE TABLE TabloNumara1 (');
Add(Format(FieldTanimiDate, ['KaySiraNo', 'AutoIncrement']));
Add(Format(FieldTanimi, ['T1_Adi', 'Text', 30]));
Add(Format(FieldTanimi, ['T1_Soyadi', 'Text', 30]));
Add(Format(FieldTanimi, ['T1_TCKimlik', 'Text', 11]));
Add(Format(FieldTanimi, ['T1_DogumYeri', 'Text', 35]));
Add(Format(FieldTanimiDate, ['T1_DogumTarihi','Date', 0]));
Add(Format(FieldTanimiDate, ['T1_Secili', 'Logical', 0]));
// Son virgülü silmek lazım,
Liste[Liste.Count - 1] := Copy(Liste[Liste.Count - 1], 1, Length(Liste[Liste.Count - 1]) - 1);
Add(')');
end;
end;
// Şimdi de işin asıl sırrına iniyoruz...
kurgulana müstakil bir procedure halinde olduğundan dilediğiniz yerden çağırırsınız.
Kod: Tümünü seç
Procedure TabloKontrol( AdoQuery1, AdoQuery2 : TAdoQuery );
// -----------------------------------------------------------------------------
// Tablo varsa eksik veya değişiklik varsa tamamla, yoksa yenisini oluştur...
// İki adet TAdoQuery (AdoQuery1 ve AdoQuery2) ihtiyaç duyulur...
// Birisi kontrol diğeri uygulama içindir...
// AdoQuery1 EXECSQL için kullanılacak
// AdoQuery2 sadece Tablo Alan listesini elde ederek kontrol için.
// -----------------------------------------------------------------------------
Const // komut seti için hazırladığım format tanımlarım
FieldSil = 'ALTER TABLE %s DROP %s';
FieldEkle = 'ALTER TABLE %s ADD %s %s(%d)';
FieldEkleDate = 'ALTER TABLE %s ADD %s %s';
FieldDegis = 'ALTER TABLE %s ALTER COLUMN %s %s(%d)';
FieldDegisDate = 'ALTER TABLE %s ALTER COLUMN %s %s';
Var
VeritabaniDosya : TFileName;
TabloListe,
Liste : TStringList;
TabloAdi : String;
Sayac : Integer;
Alan, Tip : String;
Uz : Integer;
Gecici : String;
begin
VeritabaniDosya := ExtractFilePath(Application.ExeName) + 'Veritabani.MDB';
If NOT AdoQuery1.Connection.Connected then begin
AdoQuery1.Connection.ConnectionString := 'Provider=Microsoft.Jet.OLEDB.4.0;Data Source='+VeritabaniDosya+';Persist Security Info=False';
AdoQuery1.Connection.LoginPrompt := False;
end;
Liste := TStringList.Create;
TabloListe := TStringList.Create;
// var olan Tablo listesini alıyoruz...
AdoQuery1.Connection.GetTableNames( TabloListe, False );
// TabloNumara01 tablosu için Create Table SQL text'ini Liste'ye alıyoruz.
TipTanimlari_Tablo1(Liste);
// Burada tablo adını değişkene atıyorum, siz bu isimleri döngü ile
// her tablo için yinelersiniz. Ben birisine örnek veriyorum.
TabloAdi := 'TabloNumara1';
// Tablo mevcut değilse tümüyle create ediyoruz.
If TabloListe.IndexOf( TabloAdi ) < 0 then begin
AdoQuery1.SQL.Text := Liste.Text;
AdoQuery1.ExecSQL;
end else begin
Liste.Delete(0); // ilk satırı sildik. Hani Create table olanı.
Liste.Delete(Liste.Count-1); // son satırı sildik. Hani parantez olanı.
Liste[Liste.Count-1] := Liste[Liste.Count-1] + ','; // son satıra virgül ekliyoruz.
// Bu eklenen virgül tüm satırlar tutarlı olsun diye. Çünkü parse edicez
// ederken de satır sonundaki virgülden kerteriz alıcaz...
// Artık elimizde alan isim ve tipleri var.
// Yapılacak işlem bu satırlar String Parse edilerek
// ------------------------
// 1. Eksik alan varsa eklenir.
// 2. Uzunluk değişikliği yapılmışsa güncellendir.
// 3. Tip değişikliği yapılmışsa ( Böyle bir durum henüz yok )
// Field Listesi için var olan Tablo boş olarak açılıyor...
// AlanListe stringlist'ine aktarılıyor...
AdoQuery2.SQL.Text := 'SELECT * FROM TabloNumara1 WHERE 1=0';
AdoQuery2.Active := True;
// Kontrol edilecek alanlar Liste stringlist'inden sırayla kontrol edilecek.
For Sayac := 0 to Liste.Count-1 do begin
Gecici := Trim( Liste[Sayac] );
// İlk boşluğa kadar olan kısım Alan Adı oluyor...
Alan := Copy(Gecici, 1, Pos(' ', Gecici)-1);
System.Delete( Gecici, 1, Length(Alan) );
Gecici := Trim(Gecici);
// Parantez varsa parantezin önündeki, yoksa son virgülün önündeki Tip oluyor....
Tip := Gecici;
If Copy( Tip, 1, Pos('(', Tip)-1 ) <> ''
then Tip := Copy( Tip, 1, Pos('(', Tip)-1 )
else Tip := Copy( Tip, 1, Pos(',', Tip)-1 );
System.Delete( Gecici, 1, Length(Tip) );
Gecici := Trim(Gecici);
// Parantez varsa parantez içeriği Uzunluk, yoksa uzunluk 0 oluyor....
If ( Gecici <> '' ) AND ( Gecici[1] = '(' )
then Uz := StrToInt(Copy(Gecici, 2, Pos(')', Gecici)-2))
else Uz := 0;
// Bulduğumuz alan adını Tablodan kontrol ediyoruz...
If AdoQuery2.FieldList.IndexOf(Alan) < 0 then begin
// Alan yok ekliyoruz...
If Uz = 0
then AdoQuery1.SQL.Text := Format(FieldEkleDate, [TabloAdi, Alan, Tip ])
else AdoQuery1.SQL.Text := Format(FieldEkle, [TabloAdi, Alan, Tip, Uz ]);
AdoQuery1.ExecSQL;
end else begin
// Alan var ancak Uzunluk aynı mı ? kontrol ediyoruz.
If AdoQuery2.FieldByName(Alan).Size <> Uz then begin
// Özel bir durum var. AUTOINC bir alan olacaksa o zaman eski alanı silip
// yeniden oluşturucaz yoksa sadece düzelticez..
If (UpperCase(Tip) = 'AUTOINCREMENT') then begin
// Alan düşürülür, AutoInc alan baştan eklenir...
// Alanı silme
AdoQuery1.SQL.Text := Format(FieldSil, [TabloAdi, Alan]);
AdoQuery1.ExecSQL;
// Yenisini ekleme..
If Uz = 0
then AdoQuery1.SQL.Text := Format(FieldEkleDate, [TabloAdi, Alan, Tip ])
else AdoQuery1.SQL.Text := Format(FieldEkle, [TabloAdi, Alan, Tip, Uz ]);
AdoQuery1.ExecSQL;
end else begin
// Sadece Düzeltme
If Uz = 0
then AdoQuery1.SQL.Text := Format(FieldDegisDate, [TabloAdi, Alan, Tip ])
else AdoQuery1.SQL.Text := Format(FieldDegis, [TabloAdi, Alan, Tip, Uz ]);
AdoQuery1.ExecSQL;
end;
end;
end;
end; // For döngüsü
end;
TabloListe.Free;
Liste.Free;
end;
Kod: Tümünü seç
procedure TForm1.Button1Click(Sender: TObject);
begin
TabloKontrol( AdoQuery1, AdoQuery2 )
end;
- Doğru çalışıp çalışmadığını test ederek yolladım bir sıkıntı olursa bildirin gözden kaçan bişey varsa düzelteyim. Çünkü bu kodları sıfırdan sizin için ürettik.
- Orjinal projelerimden biraz daha farklı oldu. kod satırları arasında gereken açıklamalar eklenmiştir.
- Umarım size bir faydamız dokunmuştur...
