2013-05-11 35 views
5

Tôi mới đến SQL ServerSQL Server tên cột không hợp lệ khi thêm chuỗi giá trị

tôi đã tạo ra bàn của tôi như thế này:

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

và tôi đã tạo ra một dịch vụ web để chèn dữ liệu vào bảng đó, như sau:

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"; 
    } 

Tất cả nội dung đó được lưu trữ trên máy chủ lưu trữ miễn phí.

Khi tôi kiểm tra dịch vụ web từ VS2010 và khi tôi chuyển số cho tất cả các thông số, một hàng mới được thêm thành công vào bảng. Nhưng khi tôi chuyển ít nhất một chuỗi cho dịch vụ, ví dụ "a", tôi nhận được kết quả này:

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

và hàng không được thêm vào. Tôi tự hỏi tại sao anh ta coi "a" như một tên cột? Bất cứ ai cũng có thể giúp đỡ?

+4

lý do bỏ phiếu xuống? Tôi chỉ yêu cầu :) –

+4

+1 để chống lại downvote ngu ngốc. Các bạn, tôi nghĩ đây là nơi mọi người có thể đặt câu hỏi? Cảnh sát cảnh sát thường không ra ngoài cho đến sáng thứ Hai. –

+1

[Thói quen xấu để đá: chọn loại dữ liệu sai] (http://sqlblog.com/blogs/aaron_bertrand/archive/2009/10/12/bad-habits-to-kick-using-the-wrong-data- type.aspx) - bạn nên luôn luôn sử dụng kiểu dữ liệu thích hợp nhất - đó là những gì họ đang có cho, sau khi tất cả! Vì vậy, một cột 'GUID' phải thuộc loại' UNIQUEIDENTIFIER' và các giá trị số như 'Longitude' và' Latitude' phải là 'DECIMAL (16,4)' hoặc một cái gì đó tương tự - ** not ** 'varchar (100) '! –

Trả lời

7

Tôi tự hỏi tại sao ông coi "a" là tên cột?

Điều đó không khó thấy. Bạn không nên phát triển phần mềm, triển khai nó và hy vọng nó chạy. Bạn nên kiểm tra nó. Trích xuất mã thực thi thành một phương thức lớp và gọi nó từ dịch vụ của bạn. Khi phát triển, bạn gọi phương thức này từ một bài kiểm tra đơn vị hoặc chương trình dòng lệnh hoặc bất kỳ thứ gì bạn muốn thử nghiệm.

Vấn đề của bạn: bạn không đặt dấu ngoặc kép quanh các chuỗi (hoặc varchars nếu bạn muốn) trong truy vấn. Bạn sẽ thấy nó nếu bạn chỉ in chuỗi truy vấn vào giao diện điều khiển chẳng hạn.

Nhưng thành thực thì đó là vấn đề ít nhất của bạn. Bạn không nên thủ công SQL. Ít nhất sử dụng truy vấn được tham số hóa. Vì vậy, hãy truy vấn của bạn là:

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

Và kết các thông số:

cmd.Parameters.AddWithValue("@GUID", GUID); 
... 
+0

Bạn nói đúng. Tôi nên ghi nhớ điều này. –

+3

Nếu OP không thấy khó, tôi nghi ngờ câu hỏi sẽ được hỏi. Câu trả lời tuyệt vời, nhưng một chút giảm dần. –

2

Bạn cần dấu ngoặc kép quanh chuỗi của bạn. Bạn chỉ đang thay thế trực tiếp trong các giá trị, vì vậy SQL đang cố gắng phân tích chúng thành các cột.

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

Bạn nên lưu ý, tuy nhiên, đây là mã cực kỳ không an toàn. Nó rất dễ bị tiêm SQL. Hãy thử sử dụng các truy vấn tham số.

+0

Cảm ơn bạn đã giải quyết vấn đề. –

2

Tôi đoán giá trị GUID của bạn bắt đầu bằng a. Nếu nó bắt đầu với một 3 bạn có thể có được một cái gì đó thú vị hơn.

Vì bạn đang chuyển nó dưới dạng chuỗi và không thoát bằng dấu ngoặc kép, bạn nhận được lỗi.

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

Một vài điểm:

  1. Bạn thực sự nên tránh các truy vấn xây dựng theo cách này. Sử dụng thủ tục được lưu trữ hoặc truy vấn được tham số hóa.

  2. tại sao bạn lưu trữ guid làm varchar()? Có sẵn kiểu dữ liệu Guid rất đẹp.

  3. Không đặt tên cột sau loại dữ liệu.

+0

Cảm ơn các điểm. –

1

bạn cần dấu nháy đơn để chuỗi giá trị

Nhưng tôi strightly khuyên bạn nên sử dụng SqlParameters để tránh bất kỳ SQLInjections tấn công

Bạn có thể tìm thấy ví dụ của việc sử dụng SQL Parameters here

+0

Cảm ơn bạn đã liên kết. Tôi phải cẩn thận hơn. –

4

Xin vui lòng, thay thế mã của bạn bằng cách này.

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); 

Tại sao? Vâng, giả sử rằng một trong các chuỗi của bạn chứa một trích dẫn duy nhất.
Truy vấn sẽ không thành công với lỗi cú pháp. Nhưng không dừng lại để dây. Điều gì về ngày tháng và số thập phân? Bạn cần phải định dạng chúng theo cách có hiệu quả với các cài đặt toàn cầu hóa cơ sở dữ liệu, chỉ để thất bại trên khách hàng tiếp theo với các cài đặt khác nhau. Một tham số sẽ giải quyết điều này cho bạn.

Tệ nhất. Giả sử mà người dùng độc hại, trong inputbox cho PhotoName, một cái gì đó như thế này:

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

Đó là một lớn, vấn đề lớn - Nó được gọi là Sql Injection, và có, một tham số để phòng ngừa. Tôi thực sự hy vọng rằng bạn không viết mã này trên cơ sở dữ liệu nơi bạn có thông tin nhạy cảm.

Các vấn đề liên quan