none
C# İLE SQL TEMP TABLE RRS feed

  • Soru

  • Merhaba aşağıda belirttiğim kodlarla kendi sunucumda temp table oluşturmak istiyorum ve list içerisindeki verileri aktarmak istiyorum ama kodlar hata vermemesine rağmen temp table oluşmuyor bi türlü yardımlarınız için teşekkür ederim

    List<string> No= new List<string>();
    List<string> Bolge= new List<string>();
                            while (dr.Read())
                            {
                                string Kayit;
                                Kayit= dr["Sıra"].ToString();
                                {
                                    No.Add(Kayit);
                                }
                                string Bolgeler;
                                Bolgeler= dr["Blg"].ToString();
                                {
                                    Bolge.Add(Bolgeler);
                                }
                            }
                            string query = string.Empty;

                            using (SqlConnection connection = new SqlConnection(Sunucu Baglanti))
                            {
                                connection.Open();

                                SqlTransaction transaction = connection.BeginTransaction();
                                using (SqlCommand command = new SqlCommand(query, connection))
                                {
                                    command.Transaction = transaction;
                                    command.CommandTimeout = 0;
                                    command.CommandText = "CREATE TABLE #Deneme ( Kayit INT )";
                                    command.ExecuteNonQuery();

                                    No.ForEach(x =>
                                    {

                                        command.CommandText = string.Format("INSERT INTO #Deneme(Kayit ) VALUES ({0})", x);
                                        command.ExecuteNonQuery();

                                    });
                                }
                            }

    24 Ağustos 2016 Çarşamba 07:19

Yanıtlar

  • Bu sekilde yarattigin bir temp tablo lokal bir temp tablodur ve zaten soylendigi gibi onu yaratan connection acik oldugu surece yasar. Eger connection kapansa da, o database'e baska baglantilar oldugu surece yasamasini ve diger baglantilardan da gorulmesini istiyorsan, global temp table kullanman gerekir (#Deneme yerine ##Deneme).

    Temp tablo olayini bir kenara birakirsak, kodun calismasina calisir da ne amaci var? Neden temp table? Neden transaction (cok sayida insert icin performans sorunu nedeniyle sanirim)? Neden tek tek insert? Neden int alana string insert?

    Amacini bilmeden ##Deneme gibi bir global tablo ile (gormek icin Database'e baska baglantinin olmasi lazim, baglanti kalmazsa o da gider) - (Not: Bunu yapmanin N tane yolu var, bu ornek yollardan sadece birisi):

    void Main()
    {
    	List<int> No = Enumerable.Range(1, 10000).Select(e => e).ToList();
    	var insertEdilecekNolar = string.Join(",", No);
    	
    	string query = @"declare @values varchar(max);
    	SET @values = ',' + @Parameter + ',';
    
    -- Her neden temp table gerekiyorsa
    create table ##Deneme (Kayit int);
    
    WITH cteTally AS
    (
    	SELECT TOP(LEN(@values))
            ROW_NUMBER() OVER(ORDER BY t1.Object_ID) AS N
            FROM Master.sys.All_Columns t1
            CROSS JOIN Master.sys.All_Columns t2
    )
    insert into ##Deneme (Kayit)
    SELECT cast(SUBSTRING(@values, N + 1, CHARINDEX(',', @values, N + 1) - N - 1)  as int)
        FROM cteTally
            WHERE N < LEN(@values) AND SUBSTRING(@values, N, 1) = ',';";
    		
    	using (SqlConnection connection = new SqlConnection(@"server=.\SQLExpress2012;Database=test;Trusted_Connection=yes"))
    	{
    		var cmd = new SqlCommand(query,connection);
    		cmd.Parameters.AddWithValue("@Parameter", insertEdilecekNolar);
    		connection.Open();
    		cmd.ExecuteNonQuery();
    		connection.Close();
    	}
    }
    
    Keske temp tablo ile ugrasmak yerine, asil yapmaya calistigin seyi soyleseydin.

    24 Ağustos 2016 Çarşamba 10:43
    Yanıtlayıcı
  • O zaman yukaridaki isini gorur ama bunun icin temp tabloya ihtiyac yok, table variable kullanabilirsin, ya da baglanan kisinin her iki sunucuya da erisme hakki var ise dogrudan diger sunucudan ID'leri alip bakabilirsin.

    Eger gondermen gereken ID sayisi cok fazla ise (yukaridaki 10000 id ile benim makinede 0.14 sn) o zaman bunu bir CLR function yapmanda fayda var. Dogrudan "12, 324,4332, ..." gibi gonderdigin bir listeden sana 12, 324, 4332 ... gibi int degerlerin oldugu bir tablo donduren function. Yukaridakini de aslinda procedure yaparsan islerin cok kolaylasir (ben procedure olarak kullaniyorum, aslinda CLR function da yaptim o cok daha hizli ve cok fazla sayida ID'yi gonderebiliyorum) - Kod SQLServercentral'da Jeff Moden'in bir kodundan uyarlamadir:

    CREATE FUNCTION [dbo].[iSplitter] (@Parameter VARCHAR(MAX))
    RETURNS @splitResult TABLE (number INT, [value] INT)
    AS
    BEGIN
    SET @Parameter = ','+@Parameter +',';
    
    WITH cteTally AS
    	(
    		SELECT TOP (LEN(@Parameter))
    			ROW_NUMBER() OVER (ORDER BY t1.Object_ID) AS N
    			FROM Master.sys.All_Columns t1
    			CROSS JOIN Master.sys.All_Columns t2
    	)
    INSERT @splitResult
    	SELECT ROW_NUMBER() OVER (ORDER BY N) AS Number,
    	SUBSTRING(@Parameter,N+1,CHARINDEX(',',@Parameter,N+1)-N-1) AS [Value]
    	FROM cteTally
    		WHERE N < LEN(@Parameter) AND SUBSTRING(@Parameter,N,1) = ','
    RETURN
    END

    Bu procedure varken SQL server'a soyle bir komut gonderebilirsin:

    Select * from tabloAdi t
    inner join iSplitter(@idList) s on t.ID = s.Value;
    @idList parametresi olarak, "23, 43, 43455, ..." gibi bir ID listesi kullanabilirsin.

    24 Ağustos 2016 Çarşamba 10:59
    Yanıtlayıcı

Tüm Yanıtlar

  • Yardımcı olabilecek var mı acaba..Teşekkürler

    24 Ağustos 2016 Çarşamba 08:13
  • Deleted
    24 Ağustos 2016 Çarşamba 08:21
  • Cevabınız için teşekkür ederim open ve close kısmı dediğiniz gibi yerleştirilmiş durumda breakpoint koyup çalıştırdığımda tablo oluşturulduğunda sunucuya bakıyorum select yapmıyorum tablo oluşturulmamış olarak gözükmekte :S anlamadım gitti bende
    24 Ağustos 2016 Çarşamba 08:43
  • Deleted
    24 Ağustos 2016 Çarşamba 08:57
  • Deleted
    24 Ağustos 2016 Çarşamba 09:01
  • Temp tabloyu neden açıp bakmak istiyorsun ki? Bence normal bir tablo yap bak bakalım kodun çalışıyormu eğer tamamsa ve temp table ile bu işi çözeceksen o zaman kodu temp tabloya göre uyarla. Production yaptığın db de test için değişiklik istemiyor olabilirsin ancak bunu local de test etmen mantıklı olacaktır.

    Fullstack Developer

    24 Ağustos 2016 Çarşamba 09:04
  • Şöyle birşey denedim bu yazdığınıza ilgili kodların altına sunucuyu.close yapmadan önce,  bu dediğinize göre temp oluşturup iki tablo arasında sorgu sonucunu gridde göstermesi gerek fakat sorguyu çalıştırdığım zaman #Deneme Tablosunun oluşturulmadığı şeklinde hata veriyor. İlginiz için teşekkürler.

    Konuyla alakalı sizde farklı şekilde bir kodlama varsa örnek olarak verebilirseniz sevinirim. Kolay gelsin

     command.CommandText = string.Format("Select * From Kisiler K WITH (NOLOCK) INNER JOIN #Deneme Temp ON A.KisiNo= Temp.No");
                                    using (SqlDataReader reader = command.ExecuteReader (CommandBehavior.Default))
                                    {
                                        while (reader.Read())
                                        {
                                            gridControl1.DataSource = reader;
                                        }
                                     }

    24 Ağustos 2016 Çarşamba 09:10
  • Transaction açıyorsun ama commit etmiyorsun...

    transaction .Commit()  eklemen lazım sonuna bir yere

    24 Ağustos 2016 Çarşamba 09:57
  • kodlama olarak göstere bilme şansınız varmı acaba, normalde alt kısımda  bu şekilde ekli,

    Tam bi örnek göndere bilecek varmı acaba çözmedim bu şekilde :S

     command.ExecuteNonQuery();

     transaction.Commit();

    24 Ağustos 2016 Çarşamba 10:06
  • Bu sekilde yarattigin bir temp tablo lokal bir temp tablodur ve zaten soylendigi gibi onu yaratan connection acik oldugu surece yasar. Eger connection kapansa da, o database'e baska baglantilar oldugu surece yasamasini ve diger baglantilardan da gorulmesini istiyorsan, global temp table kullanman gerekir (#Deneme yerine ##Deneme).

    Temp tablo olayini bir kenara birakirsak, kodun calismasina calisir da ne amaci var? Neden temp table? Neden transaction (cok sayida insert icin performans sorunu nedeniyle sanirim)? Neden tek tek insert? Neden int alana string insert?

    Amacini bilmeden ##Deneme gibi bir global tablo ile (gormek icin Database'e baska baglantinin olmasi lazim, baglanti kalmazsa o da gider) - (Not: Bunu yapmanin N tane yolu var, bu ornek yollardan sadece birisi):

    void Main()
    {
    	List<int> No = Enumerable.Range(1, 10000).Select(e => e).ToList();
    	var insertEdilecekNolar = string.Join(",", No);
    	
    	string query = @"declare @values varchar(max);
    	SET @values = ',' + @Parameter + ',';
    
    -- Her neden temp table gerekiyorsa
    create table ##Deneme (Kayit int);
    
    WITH cteTally AS
    (
    	SELECT TOP(LEN(@values))
            ROW_NUMBER() OVER(ORDER BY t1.Object_ID) AS N
            FROM Master.sys.All_Columns t1
            CROSS JOIN Master.sys.All_Columns t2
    )
    insert into ##Deneme (Kayit)
    SELECT cast(SUBSTRING(@values, N + 1, CHARINDEX(',', @values, N + 1) - N - 1)  as int)
        FROM cteTally
            WHERE N < LEN(@values) AND SUBSTRING(@values, N, 1) = ',';";
    		
    	using (SqlConnection connection = new SqlConnection(@"server=.\SQLExpress2012;Database=test;Trusted_Connection=yes"))
    	{
    		var cmd = new SqlCommand(query,connection);
    		cmd.Parameters.AddWithValue("@Parameter", insertEdilecekNolar);
    		connection.Open();
    		cmd.ExecuteNonQuery();
    		connection.Close();
    	}
    }
    
    Keske temp tablo ile ugrasmak yerine, asil yapmaya calistigin seyi soyleseydin.

    24 Ağustos 2016 Çarşamba 10:43
    Yanıtlayıcı
  • Cevabınız için teşekkür ederim. yapma sebebim ayrı ayrı sunuculardan verileri birbirleriyle bağlantılı olarak çekmek istyorum. A sunucusundaki ID lerle B sunucusunda bulunan tablomdaki ID leri eşleştirmek istiyorum bende bunu A sunucusundaki ID leri liste döktüm ve bu listteki verileri B sunucusuna temp table olarak atıp ınner join ile eşleştirerek ekrana getirmek için düşündüm. Teşekkür ederim.
    24 Ağustos 2016 Çarşamba 10:46
  • Cevabınız için teşekkür ederim. yapma sebebim ayrı ayrı sunuculardan verileri birbirleriyle bağlantılı olarak çekmek istyorum. A sunucusundaki ID lerle B sunucusunda bulunan tablomdaki ID leri eşleştirmek istiyorum bende bunu A sunucusundaki ID leri liste döktüm ve bu listteki verileri B sunucusuna temp table olarak atıp ınner join ile eşleştirerek ekrana getirmek için düşündüm. Teşekkür ederim.
    MSSQL kullanıyorsan ki öyle duruyor. Linked Server olarak ilişkilendir bu sunucuları SQL tarafında hallet.
    24 Ağustos 2016 Çarşamba 10:52
  • O zaman yukaridaki isini gorur ama bunun icin temp tabloya ihtiyac yok, table variable kullanabilirsin, ya da baglanan kisinin her iki sunucuya da erisme hakki var ise dogrudan diger sunucudan ID'leri alip bakabilirsin.

    Eger gondermen gereken ID sayisi cok fazla ise (yukaridaki 10000 id ile benim makinede 0.14 sn) o zaman bunu bir CLR function yapmanda fayda var. Dogrudan "12, 324,4332, ..." gibi gonderdigin bir listeden sana 12, 324, 4332 ... gibi int degerlerin oldugu bir tablo donduren function. Yukaridakini de aslinda procedure yaparsan islerin cok kolaylasir (ben procedure olarak kullaniyorum, aslinda CLR function da yaptim o cok daha hizli ve cok fazla sayida ID'yi gonderebiliyorum) - Kod SQLServercentral'da Jeff Moden'in bir kodundan uyarlamadir:

    CREATE FUNCTION [dbo].[iSplitter] (@Parameter VARCHAR(MAX))
    RETURNS @splitResult TABLE (number INT, [value] INT)
    AS
    BEGIN
    SET @Parameter = ','+@Parameter +',';
    
    WITH cteTally AS
    	(
    		SELECT TOP (LEN(@Parameter))
    			ROW_NUMBER() OVER (ORDER BY t1.Object_ID) AS N
    			FROM Master.sys.All_Columns t1
    			CROSS JOIN Master.sys.All_Columns t2
    	)
    INSERT @splitResult
    	SELECT ROW_NUMBER() OVER (ORDER BY N) AS Number,
    	SUBSTRING(@Parameter,N+1,CHARINDEX(',',@Parameter,N+1)-N-1) AS [Value]
    	FROM cteTally
    		WHERE N < LEN(@Parameter) AND SUBSTRING(@Parameter,N,1) = ','
    RETURN
    END

    Bu procedure varken SQL server'a soyle bir komut gonderebilirsin:

    Select * from tabloAdi t
    inner join iSplitter(@idList) s on t.ID = s.Value;
    @idList parametresi olarak, "23, 43, 43455, ..." gibi bir ID listesi kullanabilirsin.

    24 Ağustos 2016 Çarşamba 10:59
    Yanıtlayıcı