İKİ XML KARŞILAŞTIRMA

MS SQL Server veritabanı ve SQL komutlarıyla ilgli sorularınızı sorabilirsiniz. Delphi tarafındaki sorularınızı lütfen Programlama forumunda sorunuz.
Cevapla
Kullanıcı avatarı
softdestek
Üye
Mesajlar: 155
Kayıt: 17 Eyl 2010 03:53

İKİ XML KARŞILAŞTIRMA

Mesaj gönderen softdestek »

MS SQL Table iki alanım var
1.field [OldContent] [xml] NULL,
2.field [NewContent] [xml] NULL,

şekliden tanımlı bu alanlar olan verileri karşılaştırıp farklı verileri bulup bunu 3.xml alanı olan
3.field [UpdatedContext] [xml] NULL içine yazmak istiyorum.

Bunu sql procedure yazım kuralları ile nasıl yapabiliriz.
örnek verirsem
[OldContent] [xml] NULL, içindeki veri
<row GUEST_ID="13" GUEST_NAME="VEDAT" GUEST_SURNAME="PALA" ADRESS="İZMİR" />

[NewContent] [xml] NULL, içindeki veri ise
<row GUEST_ID="13" GUEST_NAME="VEDAT" GUEST_SURNAME="PALA" ADRESS="İZMİR" CITY="DR" CITY_CODE="35" />
Bu iki veriyi karşılaştırıp
DEĞİŞEN VERİYİ
[UptatedContent] [xml] NULL, içine aşağıdaki kodu yazmam gerekiyor
<row CITY="DR" CITY_CODE="35" />

Teşekkür ederim.
Kısacası yapmak istediğim şey aşağıdaki resimdeki alanda değişen verileri göstermek
Resimhttp://i57.tinypic.com/2pqky80.jpg

Aşağıdaki resim tam istediğim şey
Resim
http://i60.tinypic.com/2cpc615.jpg
En son softdestek tarafından 11 Tem 2015 11:36 tarihinde düzenlendi, toplamda 1 kere düzenlendi.
Kullanıcı avatarı
mrmarman
Üye
Mesajlar: 4740
Kayıt: 09 Ara 2003 08:13
Konum: İstanbul
İletişim:

Re: İKİ XML KARŞILAŞTIRMA

Mesaj gönderen mrmarman »

Merhaba.

- Senin için PARSE fonksiyonunu yazdım, kolaylık sağlayayım istedim. Artık gerisini getirirsin. :)
- Parse işlemi yapıldıktan sonra karşılaştırıp yeni bir XML üretmek çocuk oyuncağı.
- Bu örnek ile veri alanlarının yerleri değişse dahi sonuç alabilirsin. Çünkü bileşenlerine alan isimleri bazında ayırıyoruz. Yoksa Önce soyad sonra ad olsaydı ve değerler aynı olsaydı dahi gösterdiğin örnek sayfada değişmiş gibi algılanırdı değil mi?! :idea:

- Aşağıdaki örnekte daha parse işemi sırasında dahi aynı veri alanlarının olup olmadığını araştırıp satırları direkt sildirerek filtre edebilir, finalde aListe içeriğini olduğu gibi değişiklikler listesi olarak kullanabilirsin.

- SQL'deki satırları alt alta <row \> <row \> şeklinde eklesen dahi bu parse fonksiyonu hepsini ID'lendirerek aListe içerisine alacağından sıknıtı yaşamazsın. Bir kere EOF döngüsü sonuna kadar bir STRINGLIST veya MEMO benzeri yerde biriktirdiğin XML Row'larını kümülatif olarak fonksiyona verebilir hepsinin bir batında çözümünü sağlayabilirsin.

Takip edeceğin iş akışını yazayım :
(1) a- DocID 1'e ait alanları sırasıyla almak.
. b- DocID 2'de aynı isimli alan var mı diye aramak.
. c- Varsa değerlerini karşılaştırmak
. d- Değerler farklı ise yeni değeri değişmiş olarak kodlamak.

(2) a- DocID 1'deki alan DocID 2'de yok ise NULL çekip değeri değişmiş deyip elinizdeki tek değeri yazmak

(3) bu işlemleri bir Doc1-> Doc2 yönünde yaptığınız gibi bir de tersini Doc-2'den Doc-1 yönünde yapmak. Çünkü görebildiğim üzere Doc-2'de olan Doc-1'de olmayan alanlar da olabiliyor ...

Kod: Tümünü seç

function ParseEt( strDoc1, strDoc2: String ): String;
Type
  pVeri = ^tveri;
  tVeri = Record
    DocId     : Word; // Doc1 mi Doc2 mi olduğu
    Satir,
    AlanIdx    : Integer;
    AlanAdi,
    AlanDeger  : String;
  end;

  Procedure ParseEdilsin( strDoc: String; DocID:Word; Liste:TStrings );
  Const
    strSatirBasi = '<ROW';
  Var
    Veri   : pVeri;
    iSat, Idx   : Integer;
  begin
    iSat := 0;
    while POS( strSatirBasi, UpperCase(strDoc) ) > 0 do // Tek satır da olsa birden fazla da olsa çalışır...
    begin // Satır Başı...
      System.Delete( strDoc, 1, POS( strSatirBasi, UpperCase(strDoc) ) + Length(strSatirBasi)-1 );
      inc(iSat);
      strDoc := Trim(strDoc);
      Idx := 0;
      while Pos('="', strDoc) > 0 do // Başlık ve Değer var...
      begin
        New(Veri);
        Inc(Idx);
        Veri.DocId     := DocID; // Doc-1 veya Doc-2 olduğunu ifade ediyoruz...
        Veri.Satir     := iSat;
        Veri.AlanIdx   := Idx;
        Veri.AlanAdi   := Trim( Copy(strDoc, 1, Pos('="', strDoc)-1 ) );
          System.Delete( strDoc, 1, Pos('="', strDoc) + 1 );
        Veri.AlanDeger := Trim( Copy(strDoc, 1, Pos('"', strDoc)-1 ) );
          System.Delete( strDoc, 1, Pos('"', strDoc) );
        Liste.AddObject( Veri.AlanAdi, TObject(Veri) );
      end;
    end;
  end;
Var
  aListe : TStringList;
  i      : Integer;
begin
  Result := '';
  aListe := TStringList.Create;
  // Aynı şeyi iki defa yazmayalım diye procedure yaptım...
    ParseEdilsin( strDoc1, 1, aListe );
    ParseEdilsin( strDoc2, 2, aListe );
  // Şimdi "aListe" içerisinde Başlık ve Değer içerikleri
  // tümüyle parse edilmiş şekilde var...
  // artık karşılaştırma yapabiliriz...
    for i := 0 to aListe.Count - 1 do
    begin
      Result := Result + Format('Doc:%.2d @ Id:%d - Idx:%.2d : %s = %s'#13, [
          pVeri( aListe.Objects[i] ).DocId
        , pVeri( aListe.Objects[i] ).Satir
        , pVeri( aListe.Objects[i] ).AlanIdx
        , pVeri( aListe.Objects[i] ).AlanAdi
        , pVeri( aListe.Objects[i] ).AlanDeger
      ]);
    end;
  // Sonunda hafızayı boşaltıp free edelim...
    for i := 0 to aListe.Count - 1
      do Dispose( pVeri(aListe.Objects[i]) );
    aListe.Clear;
    aListe.Free;
end;
Kullanımı :

Kod: Tümünü seç

procedure TForm1.BitBtn1Click(Sender: TObject);
begin
   Memo3.Lines.Text := ParseEt( Memo1.Lines.Text, Memo2.Lines.Text );
end;
Resim
Resim
Resim ....Resim
Kullanıcı avatarı
softdestek
Üye
Mesajlar: 155
Kayıt: 17 Eyl 2010 03:53

Re: İKİ XML KARŞILAŞTIRMA

Mesaj gönderen softdestek »

Çok teşekkür ederim...Bunu sql server içerisinde procedure ile yapabilsek süper olurdu ama sorun değil..Bunu delphide function olarak yazıp sql server dll fonksiyon olarak kullanmaya çalışayım..
Loggin olayı çok güzel oldu her tabloaya sadece bir triger ile kolaylıkla monte ediyorum.
Fakat sadece updatecontent de değişen alanları gösterme kaldı...Sqlde procedure yazmaya çalışıyordum bende...
Cevapla