【问题标题】:SQL Syntax Error: Remove/Disclude Apostrophe's?SQL 语法错误:删除/排除撇号的?
【发布时间】:2013-07-25 11:20:24
【问题描述】:

我使用以下代码更新我的一个 Windows 窗体上的企业信息。当用户在 txtBusName 中将公司名称输入为“Sandy's Place”之类的内容时,我会收到Incorrect Syntax near ';'. Unclosed quotation mark after the character string ';'.

处理此问题的最佳方法是什么?

conn = new SqlConnection(connString);
conn.Open();
SqlCommand cmd = conn.CreateCommand();

mskZip.TextMaskFormat = MaskFormat.ExcludePromptAndLiterals;
string zip = mskZip.Text;
mskZip.TextMaskFormat = MaskFormat.IncludeLiterals;
mskMailZip.TextMaskFormat = MaskFormat.ExcludePromptAndLiterals;
string mailzip = mskMailZip.Text;
mskMailZip.TextMaskFormat = MaskFormat.IncludeLiterals;
mskPhone.TextMaskFormat = MaskFormat.ExcludePromptAndLiterals;
string phone = mskPhone.Text;
mskPhone.TextMaskFormat = MaskFormat.IncludeLiterals;
mskFax.TextMaskFormat = MaskFormat.ExcludePromptAndLiterals;
string fax = mskFax.Text;
mskFax.TextMaskFormat = MaskFormat.IncludeLiterals;


cmd.CommandText = "Update Business SET Name='" + txtBusName.Text + "', ContactName='" + txtContName.Text +
                "', Address='" + txtAddr1.Text + "', City='" + txtCity.Text + "', State='" + cmbState.Text + "', Zip=" + ((zip=="")?"NULL":zip) + ", " +
                "MailAddress='" + txtMailAddr1.Text + "', MailCity='" + txtMailCity.Text + "', MailState='" + cmbMailState.Text +
                "', MailZipcode=" + ((mailzip == "") ? "NULL" : mailzip) + ", Latitude=" + ((txtLat.Text == "") ? "NULL" : txtLat.Text) + ", Longitude=" + ((txtLong.Text == "") ? "NULL" : txtLong.Text) + ", Phone=" +
                ((phone == "") ? "NULL" : phone) + ", Fax=" + ((fax == "") ? "NULL" : fax) + ", Email='" + txtEmail.Text + "' " +
                "WHERE BusinessID=" + busID + " AND Status='A';";

cmd.ExecuteNonQuery();

MessageBox.Show("Database updated successfully.");
this.Close();

【问题讨论】:

  • 使用参数化查询
  • @Steve 参数化查询如何帮助防止问题发生?

标签: c# .net sql-server syntax-error


【解决方案1】:

你需要像这样使用parameterized query

cmd.CommandText = 
        "Update Business SET Name=@name, ContactName=@contact, Address=@address, " + 
                "City=@city, State=@state, Zip=@zip, " +
                "MailAddress=@mail, MailCity=@ecity, MailState=@estate, " +
                "MailZipcode=@ezip, Latitude=@lat, Longitude=@lng, Phone=@phone, " +
                "Fax=@fax, Email=@email " +
                "WHERE BusinessID=@busID AND Status='A'";

cmd.Parameters.AddWithValue("@name", txtBusName.Text);
cmd.Parameters.AddWithValue("@contact", txtContName.Text); 
cmd.Parameters.AddWithValue("@address", txtAddr1.Text);
cmd.Parameters.AddWithValue("@city", txtCity.Text);
cmd.Parameters.AddWithValue("@state", cmbState.Text);

SqlParameter p1 = cmd.Parameters.Add("@zip", SqlDbType.NVarChar);
if(zip == "") p1.Value = DBNull.Value; else p1.Value = zip;

cmd.Parameters.AddWithValue("@mail",  txtMailAddr1.Text);
cmd.Parameters.AddWithValue("@ecity", txtMailCity.Text);
cmd.Parameters.AddWithValue("@estate", cmbMailState.Text);

p1 = cmd.Parameters.Add("@ezip", SqlDbType.NVarChar);
if (mailzip == "") p1.Value = DBNull.Value; else p1.Value = mailzip;

p1 = cmd.Parameters.Add("@lat", SqlDbType.NVarChar);
if (txtLat.Text == "") p1.Value = DBNull.Value; else p1.Value = txtLat.Text;

p1 = cmd.Parameters.Add("@lng", SqlDbType.NVarChar);
if (txtLong.Text == "") p1.Value = DBNull.Value; else p1.Value = txtLong.Text;

p1 = cmd.Parameters.Add("@phone", SqlDbType.NVarChar);
if (phone == "") p1.Value = DBNull.Value; else p1.Value = phone;

p1 = cmd.Parameters.Add("@fax", SqlDbType.NVarChar);
if (fax == "") p1.Value = DBNull.Value; else p1.Value = fax;

cmd.Parameters.AddWithValue("@email", txtEmail.Text );
cmd.Parameters.AddWithValue("@busID", busID); 

上面链接的文章值得从头到尾阅读,但是,总而言之,使用参数化查询,您可以将单引号(以及数字小数和日期文字)格式化为更了解的框架代码比我和你如何处理这些字符串,并且通过这种方式你可以避免可怕的Sql Injection 问题,这可能会使你的数据库暴露于黑客攻击

注意:我不知道应该设置为 null 的列的实际数据类型,所以我假设它们都是 NVARCHAR。如果不是这种情况,则应将 SqlDbType 替换为适当的值。

【讨论】:

  • 感谢您提供的清晰示例!我现在可以看到以前代码的安全问题:SI 有一个问题:当我将鼠标悬停在任何 DBNull.Value : ... 上时,我有一个红色标记,上面写着:“错误:条件表达式的类型无法确定,因为'System.DBNull' 和 'string' 之间没有隐式转换".
  • 是的,我看到了问题,现在正在修复
  • 看起来 Zip 是 Varchar(15)、MailZipCode Varchar(15)、Latitude Varchar(20)、 经度 Varchar(20)、电话 Varchar(25)、传真 Varchar(25)。将更改代码并通知您。
【解决方案2】:
【解决方案3】:

请使用 SqlParameter 对象,而不是这样的字符串连接。比如:

    string sql = "Update Business SET Name=@Name, ContactName=@ContactName, Address=@Address WHERE BusinessID=@BusinessID AND Status='A';";
    System.Data.SqlClient.SqlParameter[] par = new System.Data.SqlClient.SqlParameter[4];
    par[0] = new System.Data.SqlClient.SqlParameter("@Name", txtBusName.Text);
    par[1] = new System.Data.SqlClient.SqlParameter("@ContactName", txtContName.Text);
    par[2] = new System.Data.SqlClient.SqlParameter("@Address", txtAddr1.Text);
    par[3] = new System.Data.SqlClient.SqlParameter("@BusinessID", busID);

        System.Data.SqlClient.SqlCommand com = new System.Data.SqlClient.SqlCommand(sql, SQL_CONNECTION);
        com.Parameters.AddRange(par);
        com.ExecuteNonQuery();

你的参数太多所以没有全部写出来:)

使用这种方法将为您处理撇号等特殊字符,并使代码看起来更清晰、更易读和更安全。

【讨论】:

  • 感谢您输入您所做的内容:) 不过,这对解决额外引号问题有何帮助?
  • 如果您使用 SqlParameter 它会为您处理特殊字符,例如撇号或某些符号(不记得我的头顶)。
【解决方案4】:

使用双单引号在 SQL 中转义单引号,因此 Sandy''s place 应该可以工作。

我强烈建议您使用查询参数而不是将您自己的查询串在一起,这可以解决潜在的安全风险(SQL 注入)以及最有可能的问题,例如您的引号。

【讨论】:

  • 我明白你关于注射风险的意思。但是,参数化查询如何帮助解决这个问题?
  • 因为它会关心编码特殊字符等。
猜你喜欢
  • 2017-12-28
  • 1970-01-01
  • 1970-01-01
  • 2022-08-11
  • 2017-05-22
  • 1970-01-01
  • 2020-04-19
  • 2012-08-07
  • 1970-01-01
相关资源
最近更新 更多