将csv文件加载到SQL Server数据库会导致错误

时间:2017-05-30 19:35:40

标签: c# sql-server csv upload

我有这个代码试图将.csv文件加载到SQL Server数据库并动态创建表。我看到它说有一个语法错误和一个未闭合的引号,但我没有看到它。有什么想法吗?

class DTUpload
{
    public static void CSVUploadCode()
    {
        string datetime = DateTime.Now.ToString("yyyyMMddHHmmss");
        string LogFolder = @"C:\Log";

        try
        {
            // Declare Variables and provide values
            string SourceFolderPath = @"C:\Old\";
            string FileExtension = "*.csv";
            string FileDelimiter = ",";
            string ColumnsDataType = "NVARCHAR(max)";
            string SchemaName = "dbo";

            // Get files from folder
            string[] fileEntries = Directory.GetFiles(SourceFolderPath, "*" + FileExtension);

            foreach (string fileName in fileEntries)
            {
                // Create Connection to SQL Server in which you would like to create tables and load data
                SqlConnection SQLConnection = new SqlConnection();
                SQLConnection.ConnectionString = "Data Source = *******; Initial Catalog = *******; User id=*******;" + "Password=*********;";

                // Writing Data of File Into Table
                string TableName = "";
                int counter = 0;
                string line;
                string ColumnList = "";

                System.IO.StreamReader SourceFile = new System.IO.StreamReader(fileName);

                SQLConnection.Open();

                while ((line = SourceFile.ReadLine()) != null)
                {
                    if (counter == 0)
                    {
                        // Read the header and prepare create table statement
                        ColumnList = "[" + line.Replace(FileDelimiter, "],[") + "]";
                        TableName = (((fileName.Replace(SourceFolderPath, "")).Replace(FileExtension, "")).Replace("\\", ""));
                        string CreateTableStatement = "IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[" + SchemaName + "].";
                        CreateTableStatement += "[" + TableName + "]')";
                        CreateTableStatement += " AND type in (N'U'))DROP TABLE [" + SchemaName + "].";
                        CreateTableStatement += "[" + TableName + "]  Create Table " + SchemaName + ".[" + TableName + "]";
                        CreateTableStatement += "([" + line.Replace(FileDelimiter, "] " + ColumnsDataType + ",[") + "] " + ColumnsDataType + ")";
                        SqlCommand CreateTableCmd = new SqlCommand(CreateTableStatement, SQLConnection);
                        CreateTableCmd.ExecuteNonQuery();
                    }
                    else
                    {
                        // Prepare Insert Statement and execute to insert data
                        string query = "Insert into " + SchemaName + ".[" + TableName + "] (" + ColumnList + ") ";
                        query += "VALUES('" + line.Replace(FileDelimiter, "','") + "')";

                        SqlCommand SQLCmd = new SqlCommand(query, SQLConnection);
                        SQLCmd.ExecuteNonQuery();
                    }

                    counter++;
                }

                SourceFile.Close();
                SQLConnection.Close();
            }
        }
        catch (Exception exception)
        {
            // Create Log File for Errors
            using (StreamWriter sw = File.CreateText(LogFolder
               + "\\" + "ErrorLog_" + datetime + ".log"))
            {
              sw.WriteLine(exception.ToString());
            }
        }
    }
}

这是我收到的错误消息:

  

System.Data.SqlClient.SqlException(0x80131904):'年度'附近的语法不正确。

     

字符串后的未闭合引号'] NVARCHAR(max))'。

     

at System.Data.SqlClient.SqlConnection.OnError(SqlException exception,Boolean breakConnection,Action`1 wrapCloseInAction)

     

at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception,Boolean breakConnection,Action`1 wrapCloseInAction)

     

at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj,Boolean callerHasConnectionLock,Boolean asyncClose)

     

at System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior,SqlCommand cmdHandler,SqlDataReader dataStream,BulkCopySimpleResultSet bulkCopyHandler,TdsParserStateObject stateObj,Boolean& dataReady)

     

at System.Data.SqlClient.SqlCommand.RunExecuteNonQueryTds(String methodName,Boolean async,Int32 timeout,Boolean asyncWrite)

     

at System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(TaskCompletionSource`1 completion,String methodName,Boolean sendToPipe,Int32 timeout,Boolean asyncWrite)

     

在System.Data.SqlClient.SqlCommand.ExecuteNonQuery()

     

在C:\ ParseColumnCount \ DTUpload.cs中的ParseColumnCount.DTUpload.C​​SVUploadCode():第66行

     

ClientConnectionId:********************
  错误号码:102,状态:1,等级:15

     

路由前的ClientConnectionId:**************
  路由目的地:*****************

进行了建议的更改,现在正在进行

  

System.Data.SqlClient.SqlException(0x80131904):' U'附近的语法不正确。

     

字符串后的未闭合引号')DROP TABLE [dbo]。   [Compensation.csv]创建表dbo。[Compensation.csv]([" Associate   ID"] NVARCHAR(最大),["职位ID"] NVARCHAR(最大),["家庭部门   代码[就业资料]"] NVARCHAR(最高),["年薪"]   NVARCHAR(最大),["常规工资额"] NVARCHAR(最大),["标准   小时"] NVARCHAR(最大),["薪酬等级代码"] NVARCHAR(最高),["支付   频率"] NVARCHAR(最大),["赔偿更改原因代码"]   NVARCHAR(最大),["薪酬变更原因说明"]   NVARCHAR(MAX))'

1 个答案:

答案 0 :(得分:2)

看看这段代码:

query += "VALUES('" + line.Replace(FileDelimiter, "','") + "')";

想象一下line的不同值。

如果它包含类似

的内容
John Smith,Dick Brain,Harry Chest

那你就没事了。

但如果它包含

John Smith,Dick Brain,Harry O'Brian

看到问题?在这种情况下,query将填充

VALUES('John Smith,Dick brain,Harry O'Brian')

就SQL而言,报价以Harry O结束,因为O后跟单引号。当它在Brian之后遇到报价时,它会找到一个没有收盘价的开盘报价,因此就是错误。

您需要清除单引号的输入并转义它们。在SQL Server中,您将replacing them with double single quotes转义它们,如下所示:

line = line.Replace("'","''");
query += "VALUES('" + line.Replace(FileDelimiter, "','") + "')";

然后query将获得

VALUES('John Smith,Dick brain,Harry O''Brian')

这是有效的SQL。

另一个(更好)选项是使用存储过程插入值,并将字符串绑定到参数,而不是动态构造SQL语句。如果你这样做,你将不必逃避任何事情。