2015-04-26 11 views
8

Tôi đang phát triển một trình bao bọc nhỏ cho một dự án sử dụng sqlite3 với API C++ và VisualStudio 2010. Theo như nó đi và kiểm tra với một công cụ như SQLiteDataBaseBrowser, vấn đề chính là thông tin tôi cố gắng chèn vào bảng có vẻ bị hỏng/không xuất hiện chút nào. Bảng này có vẻ được tạo đúng với mã hóa UTF8.Sự cố mã hóa trong INSERT với Sqlite3 C++ và VisualStudio2010

Tôi đã thử sử dụng các giá trị cấu hình Tập ký tự trong VS là "Sử dụng bộ ký tự nhiều byte" và cũng đã thử "Sử dụng bộ ký tự Unicode" nhưng không có thay đổi trong kết quả. Cả hai đều cho tôi cùng một vấn đề với dữ liệu bị hỏng. Tôi sử dụng std :: string điển hình được chuyển đổi thành legacy c char * và như tôi đã thấy trong một số ví dụ rằng nó sẽ hoạt động đúng với các hàm sqlite3_bind_text (...) mà API cung cấp.

sqlite3_bind_int(stmt, 1, newShop.GetId()); 
    sqlite3_bind_text(stmt, 2, newShop.GetName().c_str(), -1, SQLITE_STATIC); 
    sqlite3_bind_text(stmt, 3, newShop.GetLocation().c_str(), -1, SQLITE_STATIC); 
    sqlite3_bind_text(stmt, 4, newShop.GetPicturePath().c_str(), -1, SQLITE_STATIC); 
    sqlite3_bind_text(stmt, 5, newShop.GetRegisters().c_str(), -1, SQLITE_STATIC); 
    sqlite3_bind_text(stmt, 6, newShop.GetMixes().c_str(), -1, SQLITE_STATIC); 
    sqlite3_bind_text(stmt, 7, newShop.GetAllowedUsers().c_str(), -1, SQLITE_STATIC); 
    sqlite3_bind_int(stmt, 8, newShop.IsAvailable() == true?1:0); 

newShop là một thể hiện của lớp chứa thông tin trong tiêu chuẩn :: strings và int. Tôi phải nói rằng các ràng buộc với loại int, làm việc hoàn hảo và không có vấn đề, nhưng những người khác nhìn hoàn toàn sai lầm. khi các chuỗi được mã hóa cứng, chúng cũng trông ổn cho đến khi tôi cố chèn các ký tự đặc biệt như "áàä" và như vậy.

Bảng này được tạo ra với các tuyên bố:

char *szSQL = "CREATE TABLE IF NOT EXISTS SHOPS (ID INTEGER PRIMARY KEY NOT NULL, NAME TEXT NOT NULL, LOCATION TEXT, PICTUREPATH TEXT, REGISTERS TEXT, MIXES TEXT, USERS TEXT, AVAILABLE INTEGER NOT NULL);"; 
int rc = sqlite3_exec(db, szSQL, NULL, 0, NULL); 

Đây là cách nó trông khi tôi chèn dữ liệu bằng cách sử dụng đoạn mã trên:

DataBase encoding problems

gửi nó từ một thử nghiệm WINUNIT trông giống như:

Shop shOne = Shop(1234, "Its about nothing", "Manhattan", "seinfeld.jpg", "1111,2222,3333", "1000x1,2000x7", "10,11,12", true); 
Shop shTwo = Shop(4321, "Louie", "Manhattan", "", "1111,5555", "50000x1,10000x5", "60,70", true); 

WIN_ASSERT_EQUAL(0, auxsql.InsertShop(shOne)); 
WIN_ASSERT_EQUAL(0, auxsql.InsertShop(shTwo)); 

Cả hai chèn, cam kết, việc tạo câu lệnh sql hoặc bất kỳ lệnh gọi hàm nào khác tới API sqlite3 trả về một mã lỗi.

+0

Mã hóa của 'std :: string' là gì? –

+0

Bạn đã tạo bảng như thế nào? bạn đã sử dụng loại văn bản nào? – SHR

+0

Các chuỗi là chuỗi cơ bản :: chuỗi. Bảng được tạo ra như sau: 'char * szSQL =" TẠO BẢNG NẾU KHÔNG XUẤT HIỆN GIÀY (ID INTEGER PRIMARY KEY KHÔNG NULL, TEXT TEXT NOT NULL, VĂN BẢN VĂN BẢN, HÌNH ẢNH HÌNH ẢNH, ĐĂNG KÝ TEXT, MIXES TEXT, USERS TEXT, AVAILABLE INTEGER NOT NULL); "; int rc = sqlite3_exec (db, szSQL, NULL, 0, NULL); ' –

Trả lời

3

Tôi đã tìm ra giải pháp. Nó không liên quan gì đến việc mã hóa, như tôi nghĩ bởi vì các nhân vật được biểu diễn kỳ lạ trong trình duyệt DB và cũng không có gì liên quan đến độ dài.

Sự cố nằm trong tham số cuối cùng của liên kết. Trong trường hợp tôi vượt qua SQLITE_STATIC, tôi nên đã thông qua SQLITE_TRANSIENT, khi đối tượng được trả về bởi các cuộc gọi tôi muốn ràng buộc có thể bị hủy trước khi truy vấn được thực thi.Cũng giống như được giải thích trong câu hỏi khác này:

sqlite3_bind_text SQLITE_STATIC vs SQLITE_TRANSIENT for c++ string

2

Tôi nghĩ rằng sqlite reference khá rõ ràng về việc sử dụng API.

Trong những thói quen có đối số thứ tư, giá trị của nó là số byte trong tham số. Để rõ ràng: giá trị là số lượng byte trong giá trị, không phải số ký tự.

Theo sử dụng của bạn,

sqlite3_bind_text(stmt, 2, newShop.GetName().c_str(), -1, SQLITE_STATIC); các đối số thứ 4 là -1. Tuy nhiên, cần phải là newShop.GetName().length hoặc strlen (newShop.GetName(). C_str()) `

Lưu ý: hãy cẩn thận khi bạn xử lý chuỗi có ký tự đa diện. Ở đâu strlen(chinese string) ! = chinese string.len. Tham khảo here để biết thêm chi tiết.

+0

Theo như tôi biết và tôi đã có thể thấy trong một số ví dụ trên web, chỉ định kích thước của chuỗi là một thực hành tốt để cải thiện tốc độ. Khi chỉ cần đặt -1 làm tham số, sqlite sẽ đoán kích thước của chính nó, vì vậy đây không phải là vấn đề (và nó không phải là, theo các bài kiểm tra của tôi). –

+0

@Ed là bạn gặp phải lỗi tương tự, ngay cả sau khi xác định độ dài một cách rõ ràng? –

+0

Có, tôi cũng đã thử văn bản ràng buộc như thế này 'sqlite3_bind_text (stmt, 2," hardcoded ", -1, SQLITE_STATIC);' và không có vấn đề với kích thước. Vì vậy, tôi sẽ nói rằng nó không phải là một vấn đề với lập luận này. –

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