无法使用C#将数据导入SQL Server数据库

时间:2019-01-05 11:08:34

标签: c# sql-server

我已经从SQL Server Express中导出了数据,并尝试将其导入到另一个数据库中。

我想将其用作“修复表”,在该表中我将添加更多包含数据的表,但总是出现错误,我不明白为什么。

错误是

  

消息-System.Data.SqlClient.SqlException(0x80131904):字符串'ΧΥΜΟΙΑΧΛΑΔΙΩΝΤΗΣΠΟΙΚΙΛΙΑΣ'后的右引号。 'ΧΥΜΟΙΑΧΛΑΔΙΩΝΤΗΣΠΟΙΚΙΛΙΑΣ'附近的语法不正确。

说明使用希腊语,我不知道这是否与错误有关。

到目前为止我的代码

private void startBtn_Click(object sender, EventArgs e)
{
     string sqlQuery = DatabaseTables.KodikoiTaric;

     if(checkBox1.Checked) 
          InsertDefaultValues(sqlQuery);
}

void InsertDefaultValues(string tableName)
{
    RepairTable(tableName);
    // DataTable csvData = GetDataTabletFromCSVFile(DatabaseTables.taric2);
}

void RepairTable(string tableName)
{
    try
    {
        string sqlConnectionString = Parameters.Config.ConnectionString;
        string script = tableName;
        var sqlqueries = script.Split(new[] { "GO" }, StringSplitOptions.RemoveEmptyEntries);

        SqlConnection conn = new SqlConnection(sqlConnectionString);

        SqlCommand cmd = new SqlCommand("query", conn);
        Server server = new Server(new ServerConnection(conn));

        conn.Open();
        var progressBar = 10;

        foreach (var query in sqlqueries)
        {
            progressBar += 10;
            cmd.CommandText = query;
            cmd.ExecuteNonQuery();
            conn.InfoMessage += delegate (object sender, SqlInfoMessageEventArgs e)
                {
                    FileStream ostrm;
                    StreamWriter writer;
                    TextWriter oldout = Console.Out;
                    string _dbUpdateLogPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + @"\DBUpdate" + DateTime.Now.ToString("ddMMyy") + ".txt";
                    try
                    {
                        if (!File.Exists(_dbUpdateLogPath))
                        {
                            ostrm = new FileStream(_dbUpdateLogPath, FileMode.OpenOrCreate, FileAccess.Write);
                            writer = new StreamWriter(ostrm);
                            Console.SetOut(writer);
                            Console.WriteLine(e.Message);
                            Console.SetOut(oldout);
                            writer.Close();
                            ostrm.Close();
                        }
                        else if (File.Exists(_dbUpdateLogPath))
                        {
                            ostrm = new FileStream(_dbUpdateLogPath, FileMode.Append, FileAccess.Write);
                            writer = new StreamWriter(ostrm);
                            Console.SetOut(writer);
                            Console.WriteLine(e.Message);
                            Console.SetOut(oldout);
                            writer.Close();
                            ostrm.Close();
                        }
                    }
                    catch (Exception ex)
                    {
                        NLogger.NLogger.LibraryLogClass.Error(ex.ToString());
                        return;
                    }

                };
            }

            conn.Close();
    }
    catch (Exception ex)
    {
        NLogger.NLogger.LibraryLogClass.Error(ex.ToString());
    }
}

我将文件作为资源文件,格式如下:

SET NUMERIC_ROUNDABORT OFF
GO

SET ANSI_PADDING, ANSI_WARNINGS, CONCAT_NULL_YIELDS_NULL, ARITHABORT, QUOTED_IDENTIFIER, ANSI_NULLS, NOCOUNT ON
GO

SET DATEFORMAT YMD
GO

SET XACT_ABORT ON
GO

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
GO

BEGIN TRANSACTION
GO

DELETE FROM [dbo].[KodikosTaric]
GO

SET IDENTITY_INSERT [dbo].[KodikosTaric] ON 

INSERT INTO [dbo].[KodikosTaric] ([Id], [KodikosTaric], [KoinotikonMetron_a], [KoinotikonMetron_b], [Perigrafi], [DasmosTritonXoron], [ProtimisiakosDasmos], [SimpliromatikesMonades], [YpologismosKila], [DiasafistisId]) 
VALUES (1, N'8701100000', NULL, NULL, N'ΕΛΚΥΣΤΗΡΕΣ ΧΕΙΡΟΔΗΓΟΥΜΕΝΟΙ', NULL, NULL, NULL, NULL, NULL),
       (2, N'8701201000', NULL, NULL, N'ΚΑΙΝΟΥΡΓΙΟΙ', NULL, NULL, NULL, NULL, NULL),
       (3, N'8701209000', NULL, NULL, N'ΜΕΤΑΧΕΙΡΙΣΜΕΝΟΙ', NULL, NULL, NULL, NULL, NULL)
      .
      .
      .

总是给我错误的那一行是

INSERT INTO [dbo].[KodikosTaric] ([Id], [KodikosTaric], [KoinotikonMetron_a], [KoinotikonMetron_b], [Perigrafi], [DasmosTritonXoron], [ProtimisiakosDasmos], [SimpliromatikesMonades], [YpologismosKila], [DiasafistisId]) 
VALUES (782, N'2009809711', NULL, NULL, N'ΧΥΜΟΙ ΑΧΛΑΔΙΩΝ ΤΗΣ ΠΟΙΚΙΛΙΑΣ GOYAVES', NULL, NULL, NULL, NULL, NULL)

在哪一行都没关系。我尝试将其放在文件的第一行,并抛出相同的错误。

有趣的是,如果我从SQL Server Express导入该文件作为查询,效果很好。

编辑: 感谢@Chris J,我开始了解这个问题。 所以问题是文件中有

  

GOYAVES

当我分割文本时,它将其视为GO而不是GOYAVES。我试图更改split命令

var sqlqueries = script.Split(new[] { "\nGO", "\ngo" }, StringSplitOptions.RemoveEmptyEntries);

我再也没有例外了,但问题是,即使它似乎可以正常工作并且可以更正sql文件,它也不会向表中写入任何内容。

编辑2: 我从sql脚本中删除了这些行

SET NUMERIC_ROUNDABORT OFF
GO

    SET ANSI_PADDING, ANSI_WARNINGS, CONCAT_NULL_YIELDS_NULL, ARITHABORT, QUOTED_IDENTIFIER, ANSI_NULLS, NOCOUNT ON
    GO

    SET DATEFORMAT YMD
    GO

    SET XACT_ABORT ON
    GO

    SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
    GO

    BEGIN TRANSACTION
    GO

,一切正常。谢谢大家的帮助

2 个答案:

答案 0 :(得分:5)

问题最有可能在这里

N'ΧΥΜΟΙ ΑΧΛΑΔΙΩΝ ΤΗΣ ΠΟΙΚΙΛΙΑΣ GOYAVES'
                               ^^

您正在执行的C#代码的早期版本:

var sqlqueries = script.Split(new[] { "GO" }, StringSplitOptions.RemoveEmptyEntries);

因此,可能会在子字符串中的“ GO”上拆分SQL查询。另一个提示是错误本身:

Unclosed quotation mark after the character string 'ΧΥΜΟΙ ΑΧΛΑΔΙΩΝ ΤΗΣ ΠΟΙΚΙΛΙΑΣ '.

此字符串是该完整字符串的子字符串,直到并包括空格。

您可能需要将C#更改为仅在行首查找GO

关于执行此操作的最佳方法,似乎您的代码将文件作为一个字符串整体读入内存,然后拆分该字符串。对于大文件,这可能会很慢并且内存效率低下:通常我会尝试避免自己这样做。

一种更有效的方法是在读取文件时进行拆分-这省去了读取和处理内存中大字符串的麻烦。像这样的事情就可以完成工作:

private IEnumerable<string> GetStatement(string sqlFile)
{
    using (var sr = new StreamReader(sqlFile))
    {
        string s;
        var sb = new StringBuilder();
        while ((s = sr.ReadLine()) != null)
        {
            if (s.Trim().Equals("GO", StringComparison.InvariantCultureIgnoreCase))
            {
                yield return sb.ToString();
                sb.Clear();
                continue;
            }

            sb.AppendLine(s);
        }

        yield return sb.ToString();
    }
}

此方法逐行读取文件,当它自身一行遇到“ GO”时,它将返回该批处理。每个都可以简单地调用它:

foreach (var batch in GetStatement("Batch.sql"))
{
    Console.WriteLine(batch);
}

如果您仍然希望完整读取文件并处理字符串,则可以将StreamReader换成StringReader并应用相同的方法。但是除非真正需要将整个文件加载到内存中,否则它会更简单(对于大文件来说可能更快),避免首先进行此操作,而是随心所欲地进行处理。

答案 1 :(得分:1)

如何?

  var sqlqueries = script.Split(new[] { "\rGO", "\r\nGO" }, 
             StringSplitOptions.RemoveEmptyEntries);

这两个字符串将匹配可能的换行符形式。

请参见How to split strings on carriage return with C#?