12 Aralık 2006

Tek Kolonda Tutulan Çoklu Değerler

Veritabanımızda bir verinin değeri birden fazla değerden oluşabiliyorsa (checkbox), bu durumda bu alanları saklamak için 2 yöntem kullanabiliriz. Birincisi bu değerleri bir key ilişkisiyle ayrı bir tabloda satırlar halinde tutmak, ikincisi ayırıcı bir karakter yardımıyla bu değerleri tek bir alanda tutmak. Birinci yöntemde raporlamada problem yaşanmaz, fakat ikinci yöntemde bu değerlerin gösterimi ve analizi biraz daha zor olacaktır.
Böyle bir durumla karşılaşırsak yazacağımız bir Split fonksiyonuyla işimizi kolaylaştırabiliriz.

Alan değerimizin izlenen TV kanalları olduğunu varsayalım. Değerleri de;

1: ATV
2: KANAL D
3: SHOW TV
4: NTV
5: CNN TURK


olsun. Ayırıcı işaret olarak ";" kullandığımızı varsayalım.

--Önce Split fonksiyonunu yazalım;

CREATE FUNCTION [dbo].[Split] (@Str NVARCHAR(500), @Delimiter CHAR(1))
RETURNS @Results TABLE (Rows nvarchar(4000))
AS
BEGIN
DECLARE @Indx INT
DECLARE @Prt NVARCHAR(4000)
SELECT @Indx = 1
IF @Str Is NULL RETURN
WHILE @Indx != 0
BEGIN
SELECT @Indx = CharIndex(@Delimiter, @Str)
IF @Indx != 0
SELECT @Prt = left(@Str, @Indx - 1)
ELSE
SELECT @Prt = @Str
IF (@Prt!='0' and @Prt!='') INSERT INTO @Results(Rows) VALUES (@Prt)
SELECT @Str = right(@Str, Len(@Str) - @Indx)
IF Len(@Str) = 0 BREAK
END
RETURN
END

Daha sonra test için bir kullanıcı tablosu yaratalım,
CREATE TABLE [dbo].[UserInfo](
[userid] [int] NOT NULL,
[Email] [varchar](100) COLLATE Turkish_CI_AS NOT NULL,
[channel] [varchar](100) COLLATE Turkish_CI_AS NOT NULL
)

Sonra bu tabloya test kayıtları ekleyelim

INSERT INTO [dbo].[UserInfo](userid,Email,Channel)
VALUES (887,'test1@test.com','1;0;0;4;5')
INSERT INTO [dbo].[UserInfo](userid,Email,Channel)
VALUES (965,'test2@test.com','1;0;3;0;0')

Daha sonra kanal seçim tablosunu oluşturalım
CREATE TABLE [dbo].[Channels](
[userid] [int] NOT NULL,
[Channel] [int] NOT NULL
)

Yazdığımız Split fonksiyonunu kullanarak kayıtları ekleyelim
DECLARE @channel varchar(200)
DECLARE @userid varchar(200)
DECLARE @cr_channel CURSOR
SET @cr_channel = CURSOR FOR
SELECT channel,userid FROM dbo.UserInfo
OPEN @cr_channel
FETCH NEXT FROM @cr_channel INTO @channel,@userid
WHILE ( @@FETCH_STATUS = 0)
BEGIN
INSERT INTO
Channels(userid, channel)
SELECT @userid, * From Split (@channel,';')
FETCH NEXT FROM @cr_channel INTO @channel,@userid
END

Channels tablosunda userid ve Channel olarak satır bazlı kayıtlarımız oluştu. Bu kayıtları artık çok rahat bir şekilde kullanabiliriz.

0 yorum: