1

我正在开发一个程序,该程序允许用户选择 MS Access 表,然后将其导出到特定目的地的 .csv 文件。问题是当所选表包含 sql 特殊字符时出现错误。

我已经对该主题进行了一些研究,并且我知道我需要使用参数,但我无法弄清楚如何实际这样做。这是我的代码示例:

        string destination = Form2.destination;
        string selectString = "SELECT * FROM " + tablename;                      
        string path = destination + "\\" + tablename + ".csv"; 
        File.Create(path).Dispose();
        TextWriter tw = new StreamWriter(path);

        OleDbConnection connection = new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + txtDataPath.Text);
        connection.Open();
        DataSet myDataSet = new DataSet();

        OleDbCommand command = new OleDbCommand(selectString,connection);

        OleDbDataAdapter adapter = new OleDbDataAdapter(command.CommandText,connection);
        adapter.Fill(myDataSet, tablename);

到目前为止,如果选择了没有特殊字符的表名,则会创建 csv 文件并且看起来不错,但如果它包含类似“-”的内容,那么我的程序会产生“FROM 子句中的语法错误”是因为特殊的性格。

到目前为止,我所看到的所有示例都不适用于我正在尝试做的具体事情,所以希望有人可以帮助我。谢谢。

4

5 回答 5

4

您的实际查询不需要参数,因为它们可用于为 WHERE 条件或 INSERT/UPDATE 语句提供值,但不能用于替换表名或列名。

但是,如果表名包含特殊字符(例如空格),则表名本身就有
问题 为避免此问题,请将表名括在方括号中

string selectString = "SELECT * FROM [" + tablename + "]";

请记住,以这种方式连接字符串是非常危险的。如果 tablename 变量来自未经适当检查的用户输入,您将面临Sql Injection Attack的风险。

也不要使用字符串连接来构建你的路径,有一个非常方便的类

string path = Path.Combine(destination, tablename + ".csv"); 

最后,尝试使用Using 语句来封装你的连接和其他一次性对象,因为它可以确保正确关闭和处理这些对象,否则可能会成为程序稳定性的问题

using(OleDbConnection connection = new OleDbConnection("........"))
using(OleDbCommand command = new OleDbCommand(selectString,connection))
using(OleDbDataAdapter adapter = new OleDbDataAdapter(command))
{
    connection.Open();
    DataSet myDataSet = new DataSet();
    adapter.Fill(myDataSet, tablename);
}
于 2013-05-24T20:40:21.583 回答
2

用括号将表名括起来。以下应该是有效的命令:

SELECT foo FROM [Le Tablé]

您也可以将括号添加到没有特殊字符的表名中,因此无论如何都将它们全部包起来并感到高兴。

于 2013-05-24T20:40:42.160 回答
1

尝试将您的表名括在括号中。

SELECT * FROM [Some Table Name]
于 2013-05-24T20:39:54.373 回答
1

首先,将表名括在括号中,如下所示:

string selectString = "SELECT * FROM [" + tablename + "]";

其次,像这样参数化您的查询:

command.Parameters.Add("@parametername1here", OleDbType.VarChar).value = "somevalue"
command.Parameters.Add("@parametername2here", OleDbType.VarChar).value = "someothervalue"
于 2013-05-24T20:42:05.370 回答
0

据我所知,你有两个选择。

第一个更简单的选择是只清理表名:

tableName = tableName.replace("-", "\\-");

第二个选项在这里可能不合适,是让 C# 使用SqlParameter实例自动为您转义名称。类似于(伪代码):

    string selectString = "SELECT * FROM @tableName";                      
    // [...]
    OleDbCommand command = new OleDbCommand(selectString, connection);
    command.AddParameter(new SqlParamter("@tableName", tablename); // auto-escapes
于 2013-05-24T20:41:14.587 回答