17 Ağustos 2007

Tabloda Tekrar Eden Kayıtların Tekilleştirilmesi

Tablomuzda tekrar eden kayıtları tek bir sorguyla tekilleştirebiliriz.



delete [user]
where userid not in
(select max(userid) from [user]
group by username,usersurname)


Eğer userid alanımız kayıt bazında tekil değilse



Bu durumda testid isimli bir identity alan eklememiz gerekir.
Sorgu ise aşağıdaki şekilde değişir;
delete [user]
where testid not in
(select max(testid) from [user]
group by userid,username,usersurname)


16 Ağustos 2007

Where Kosulunu Devre Dışı Bırakmak

Blog yazılarımda karşılaşıp bulduğum bazı küçük çözümleri yazmaya çalışıyorum. Ne yazık ki klasik problemlerle ilgili bir çok sonuç bulabilirken çok özel durumlar için bilgi bulmak biraz zor oluyor.

Bir listeleme kontrolünüz olsun. (Treeview, Combo, Listbox ..).
Bu kontrolün elemanları bir sorguyla dolsun ve seçilen elemanın değerini başka bir listelemede kullanalım.

Örneğin ismin ilk harfine göre listeleme olsun ve hangi harf seçilirse diğer listede bu harfle ilgili bir içerik gelsin.

İlk listeyi aşağıdaki sorguyla dolduralım.

select 'A','A'
union select 'B','B'
union select 'C','C'

Diğer listelemede de

Select * from User where username like '@content%'

Buraya kadar herşey normal görünüyor. Fakat bir de bunların en üstünde 'Tüm Kullanıcılar' şeklinde bir durum istenirse nasıl olacak?

Burada sıkıntı olacak 2 durum sözkonusu. Birincisi bu seçeneğin en üstte çıkma gerekliliği, ikincisi ise diğer listeleme sorgusunu kullanarak where koşulunu es geçmek. Eğer like yerine = koşulu olsaydı klasik injection yöntemiyle 'aaa or 1=1' değeriyle çözüme ulaşabilirdik.

Bu durumu ise bir kaç deneme sonucu content değeri için '%' vererek çözebildim. Hem listede en üstte çıktı hemde where koşulunda sınırlama koymadı. Yani (where kolon like '%%') şeklinde where koşulunu işlem dışı yapabiliyoruz.

Belki bir yerlerde işinize yarayabilir.

15 Ağustos 2007

Yeni Nesil Google

Google'ın şaşılacak kadar kısa sürede sonuç getirmesinin verdiği hayranlığın artık aşıldığını düşünüyorum. Bir taraftan da kütüphanede bilgi aramak ile kıyaslandığındaki muhteşem hız yerini "acaba doğru mu?" kuşkularının artmasına bıraktı. Bir çok kişinin ortak sıkıntısı ise artık Google'da aradığını bulamamak. Veritabanı ve Pazarlama yazısında kısaca bahsettiğim şekliyle bilinçsiz veri toplama sonucunda artık bir çok kişinin elinde az kullanılmış veri çöplükleri var. Bir süre sonra acaba google da bir çöplük olacak mı? Aradığını bulamama problemi ile birlikte içeriğin bu hızla artmasıyla içerik kalitesinde de belli oranda düşüş yaşanacağı kesin.

Aradığını bulamamak problemi için en büyük neden olarak eşsesli kelimelerin kargaşasını örnek verebiliriz. Temel bir çözüm olarak kullancı deneyimlerini baz alarak yapılan indekslemeler bu problemi biraz azaltacaktır. Her aramada binlerce sonuç yerine bana özel sonuç kümesi gelmeli. Örneğin ben daha çok yazılımla alakalı kelimeler arıyorsam "structure" kelimesi yazdığımda muhtemelen inşaat görmek istemiyorumdur. Diğer taraftan bu özellik de benim gerçekten inşaatla alakalı bilgi aradığım durumlarda problem yaratacaktır.

Olaya farklı bir açıdan bakalım. Bir çok kişinin iş görüşmesi öncesi adayın ismini google da aradığını biliyoruz. Arayan kişinin aday hakkında çıkan sonuçları aslında kendi deneyimleri sonucu geleceği için o kişiye ne kadar yakın veya uzak olduğu hakkında da bir fikir verebilir. Aynı şekilde iki kişinin birbiriyle yakınlığı hakkında da bir fikir verebilir. Diğer taraftan çalışan da iş görüşmesi yapacağı genel müdürün ismini googleda aratıp, onun bir röportajını okuyup, bu bilgileri iş görüşmesinde kullansa sanırım doğru bir iş yapmış olur.

Daha da ileri gidersek medeni kanuna google aramalarında belli oranda uyumluluk şartı getirilebilir:) Birbirinizi çok seviyorsunuzdur ama aranızda ne yazık ki google vardır. Google hayatımıza daha fazla girmeye devam edecek mi acaba?

14 Ağustos 2007

Birleşmiş Milletler ve Sql Injection

Hackademix'te geçen habere göre Birleşmiş milletler sitesi SQL Injection yoluyla hacklenmiş. Yanlış hatırlamıyorsam 2003 yılında bir SQL Injection seminerinin akşamında ülkemizde 500 kadar site hacklenmişti. Uzun süredir gündemde ve de korunulması basit olmasına rağmen hala injection ihmali devam ediyor.
Note : This picture has been taken from http://www.bobnewell.net/ web site.

13 Ağustos 2007

Tablo ve Kolon Listesi

Çok tablolu sistemlerde tablo ve kolon adlarını hatırlamak çoğu zaman zor olmaktadır. Oracle ve SQL Server'da aşağıdaki sorgularla bu bilgilere ulaşabiliriz.

Oracle:

Tablo listesi
select * from tab
select * from tabs
Kolon listesi
select * from col
select * from cols

SQL Server

Tablo listesi
select * from sysobjects where xtype='U',
select * from INFORMATION_SCHEMA.TABLES
Kolon listesi
select * from syscolumns
select * from INFORMATION_SCHEMA.COLUMNS

31 Temmuz 2007

Union All Kayıt Setinden Gruplamak

Union All ile oluşan kayıt setini bir tablo olarak düşünüp bunun üzerinde gruplama işlemi yapabiliriz. Çeşitli zorunluluklardan veya kötü tasarımdan dolayı raporlama esnasında çeşitli yöntemler bulmak zorunda kalabiliriz.
Örneğin bir satış sitesi olsun ve aynı ürüne ait satış bilgileri farklı 3 tabloda tutulsun. Biz bu 3 tablodan ürün koduyla sorgulama yapıp toplamlarını çekelim. Son olarak da hepsinin toplamını almamız istensin.

select UrunKod,Sum(Fiyat) from
(
select UrunCode,Sum (UrunFiyat) as Fiyat
from table1
where UrunCode=x

union all
Select UrunCode,Sum(UrunFiyat) as Fiyat
From table2
Where UrunCode=x

union all
Select UrunCode,Sum(UrunFiyat) as Fiyat
From table3
Where UrunCode=x
)
group by UrunKod

Bu şekilde tek sorguyla istediğimiz sonucu elde edebiliriz. Hem kod içerisinde ekstra koda ihtiyacımız kalmaz hem de bir miktar performans sağlamış oluruz.

25 Temmuz 2007

Haftanın Gününü Veren Fonksiyon

Sql Server'da verilen tarihin haftanın hangi günü olduğunu döndüren kullanıcı tanımlı bir fonksiyon yazalım. DATEPART(weekday,date) şeklinde dönen değer haftanın gün sırasıdır. Fakat bu değer haftanın ilk günü olarak tanımlanan DATEFIRST server değişkenine göre değişmektedir. Bu yüzden fonksiyonda bu durum için bir önlem alacağız.
Amerikan ingilizcesi dil ayarlarında default değer 7 yani Pazar'dır.

SELECT @@DATEFIRST ile tanımlı değeri alabiliriz
SET DATEFIRST 1 (İlk günü Pazartesi olarak tanımlayabiliriz)

CREATE FUNCTION DayOfWeek(@date DATETIME)
RETURNS VARCHAR(9)
AS
BEGIN
DECLARE @defDayofWeek VARCHAR(10)
DECLARE @dofWeek int
SET @dofWeek= (@@DATEFIRST + DATEPART(weekday,@Date)-1)%7
SELECT @defDayofWeek=CASE @dofWeek
WHEN 0 THEN 'Pazar'
WHEN 1 THEN 'Pazartesi'
WHEN 2 THEN 'Salı'
WHEN 3 THEN 'Çarşamba'
WHEN 4 THEN 'Perşembe'
WHEN 5 THEN 'Cuma'
WHEN 6 THEN 'Cumartesi'
END
RETURN (@defDayofWeek)
END


SET @dofWeek= (@@DATEFIRST + DATEPART(weekday,@Date)-1)%7
ifadesinde ilk günün her zaman Pazartesi olmasını sağladık.

24 Temmuz 2007

Union All Kullanarak Toplu Insert

UNION komutu kullanarak aynı tipteki değerleri tek transactionda ekleyebiliriz. Örneğin bir kayıt formumuz olsun ve bu formda kişinin okuduğu gazeteleri checkbox tipinde bir kontrolle alalım. Normalizasyonu düşünerek bu değerleri farklı bir tabloda UserId ve GazeteId olarak tutalım. Standart yöntemle bir döngü içerisinde her seçili olan kayıt için bir insert komutu çalıştırılır. Fakat bu döngü içinde seçili olanları UNION ALL ile birleştirip tek sorguda kaydı yapabiliriz.

Sorgumuz aşağıdaki şekilde oluşur;



Kayıt sayısının çok fazla olduğu durumlarda işlem süresindeki kazancımız ciddi oranda artacaktır.

21 Temmuz 2007

Silverlight Flash'a Karşı

Oyun bağımlılığım hiç olmadı. En son ortaokul yıllarında tetris rüzgarından nasibimi almıştım. Silverlight örneklerine bakarken bu eski dost bir hayli hoş geldi bana.

Tetris örneğini oynamak için öncelikle Silverlight 1.1 Alpha eklentisini kurmanız gerekecektir.

Microsoft'un zengin interaktif uygulamalar için tarayıcı eklentisi olarak Adobe Flash'a alternatif olarak çıkardığı Silverlight üzerinde bir çok örnek uygulama yapılmaya başlandı. Şu an % 98 oranında yaygınlığa sahip flash a rakip olması ilk bakışta biraz zor görünüyor. Fakat Microsoft'un uyguladığı çapraz ürün bağımlılığı stratejisi onun en büyük avantajı. Örneğin bir .net uygulama geliştiricisi hakim olduğu platformda interaktif uygulama geliştirmeyi flash öğrenmeye/kullanmaya tercih edecektir.

Uygulamanın kaynak kodlarına buradan ulaşabilirsiniz

Bekleyelim ve görelim.

19 Temmuz 2007

Sql Server'dan Oracle'a Geçiş

Yazılım projelerinde veritabanı olarak Oracle ve Sql Server hatırı sayılır bir büyüklüğe sahiptir. Bu nedenle bir çoğumuz iki veritabanıyla da uğraşmak durumunda kalabiliriz. Sql Server'da iyi derecede olup Oracle'a geçişi kolaylaştırmak için başlangıç düzeyindeki farkları yazmanın faydalı olacağını düşündüm. Verdiğim tüm örneklerde Sql Server ifadelerini büyük harflerle Oracle ifadelerini küçük harflerle yazacağım.

Öncelikle çok kullanılan bir kaç fonksiyona bakalım;
GETDATE() - sysdate
ISNULL - nvl
CONVERT(VARCHAR,x) - to_char(x)
CONVERT(DATETIME,x) - to_date(x)
LEN - length
+ -

SELECT * INTO NEW_TABLE FROM TABLE şeklindeki SELECT INTO kalıbı yerine Oracle'da create table new_table as select * from table ifadesini kullanabiliriz.

İki tarih arasındaki fark için kullandığımız DATE_DIFF in direk karşılığı Oracle'da yok. date_diff_month(date1,date2) fonksiyonuyla ay farkını alabiliriz. Ayrıca date2-date1 ifadesi direk olarak gün cinsinden sonuç vereceği için gün farkı için bunu kullanabiliriz.

Değişken tanımlamada
DECLARE @a
INTEGER SET
@a=3
şeklindeki ifade Oracle'da
declare a number;begin a := 3;end;

Sql Server'da bir objeden bağımsız olarak SELECT 1 şeklinde bir sorgulama yapabiliriz. Oracle'da ise dummy table olarak adlandırılan DUAL tablosundan sorgulama yapmamız gerekecektir.
select 1 from dual