我想将它用作“修复表”,在其中我将添加更多带有数据的表,我总是会收到错误,我无法理解为什么.
错误是
Message – System.Data.SqlClient.SqlException (0x80131904): Unclosed quotation mark after the character string ‘ΧΥΜΟΙ ΑΧΛΑΔΙΩΝ ΤΗΣ ΠΟΙΚΙΛΙΑΣ ‘. Incorrect syntax near ‘ΧΥΜΟΙ ΑΧΛΑΔΙΩΝ ΤΗΣ ΠΟΙΚΙΛΙΑΣ ‘.
描述是希腊语,我不知道这是否与错误有关.
我的代码到目前为止
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
一切都很好.谢谢大家的帮助
问题最有可能在这里:N'ΧΥΜΟΙ ΑΧΛΑΔΙΩΝ ΤΗΣ ΠΟΙΚΙΛΙΑΣ GOYAVES' ^^
在您的C#代码中,您正在做的事情是:
var sqlqueries = script.Split(new[] { "GO" }, StringSplitOptions.RemoveEmptyEntries);
因此,它可能会将您的SQL查询拆分为子字符串中的“GO”.另一个线索是错误本身:
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并应用相同的方法.但除非你真的需要将整个文件加载到内存中,否则它更简单(并且对于大文件来说可能更快),以避免在第一个实例中执行此操作并且只是随时处理.