Şimdi Ara

T-SQL Uzman Sorusu

Daha Fazla
Bu Konudaki Kullanıcılar: Daha Az
2 Misafir - 2 Masaüstü
5 sn
9
Cevap
0
Favori
1.885
Tıklama
Daha Fazla
İstatistik
  • Konu İstatistikleri Yükleniyor
0 oy
Öne Çıkar
Sayfa: 1
Giriş
Mesaj
  • Merhaba,

    İşin içinden bir türlü çıkamayınca size yazmak istedim. Sanırım istediğim şey SQL'de yok.

    Soru :

    HHH adında bir tablomun olduğunu ve içinde de OgrNo Adında Bir Field olduğunu düşenelim .Amacım Şöyle bir insert yapmaktır.

    Declare
    @OgrNo int
    ,@TabloAdi nvarchar(50)
    ,@Field nvarchar(50)


    Set @OgrNo = 6
    Set @TabloAdi = 'HHH'
    Set @Field = 'OgrNo'



    Insert Into @TabloAdi(
    @Field
    )
    Values(
    @OgrNo
    )


    Üst Taraftada yazdığım gibi TAblo Adını ve Fieldları da Declareden yani vb'den gelen parametrelerle yapmak istiyorum ama sql böyle birşeyi kabul etmiyor.Daha önceden böyle bir çalışma yapan oldu mu?



  • sen onu

    SELECT @komut = işte bilmem 'select from '+ @tabloadi +' falan fişman'

    diye yapamıyormusun? gelen değişkenlerle dinamik sql sorgusu oluştur onları da executesql diye bi komut vardı ona ver, tam hatırlamıyorum.

    ama burda senin yaptığın daha büyük bir hata var tablo adı değişken olmazki? çünkü aynı işi yapan birden fazla tablo olmaz bu bir, bütün tabloların içi farklıdır buda iki

    ya sen böyle 1a sınıfına bi tablo 2a sınıfına bi tablo 1c sınıfına bi tablo diyemi yapıyorsun? eğer öyleyse yannış
  • Şu şekilde yapabilirisin

    Declare
    @OgrNo varchar(5)
    ,@TabloAdi nvarchar(50)
    ,@Field nvarchar(50)
    ,@sorgu nvarchar(max)


    Set @OgrNo = '6'
    Set @TabloAdi = 'HHH'
    Set @Field = 'OgrNo'


    Set @sorgu = 'Insert Into ' + @TabloAdi + ' ('+@Field+') Values('+@OgrNo+')'
    exec sp_executesql @sorgu
  • Merhaba ,

    İstediğim Sorguyu aşağıdaki şekilde aldım . Fakat Benim Asıl amacım şimdi başladı .

    Declare
    @OgrNo nvarchar(50)
    ,@TabloAdi nvarchar(50)
    ,@Field nvarchar(50)
    ,@sql_str nvarchar(250)


    Set @OgrNo = '19'
    Set @TabloAdi = 'HHH'
    Set @Field = 'OgrNo'


    SET @sql_str = '
    Insert Into ' +@TabloAdi+'(
    '+@Field +'
    )
    Values(
    '+ @OgrNo + '
    ) '
    --select @sql_str
    EXEC(@sql_str)


    Benim Amacım vb.netten gelen parametreleri değişken hale getirmek . yani İnsert Update Delete için Ayrı ayrı spler yazmıyacağım .Sadece 1 tane sp ile bütün tablolar için insert yapabiliyor olacağım.

    Yani Exec denemesp @Birey_ID = 15 , @Ad = 'xxx' , @Okul = 'yyyy' , @Tablo = 'Kisi' şeklinde parametreler geldiğinde Kisi tablosuna gelen parametreyi kayıt edeceğim.
    Yine Aynı sp ile şöyle bir kayıt yapabileceğim
    Yani Exec denemesp @ID = 21 , @Unvan = 'ttt' , @Gorev = 'hhh' , @Tablo = 'Bilgi' . Dikkat edilmesi gereken ikisinde de aynı sp çalışıyor olması .

    Gelelim Benim yapamadığım Bölüme ;

    Amacım Gelen Parametreyi Hem Text olarak Hemde Value olarak kullanmak . yani vb.netten bana @Birey_ID = 15 şeklinde gelecek . Gelen Parametre Benim Field'ım oluyor.
    Insert Into fff (Birey_ID) values(@Birey_ID) şeklinde. Yani Gelen Parametrenin Text Bölümünü ( @(et) işareti hariç )Field Alanına , Value Değerini de Values Alanına yazdırmak istiyorum

    Aslında sorum basit ama yapılışı zor :) Gelen Parametreyi Text olarak alamıyorum.

    Umarım ne demek istediğimi anlatmışımdır.




  • Aşağıdaki split fonksiyonu kullanarak gelen degeri ayır.
    Daha sonra döngüye sok gerekli alanları al senin istegine göre belki 2 tane split fonkisyonu da kullanabilirsin. ben aşağıdakini '=' göre böldüm
    senin gelendegerle rin @Birey_ID = 15,@orgNo=21 şeklinde ise dışarıdan bir tane daha split fonksiyonu çağır döngü içerisinde. onu da ',' ile ayır
    Biraz ugraşırsan, önceki örneğin de baz alarak kolay bir şekilde yapabilirsin. Biraz ugraş yapamaz isen gene mesaj at tam kodu yazıp göndereyim :)
    Eger meslegin bu iş ise ugraşıp çözmeni öneririm. Elinde bütün veriler ve örnekler var sadece birleştirip uygulamaya koyacaksın.


    Declare cItems cursor for
    Select Items from [dbo].Split(@gelendeger,'=')
    Open cItems
    Fetch Next From cItems Into @Items
    While @@Fetch_Status=0
    Begin
    -- Burada sql sorgu stringini oluştur.
    Fetch Next From cItems Into @Items
    End

    CREATE FUNCTION [dbo].[Split](@STRING nvarchar(4000), @Delimiter char(1))
    RETURNS @Results TABLE (Items nvarchar(4000))
    AS
    BEGIN
    DECLARE @INDEX INT
    DECLARE @SLICE nvarchar(4000)
    SELECT @INDEX = 1
    IF @STRING IS NULL RETURN
    WHILE @INDEX !=0
    BEGIN
    SELECT @INDEX = CHARINDEX(@Delimiter,@STRING)
    IF @INDEX !=0
    SELECT @SLICE = RTRIM(LTRIM(LEFT(@STRING,@INDEX - 1)))
    ELSE
    SELECT @SLICE = RTRIM(LTRIM(@STRING))
    INSERT INTO @Results(Items) VALUES(@SLICE)
    SELECT @STRING = RIGHT(@STRING,LEN(@STRING) - @INDEX)
    IF LEN(@STRING) = 0 BREAK
    END
    RETURN
    END




  • Merhaba,

    Öncelikle uğraşıp cevap verdiğin için teşekkür Ederim . Ama sanırım tam anlatamadım derdimi.

    Sen split ile ayır demişsin. Ben o fonksiyonları daha önceden yazmıştım . Elimde 1'den 10'a kadar ayırıcı var.
    Yani
    Değer = '1,2,3,4,5,3,6,5,4,5,' olsun

    Ben onu 2'li olarak 1 2 , 3 4 ,5 3 , 6 5 , 4 5 olarak
    Ya da 5 li olsun 1 2 3 4 5 , 3 6 5 4 5 olarak ayırabilirim . Ama bana faydası ne orayı anlamadım :(


    Declare
    @BireY_ID int

    set @BireY_ID = 15

    select * from [dbo].[Split](@Birey_ID, '|')

    Sen burda sanırım şöyle anladın . @Birey_ID = Birey_ID | 15 ama bana gelen Parametre öyle olmayacak ki . Bana gelen @Birey_ID = 15 şeklinde olacak

    Sana başka bir örnek göndereceğim . Burda yapmak istediğim olayın Zemini Var . Tam karşılamıyor ama amaç bu .

    SP'ye gelen parametrelerle kayıt yapmak. Ben Otomasyon Programına destek veriyorum ve burda 1000'e yakın procedure var . Sadece bu basit kodla belki de %70'ini yok edebilirim . Diğer sp'ler joinli create templi sp'ler olacaktır. Ama Sadece 1 tane Insert Sp ile bütün tablolara kayıt işlemini yapabilmektir.

    Aşağıdaki sorguda bu olayı gerçekleştiriyorum . Ama burda alanların sabit.

    Set @Field = 'OgrNo , Ad , Soyad , Statu' Olarak bana gelmesini istemiyorum.

    İstediğim @OgrNo= 1 , @Ad = 'HFF' , @Soyad = 'ÇÇÇÇ' , @Statu = '15' şeklinde gelmesi ve bunları aşağıdaki gibi sorgulamak . (Yani Parametreler parça parça gelecek)

    Sanırım yazımı biraz karışık yazdım :)

    Declare
    @Field nvarchar(max)
    ,@TabloAdi nvarchar(250)
    ,@Values nvarchar(250)
    ,@SQL nvarchar(250)


    Set @Field = 'OgrNo , Ad , Soyad , Statu'
    Set @Values = '1 , ''FFF'' , ''ÇÇÇÇ'' , ''15'''
    set @TabloAdi = 'HHH'

    Set @SQL ='
    Insert Into '+ @TabloAdi +'(
    '+@Field+'
    )
    Values(
    '+@Values+'
    )'

    Select @SQL




  • Anladığım kadarı ile istediğin şey böle bir şey 1 saat kadar ugraşıp düzenledim :) senin dediğin gibi gelen Alanları degerler ile karşılaştırıp sorgu oluşturuyor. Procedure olarak kullanırsan daha hızlı olur table function yapma. Olmaz ise bilgi ver istediğin şekli bulalım. Yorum kısmını da açıp çalışması dizmesine bakabilirsin.

    Declare
    @Field nvarchar(max)
    ,@TabloAdi nvarchar(250)
    ,@Values nvarchar(250)
    ,@SQL nvarchar(max)


    Set @Field = 'OgrNo, Ad , Soyad , Statu'
    Set @Values = '1 ,''FFF'' , ''ÇÇÇÇ'' , ''15'''
    set @TabloAdi = 'HHH'


    --CREATE TABLE #test ([alanAd] varchar(2000),[alanDeger] varchar(2000))

    Declare @Delimiter char(1)
    Set @Delimiter=','

    DECLARE @INDEX INT
    DECLARE @INDEX1 INT
    SELECT @INDEX =1
    SELECT @INDEX1=1

    DECLARE @SLICE nvarchar(max)
    DECLARE @SLICE1 nvarchar(max)

    Declare @temp_Fields nvarchar(max)
    Declare @temp_Values nvarchar(max)
    Set @temp_Fields =''
    Set @temp_Values =''


    IF @Field IS NULL RETURN
    WHILE @INDEX1 !=0
    BEGIN
    SELECT @INDEX = CHARINDEX(@Delimiter,@Field)
    SELECT @INDEX1 = CHARINDEX(@Delimiter,@Values)
    IF (@INDEX !=0 and @INDEX1 !=0)
    Begin
    SELECT @SLICE = RTRIM(LTRIM(LEFT(@Field,@INDEX - 1)))
    SELECT @SLICE1 = RTRIM(LTRIM(LEFT(@Values,@INDEX1 - 1)))
    End
    Else
    Begin
    SELECT @SLICE = RTRIM(LTRIM(@Field))
    SELECT @SLICE1 = RTRIM(LTRIM(@Values))
    End

    Set @temp_Fields = @temp_Fields + @SLICE + ','
    Set @temp_Values = @temp_Values + @SLICE1 + ','

    ---INSERT INTO #test([alanAd],[alanDeger]) VALUES(@SLICE,@SLICE1)

    SELECT @Field = RIGHT(@Field,LEN(@Field) - @INDEX)
    SELECT @Values = RIGHT(@Values,LEN(@Values) - @INDEX1)
    IF LEN(@Field) = 0 BREAK
    END

    -- işte sana alanlar ve karşılığındaki degerler
    Set @temp_Fields = SUBSTRING(@temp_Fields,0,LEN(@temp_Fields))
    Set @temp_Values = SUBSTRING(@temp_Values,0,LEN(@temp_Values))

    --Select @temp_Fields,@temp_Values
    SET @SQL = 'Insert Into ' +@TabloAdi+'('+ @temp_Fields+') Values('+ @temp_Values + ')'
    Select @sql


    --Select * from #test
    --Drop table #test




  • Öncelikle teşekkür ederim . Zahmet edip uğraşmışsın . İstanbulda oturuyorsan sana yemek ısmarlayabilirim :) Uğraştırıyorum seni :) yazarken mahcup oluyorum artık :)

    Benim yazdığım ile senin yazdığın kod hemen hemen aynı . Senin yazdığın biraz daha geliştirilmişi.

    Galiba ben tam olarak ne istediğimi bilmediğim için sana da düzgün anlatamıyorum ::)

    ben sorgudan dönen değer olarak senin yaptığın sorguda Select @sql değerinin dönmesini istiyorum . (Insert Into HHH(@OgrNo,@Ad,@Soyad,@Statu) Values(1,FFF,ÇÇÇÇ,15))
    Yani sonucun tam istediğim gibi. Buraya kadar süpersin :) benim bir türlü başaramadığım ve anlatamadığım olay parametre alma olayı .

    Bizim ikimizin yaptığı sorguda da değerlerin bize şu şekilde gelmesi lazım
    Set @Field = 'OgrNo, Ad , Soyad , Statu'
    Set @Values = '1 ,''FFF'' , ''ÇÇÇÇ'' , ''15'''


    Ama ben değerlerin bu şekilde gelmesini istemiyorum . (Bu kısmı üstteki yazılarımda ben sana yanlış anlattım sanırım ya da anlatamadım )

    Benim otomasyon programımda kütüphanede dll dosyam var . onunda parametreye değer göndermesi şu şekilde oluyor.

    Bir forum alanı düşün . 3 tane text box var . Text_Box değerlerine şöyle id veriyorum . p_OgrNo , p_AdSoyad , p_Unvan
    dll kodum forumdaki bütün p_ ile başlayan değerleri value değeriyle beraber toplayıp sorguma (stored procedure) gönderiyor .
    Yani sorguma geliş şekli aynen böyle
    @OgrNo = 5 , @AdSoyad = 'fff' , @Unvan = 'Doktor'

    Bende bu parametleri procedure'dan alıyorum ve kayıt ediyorum. işte her procedure farklı parametreler geldiğinden hepsi için ayrı ayrı insert yazıyorum. Çünkü bu sorgu XXX tablosuna kayıt ederken başka bir forumda da p_adres , p_semt , p_il diye text boxlarım var .Bunu da adres tablosuna kayıt etmek için tekrar sorgu yazıyorum .
    çünkü bana bu sefer de @adres = 'aaaa' , @il = 'istanbul' , @ilce = 'ataşehir' şeklinde geliyor.

    İşte benim amacım bu procedure'ları birleştirmek . Sonuçta hepsi için Aynı ınsert yazıyorum.Tek farkı gelen parametreler ve kayıt ettiğim tablo adı .

    Gelelim benim anlatamadığım noktaya .

    Ben Bütün hepsi için geçerli olacak tek bir sp yazmak istiyorum .Yani öyle bir sp yazayım ki bana @ogrNo , @adsoyad , @unvan ve ilave olarak @tabloAdi değerleri gelsin bu sorgum gelen tablo adına gerekli parametreleri kayıt etsin

    Yine aynı sp'me @adres, @il , @ilce alanı da gelse bu sefer adres alanına kayıt etsin .

    İşte içinden çıkamadığım nokta ben naparım da sorguma gelen parametreleri de full değişken yapabilirim.

    Yani bana parametreler bu şekilde gelmeyecek
    Set @Field = 'OgrNo, Ad , Soyad , Statu'
    Set @Values = '1 ,''FFF'' , ''ÇÇÇÇ'' , ''15'''


    Bana parametreler aynen böle gelecek
    @OGrNo = 1 , @Ad = FFf , @Soyad = ÇÇÇ , @statu = 15,@tabloadi = 'xx'

    Ama başka bir forumda da aynen böle gelecek
    @adres = 'cc' , @il = 'ist' , @ilce = 'ataşehir' , @tabloadi = 'yy'


    Sonuç olarak hepsinde senin yazmış olduğun gibi değer dönecek .yani select @sql şeklinde

    Böyle birşey yapmak sql'de mümkün müdür ? Ben gelen parametreler her defasında değişebilen ve bunların hepsini karşılayan bi kod , bi sorgu bulamadım . 4 gündür arıyorum :) Uğraşıp zamanını harcadığın için tekrar teşekkür ederim . Yemek konusunda da ciddiyim :)

    Extra Kısa Acıklama :

    CREATE PROC kayitet
    @OGrNo nvarchar(50)
    ,@Adsoyad nvarchar(50)
    ,@Statu nvarchar(50)


    CREATE PROC kayitet
    @Adres nvarchar(50)
    ,@Il nvarchar(50)
    ,@Ilce nvarchar(50)

    Aynen bu şekilde aynı sp fakat farklı parametreleri alabileceğim bu durum yapabilir miyim ? . SQLden mailgönderme olayında dll çağırmıştım sql'den . İlla öyle bişey mi yapmam gerekiyor acaba . Ya da bunların hepsinin dışında şöyle birşey yapabilirsin diyebileceğin bir düşüncen var mı?




  • Senin anlattıklarından yola çıkarak şöle bir şey yaptım Umarım dogru anlamışımdır :) eger böyle de olmaz ise veya yanlış anlamışız ise Özel den bana bana telefon ve ya email adresini gönder.
    Proje de
    Split fonksiyonunu gene kullanacağız . Onu yukarıda vermiştim.

    Devamında da şöle bir şey yaptım

    -- Anladığım kadarı ile gelen parametrelerin böle bir şey

    Declare @gelenDegerler nvarchar(max)
    Set @gelenDegerler = '@OGrNo=1,@Ad=FFf,@Soyad=ÇÇÇ,@statu=15,@tabloadi = HHH'

    Declare @Field nvarchar(max)
    Declare @TabloAdi nvarchar(50)
    Declare @SQL nvarchar(max)
    Declare @INDEX INT
    Declare @INDEX1 INT
    Set @INDEX =1
    Set @INDEX1=1

    Declare @Delimiter char(1)
    Set @Delimiter=','

    Set @gelenDegerler = REPLACE(@gelenDegerler,'@','')

    Set @INDEX = CHARINDEX(@Delimiter,REVERSE(RTRIM(LTRIM(@gelenDegerler))))
    --Select RIGHT(@gelenDegerler,@INDEX-1)
    --Select LEN(RIGHT(@gelenDegerler,@INDEX-1))
    Set @Field = SUBSTRING(@gelenDegerler,0,LEN(@gelenDegerler)- LEN(RIGHT(@gelenDegerler,@INDEX-1)))
    Set @INDEX1 = CHARINDEX('=',REVERSE(RIGHT(@gelenDegerler,@INDEX-1)))
    --Select RTRIM(LTRIM(RIGHT(@gelenDegerler,@INDEX1-1)))
    Set @TabloAdi = RTRIM(LTRIM(RIGHT(@gelenDegerler,@INDEX1-1)))
    --Select @TabloAdi
    --Select @Field

    -- Tablo adları ile Fieldleri bir ayırdım Sonra da alaları ayarladım

    Declare @temp_Fields nvarchar(max)
    Declare @temp_Values nvarchar(max)
    Set @temp_Fields =''
    Set @temp_Values =''

    Declare @sayi int
    Set @sayi=0
    Declare @Items varchar(50),@Items1 varchar(50)
    Declare cItems cursor for
    Select Items from [dbo].Split(@Field,',')
    Open cItems
    Fetch Next From cItems Into @Items
    While @@Fetch_Status=0
    Begin
    --Set @SQL = @SQL + @Items
    -----------------------------------------------------------
    Declare c1 cursor for
    Select Items as Items1 from [dbo].Split(@Items,'=')
    Open c1
    Fetch Next From c1 Into @Items1
    While @@Fetch_Status=0
    Begin
    if((@sayi%2)=0)
    Set @temp_Fields = @temp_Fields + @Items1 + ','
    else
    Set @temp_Values = @temp_Values+ @Items1 + ','

    --Select @sayi
    Set @sayi = @sayi+1

    Fetch Next From c1 Into @Items1
    End
    Close c1
    Deallocate c1
    -----------------------------------------------------------
    Fetch Next From cItems Into @Items
    End
    Close cItems
    Deallocate cItems
    Set @temp_Fields = SUBSTRING(@temp_Fields,0,LEN(@temp_Fields))
    Set @temp_Values = SUBSTRING(@temp_Values,0,LEN(@temp_Values))
    --Select @temp_Fields
    --Select @temp_Values
    SET @SQL = 'Insert Into ' +@TabloAdi+' ('+ @temp_Fields+') Values('+ @temp_Values + ')'
    Select @SQL
    --exec sp_executesql @SQL




    CREATE FUNCTION [dbo].[Split](@STRING nvarchar(4000), @Delimiter char(1))
    RETURNS @Results TABLE (Items nvarchar(4000))
    AS
    BEGIN
    DECLARE @INDEX INT
    DECLARE @SLICE nvarchar(4000)
    SELECT @INDEX = 1
    IF @STRING IS NULL RETURN
    WHILE @INDEX !=0
    BEGIN
    SELECT @INDEX = CHARINDEX(@Delimiter,@STRING)
    IF @INDEX !=0
    SELECT @SLICE = RTRIM(LTRIM(LEFT(@STRING,@INDEX - 1)))
    ELSE
    SELECT @SLICE = RTRIM(LTRIM(@STRING))
    INSERT INTO @Results(Items) VALUES(@SLICE)
    SELECT @STRING = RIGHT(@STRING,LEN(@STRING) - @INDEX)
    IF LEN(@STRING) = 0 BREAK
    END
    RETURN
    END




  • 
Sayfa: 1
- x
Bildirim
mesajınız kopyalandı (ctrl+v) yapıştırmak istediğiniz yere yapıştırabilirsiniz.