ExecuteNonQuery无法创建临时表SQL Server

时间:2019-07-03 14:48:17

标签: c# sql-server ado.net

数据库中未创建临时表。我验证了凭据有权创建临时表。复制并粘贴SQL命令,它可以在SSMS中使用。

调试时不会抛出异常。在执行之前,cmd变量具有正确的连接和SQL文本。

我在应用程序的其他部分使用了相同的连接字符串来成功查询服务器,所以那里没有问题。

我的目标是创建一个临时表,然后通过SqlBulkCopy填充它,然后进行合并更新,然后删除该临时表。

编辑:我的错误是在DestinationTableName中引用了错误的表,但是我正在使用无法看到临时表的单独连接来检查SSMS中的进度。另外,finally语句是多余的。谢谢大家!

        string tmpTable = @"create table #TempTable 
                            (
                            [Column1] [varchar](50) NOT NULL,
                            [Column2] [varchar](50) NOT NULL,
                            [Column3] [varchar](50) NOT NULL
                            )";
        string connString = "Data Source=AzureDBServer;" + 
                                "Initial Catalog=Database;" + 
                                "User id=UserId;" + 
                                "Password=Password;";

        using (SqlConnection connection = new SqlConnection(connString))
        {
            connection.Open();
            SqlCommand cmd = new SqlCommand(tmpTable, connection);
            cmd.ExecuteNonQuery();

            try
            {
                using (SqlBulkCopy bulkCopy = new SqlBulkCopy(connection))
                {
                    bulkCopy.DestinationTableName = "#TempTable";
                    bulkCopy.WriteToServer(dataTable);

                    string mergeSql = "<Will eventually have merge statement here>";

                    cmd.CommandText = mergeSql;
                    int results = cmd.ExecuteNonQuery();

                    cmd.CommandText = "DROP TABLE #TempTable";
                    cmd.ExecuteNonQuery();
                }
            }
            catch (Exception)
            {
                throw;
            }

            finally
            {
                SqlCommand final = new SqlCommand("DROP TABLE #TempTable", connection);
                final.ExecuteNonQuery();

            }

        }

2 个答案:

答案 0 :(得分:3)

  

我正在使用相同的凭据签入SSMS,在代码完成后收到“无效的对象名称'#TempTable'”错误

那是因为SSMS使用的是不同的连接,而临时表(例如#Foo每个连接)。您无法从任何其他连接访问#Foo临时表。

听起来您想要一个全局临时表。就像将其命名为##Foo而不是#Foo一样简单。全局临时表在所有连接上共享。

答案 1 :(得分:0)

问题是@MarcGravell在评论中指出的简单错字。

bulkCopy.DestinationTableName = "TempTable";

应该是

bulkCopy.DestinationTableName = "#TempTable";

如果未在嵌套批处理或存储过程中创建,则临时表具有会话生存期。

此方法有效:

using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace sqlclienttest
{
    class Program
    {
        static void Main(string[] args)
        {
            string tmpTable = @"create table #TempTable 
                                (
                                [Column1] [varchar](50) NOT NULL,
                                [Column2] [varchar](50) NOT NULL,
                                [Column3] [varchar](50) NOT NULL
                                )";
            string connString = "Data Source=xxxx.database.windows.net;" +
                                    "Initial Catalog=Adventureworks;" +
                                    "User id=xxxxxx;" +
                                    "Password=xxxxxx;";

            var dataTable = new DataTable();
            dataTable.Columns.Add("Column1", typeof(string));
            dataTable.Columns.Add("Column2", typeof(string));
            dataTable.Columns.Add("Column3", typeof(string));

            dataTable.BeginLoadData();
            for (int i = 0; i < 10000; i++)
            {
                var r = dataTable.NewRow();
                r[0] = $"column1{i}";
                r[1] = $"column2{i}";
                r[2] = $"column3{i}";
                dataTable.Rows.Add(r);
            }
            dataTable.EndLoadData();

            using (SqlConnection connection = new SqlConnection(connString))
            {
                connection.Open();
                SqlCommand cmd = new SqlCommand(tmpTable, connection);
                cmd.ExecuteNonQuery();

                try
                {
                    using (SqlBulkCopy bulkCopy = new SqlBulkCopy(connection))
                    {
                        bulkCopy.NotifyAfter = 1000;
                        bulkCopy.SqlRowsCopied += (s, a) => Console.WriteLine($"{a.RowsCopied} rows");
                        bulkCopy.DestinationTableName = "#TempTable";
                        bulkCopy.WriteToServer(dataTable);

                        //string mergeSql = "<Will eventually have merge statement here>";

                        //cmd.CommandText = mergeSql;
                        //int results = cmd.ExecuteNonQuery();

                        cmd.CommandText = "DROP TABLE #TempTable";
                        cmd.ExecuteNonQuery();
                    }
                }
                catch (Exception)
                {
                    throw;
                }


            }
        }
    }
}

唯一的缺点是,如果客户端驱动程序决定将CREATE TABLE语句包装在sp_executesql中,则临时表将嵌套批处理生存期,而不是会话生存期。但是,除非您批量创建临时表的参数,否则System.Data.SqlClient不会执行此操作。

相关问题