Sql Server临时表消失

Sea*_*ive 7 c# sql-server

我正在创建一个临时表#ua_temp,它是常规表的子集.我没有收到错误,但是当我在第二步尝试从#ua_temp中选择时,却找不到它.如果删除#,则会创建名为ua_temp的表.

我使用了与其他地方的SELECT INTO一起创建表的完全相同的技术.它运行正常,所以我认为它与数据库设置无关.有谁能看到这个问题?

        // Create temporary table 
        q = new StringBuilder(200);
        q.Append("select policy_no, name, amt_due, due_date, hic, grp, eff_dt, lis_prem, lis_grp, lis_co_pay_lvl, ");
        q.Append("lep_prem, lapsed, dn_code, [filename], created_dt, created_by ");
        q.Append("into #ua_temp from elig_ua_response ");
        q.Append("where [filename] = @fn1 or [filename] = @fn2 ");
        sc = new SqlCommand(q.ToString(), db);
        sc.Parameters.Add(new SqlParameter("@fn1", sFn));
        sc.Parameters.Add(new SqlParameter("@fn2", sFn2));
        int r = sc.ExecuteNonQuery();
        MessageBox.Show(r.ToString() + " rows");

        // Rosters
        q = new StringBuilder(200);
        q.Append("select policy_no,name,amt_due,due_date,hic,grp,eff_dt,");
        q.Append("lis_prem,lis_grp,lis_co_pay_lvl,lep_prem,lapsed,dn_code,[filename] ");
        q.Append("from #ua_temp where (lis_prem > 0.00 or lep_prem > 0.00) ");
        q.Append("and [filename] = @fn order by name");
        sc.CommandText = q.ToString();
        sc.Parameters.Clear();
        sc.Parameters.Add(new SqlParameter("@fn", sFn));
        sda = new SqlDataAdapter(sc);
        sda.Fill(ds, "LIS LEP Roster");
Run Code Online (Sandbox Code Playgroud)

回答一些显而易见的问题:使用源表elig_ua_response,该程序运行正常.引入临时表的原因是我想删除此特定报告的一些行.我在测试时在列[filename]周围放置了括号,以确保它不是关键字问题.如果用#elig_ua_response替换#ua_temp,第二个SELECT工作正常.我为临时表尝试了不同的名字.显示行数的MessageBox仅用于调试目的; 它不会影响问题.

rsb*_*rro 7

我认为你的问题的解决方案是结合临时表的创建和从临时表中选择一个查询(参见下面的代码片段#3).如果您没有使用命令参数,则执行命令两次(就像您在问题中的代码中所做的那样)似乎工作正常,但如果引入它们则会失败.我测试了几种不同的方法,这就是我发现的.

1)工作正常:使用相同的命令对象,无命令参数,执行命令两次:

using (var conn = new SqlConnection("..."))
{
    conn.Open();
    using (var cmd = conn.CreateCommand())
    {
        const string query = @"
            CREATE TABLE #temp 
                ([ID] INT NOT NULL, [Name] VARCHAR(20) NOT NULL)
            INSERT INTO #temp VALUES(1, 'User 1')
            INSERT INTO #temp VALUES(2, 'User 2')";
        cmd.CommandType = CommandType.Text;
        cmd.CommandText = query;
        cmd.ExecuteNonQuery();

        cmd.CommandText = "SELECT * FROM #temp";
        using (var sda = new SqlDataAdapter(cmd))
        {
            var ds = new DataSet();
            sda.Fill(ds);
            foreach (DataRow row in ds.Tables[0].Rows)
                Console.WriteLine("{0} - {1}", row["ID"], row["Name"]);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

2)FAILS:使用相同的命令对象,命令参数,执行命令两次:

using (var conn = new SqlConnection("..."))
{
    conn.Open();
    using (var cmd = conn.CreateCommand())
    {
        const string query = @"
            CREATE TABLE #temp 
                ([ID] INT NOT NULL, [Name] VARCHAR(20) NOT NULL)
            INSERT INTO #temp VALUES(1, @username1)
            INSERT INTO #temp VALUES(2, @username2)
        ";
        cmd.CommandType = CommandType.Text;
        cmd.CommandText = query;
        cmd.Parameters.Add("@username1", SqlDbType.VarChar).Value ="First User";
        cmd.Parameters.Add("@username2", SqlDbType.VarChar).Value ="Second User";
        cmd.ExecuteNonQuery();

        cmd.Parameters.Clear();
        cmd.CommandText = "SELECT * FROM #temp";
        using(var sda = new SqlDataAdapter(cmd))
        {
            var ds = new DataSet();
            sda.Fill(ds);
            foreach(DataRow row in ds.Tables[0].Rows)
                Console.WriteLine("{0} - {1}", row["ID"], row["Name"]);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

3)工作正常:使用相同的命令对象,命令参数,仅执行一次命令:

using (var conn = new SqlConnection("..."))
{
    conn.Open();
    using (var cmd = conn.CreateCommand())
    {
        const string query = @"
            CREATE TABLE #temp 
                ([ID] INT NOT NULL, [Name] VARCHAR(20) NOT NULL)
            INSERT INTO #temp VALUES(1, @username1)
            INSERT INTO #temp VALUES(2, @username2)
            SELECT * FROM #temp
        ";
        cmd.CommandType = CommandType.Text;
        cmd.CommandText = query;
        cmd.Parameters.Add("@username1", SqlDbType.VarChar).Value ="First User";
        cmd.Parameters.Add("@username2", SqlDbType.VarChar).Value ="Second User";
        using (var sda = new SqlDataAdapter(cmd))
        {
            var ds = new DataSet();
            sda.Fill(ds);
            foreach (DataRow row in ds.Tables[0].Rows)
                Console.WriteLine("{0} - {1}", row["ID"], row["Name"]);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


Sea*_*ive 7

这有效.显然,如果SqlParameters位于创建表的步骤中,则表格不会留下以供下一步使用.创建表后,可以在INSERT的单独步骤中使用SqlParameters.

        // Create temporary file dropping members from termed groups.
        q = new StringBuilder(500);
        q.Append("create table #ua_param ");
        q.Append("([ID] int not null, fn varchar(50) not null) ");
        sc = new SqlCommand(q.ToString(), db);
        sc.ExecuteNonQuery();

        q = new StringBuilder(500);
        q.Append("insert into #ua_param values(1,@fn1) ");
        q.Append("insert into #ua_param values(2,@fn2) ");
        sc = new SqlCommand(q.ToString(), db);
        sc.Parameters.Add(new SqlParameter("@fn1", sFn));
        sc.Parameters.Add(new SqlParameter("@fn2", sFn2));
        sc.ExecuteNonQuery();

        q = new StringBuilder(500);
        q.Append("select policy_no, name, amt_due, due_date, hic, grp, eff_dt, lis_prem, lis_grp, lis_co_pay_lvl, ");
        q.Append("lep_prem, lapsed, dn_code, [filename], created_dt, created_by ");
        q.Append("into #ua_temp from elig_ua_response inner join #ua_param on [filename] = fn ");
        sc.Parameters.Clear();
        sc.CommandText = q.ToString();
        sc.CommandTimeout = 1800;
        sc.ExecuteNonQuery();
Run Code Online (Sandbox Code Playgroud)

  • 当存在参数时,SqlCommand通过sp_executesql调用带有参数的sql,这意味着你的临时表在内部创建(然后清理)存储过程,以便将来调用无法使用 - 即使它们共享相同的连接 (4认同)

Dav*_*lli 5

乔·扎克(Joe Zack)的评论是什么帮助我了解了这里发生的事情。一个非常清晰简洁的解释。这应该是一个答案,这样对于通过Google搜索到达此处的人们来说,它更容易被看到。

当有参数时,SqlCommand通过sp_executesql调用带有参数的sql,这意味着将在存储过程中创建(然后清理)临时表,因此以后的调用将无法使用它-即使它们共享相同的连接