5

我是 SQL Server 的新手

我已经像这样创建了我的表:

CREATE TABLE Accidents (
     Id INT NOT NULL PRIMARY KEY IDENTITY,
     GUID VARCHAR(100),
     Latitude VARCHAR(100),
     Longitude VARCHAR(100),
     PhotoName VARCHAR(100)        
     )

我创建了一个 Web 服务来向该表插入数据,如下所示:

    SqlConnection con = new SqlConnection(@"workstation id=DatabaseSample.mssql.somee.com;packet size=4096;user id=???;pwd=???;data source=DatabaseSample.mssql.somee.com;persist security info=False;initial catalog=DatabaseSample");

    public string addAccidentToDatabase(string GUID, string imageBase64String, string latitude, string longitude, string photoName)
    {
        SqlCommand cmd = new SqlCommand("INSERT INTO Accidents (GUID,Latitude,Longitude,PhotoName) VALUES ("
            + GUID + "," + latitude + "," + longitude + "," + photoName + ")", con);

        try
        {
            con.Open();
            cmd.ExecuteNonQuery();
        }
        catch (Exception e)
        {
            return e.Message;
        }
        finally
        {
            con.Close();
        }

        return "succeeded";
    }

所有这些东西都托管在免费的托管服务器上。

当我从 VS2010 测试 Web 服务时,当我将数字传递给所有参数时,新行成功添加到表中。但是当我将至少一个字符串传递给服务时,例如“a”,我得到这个结果:

<string xmlns="http://tempuri.org/">Invalid column name 'a'.</string>

并且没有添加该行。我想知道他为什么将“a”视为列名?任何人都可以帮忙吗?

4

5 回答 5

8

我想知道他为什么将“a”视为列名?

这不难看出。您不应该开发软件、部署它并希望它运行。你应该测试一下。将执行代码提取到类方法中,然后从您的服务中调用它。开发时,您可以从单元测试或命令行程序或任何您喜欢测试的程序中调用此方法。

您的问题:您没有在查询中的字符串(或 varchars,如果需要)周围加上引号。例如,如果您只是将查询字符串打印到控制台,您就会看到它。

但老实说,这是你的问题中最少的。你不应该手工制作 SQL。至少使用参数化查询。所以让你的查询是:

"INSERT INTO Accidents (GUID, Latitude, Longitude, PhotoName) 
                VALUES (@GUID, @Latitude, @Longitude, @PhotoName)"

并绑定参数:

cmd.Parameters.AddWithValue("@GUID", GUID);
...
于 2013-05-11T21:59:08.333 回答
4

请用这个替换你的代码。

 SqlCommand cmd = new SqlCommand("INSERT INTO Accidents (GUID,Latitude,Longitude,PhotoName) " + 
                                 "VALUES (@guid, @lat, @long, @photo)", con);
 cmd.Parameters.AddWithValue("@guid", GUID);
 cmd.Parameters.AddWithValue("@lat", latitude);
 cmd.Parameters.AddWithValue("@long", longitude);
 cmd.Parameters.AddWithValue("@photo", photoName);

为什么?好吧,假设您的一个字符串包含一个单引号。
查询将因语法错误而失败。但不要停止字符串。日期和十进制数字呢?您需要以适合数据库全球化设置的方式对它们进行格式化,以防下一个具有不同设置的客户失败。一个参数将为您解决这个问题。

最糟糕的。假设恶意用户在 PhotoName 的输入框中键入如下内容:

 p1.jpg'); DROP TABLE ACCIDENTS; -- 

这是一个很大的问题 - 它被称为Sql Injection,是的,一个参数可以防止这种情况。我真的希望您不要在拥有敏感信息的数据库上编写此代码。

于 2013-05-11T22:08:34.257 回答
2

你需要在你的字符串周围加上引号。您只是直接替换值,因此 SQL 试图将它们解析为列。

SqlCommand cmd = new SqlCommand("INSERT INTO Accidents (GUID,Latitude,Longitude,PhotoName)    
       VALUES ('" + GUID + "','" + latitude + "','" + longitude + "','" + photoName + "')", con);

但是,您应该注意,这是非常不安全的代码。它很容易发生 SQL 注入。尝试改用参数化查询。

于 2013-05-11T21:59:43.160 回答
2

我猜您的 GUID 值以a. 如果它以 a 开头,3您可能会得到更有趣的东西。

由于您将它作为字符串传递,而不是用引号将其转义,因此您会收到错误消息。

SqlCommand cmd = new SqlCommand("INSERT INTO Accidents (GUID,Latitude,Longitude,PhotoName) VALUES ("
            + "\"" + GUID + "\"," + latitude + "," + longitude + ",\"" + photoName + "\")", con);

几点:

  1. 您确实应该避免以这种方式构建查询。使用存储过程或参数化查询。

  2. 你为什么将 a 存储guid为 a varchar()?有一个非常好的Guid数据类型可用。

  3. 不要以数据类型命名列。

于 2013-05-11T21:59:56.130 回答
1

你需要单引号来字符串值

但我强烈建议您使用 SQLParameters避免任何SQLInjections攻击

您可以在此处找到使用SQL 参数的示例

于 2013-05-11T22:00:08.647 回答