Arama butonu
Bu konudaki kullanıcılar: 1 misafir, 1 mobil kullanıcı
8
Cevap
2081
Tıklama
0
Öne Çıkarma
T-SQL Uzman Sorusu
M
15 yıl
Yüzbaşı
Konu Sahibi

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?

DH forumlarında vakit geçirmekten keyif alıyor gibisin ancak giriş yapmadığını görüyoruz.

Üye olduğunda özel mesaj gönderebilir, beğendiğin konuları favorilerine ekleyip takibe alabilir ve daha önce gezdiğin konulara hızlıca erişebilirsin.

Üye Ol Şimdi Değil



E
15 yıl
Çavuş

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ış


Bu mesaja 1 cevap geldi.
J
15 yıl
Yüzbaşı

Ş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


Bu mesaja 1 cevap geldi.
M
15 yıl
Yüzbaşı
Konu Sahibi

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.


Bu mesaja 1 cevap geldi.
J
15 yıl
Yüzbaşı

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


Bu mesaja 1 cevap geldi.
M
15 yıl
Yüzbaşı
Konu Sahibi

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


Bu mesaja 1 cevap geldi.
J
15 yıl
Yüzbaşı

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


Bu mesaja 1 cevap geldi.
M
15 yıl
Yüzbaşı
Konu Sahibi

Ö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ı?


Bu mesaja 1 cevap geldi.
J
15 yıl
Yüzbaşı

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



DH Mobil uygulaması ile devam edin. Mobil tarayıcınız ile mümkün olanların yanı sıra, birçok yeni ve faydalı özelliğe erişin. Gizle ve güncelleme çıkana kadar tekrar gösterme.