问题 SQLite - 是否可以通过insert语句插入BLOB?


我正在开发一个Android应用程序,我正在使用Sqlite数据库来存储一些位图。我希望在用户安装应用程序时自动插入一些图像。

我正在使用 SQLiteOpenHelper 像这样的类:

public class DatabaseHelper extends SQLiteOpenHelper {

...

DatabaseHelper(Context context, String nameOfDB, int version, String[] scriptSQLCreate,
        String scriptSQLDelete) {
    super(context, nameOfDB, null, version);

    this.scriptSQLCreate = scriptSQLCreate;
    this.scriptSQLDelete = scriptSQLDelete;
}

@Override
public void onCreate(SQLiteDatabase db) {
    int numScripts = scriptSQLCreate.length;
    for(int i = 0; i<numScripts; i++){
    Log.i(TAG,"Creating database, executing script " + i);
    db.execSQL(scriptSQLCreate[i]);
    }
}
}

...

我想将一个常量传递给上面显示的scriptSQLCreate参数,如下所示:

private static final String[] SCRIPT_DATABASE_CREATE = {
   "create table memes(  id integer primary key autoincrement," + 
                     + " img blob not null," + 
                     + " name text not null unique)" ,
   "insert into memes(img,name) values(BITMAP1,'1.jpg')",
   "insert into memes(img,name) values(BITMAP2,'2.jpg')",
   "insert into memes(img,name) values(BITMAP3,'3.jpg')"}    

}

任何帮助都会被贬低,

谢谢, Tulio Zahn


7725
2018-01-16 17:44


起源



答案:


如果你真的,真的想要你可以使用一个很长的十六进制文字作为blob文字:

insert into memes(img, name) values(X'0102030405060708090a0b0c0d0e0f', '1.jpg')

然而,这通常是一个坏主意;相反,去看看 参数化查询。它们将允许您使用占位符而不是实际值编译语句,然后多次重复使用,根据需要填充占位符:

SQLiteStatement p = sqlite.compileStatement("insert into memes(img, name) values(?, ?)");

byte[] data = loadData("1.jpg");
p.bindBlob(1, data);
p.bindString(2, "1.jpg");
p.execute();

byte[] data = loadData("2.jpg");
p.bindBlob(1, data);
p.bindString(2, "2.jpg");
p.execute();

(警告---代码未经测试。)

通常,您应该使用参数化查询 到处,因为它们是避免SQL注入攻击的可靠方法,而且通常更容易和更清晰。应该不惜一切代价避免通过将字符串粘合在一起来组装SQL查询。


16
2018-01-16 18:09



嗯,你的方法绝对有趣。如果需要使用数百个位图预填充数据库而不是少数位图,则更是如此。在这种情况下,拥有数百个插入语句变得非常不切实际。我将测试你的方法,但首先我必须找到解决所有这些图像的问题的解决方案。在拥有很多它们的情况下,将它们放在drawable文件夹中似乎也是非常不切实际的 - tulio84z
你想要的是项目中的资产目录---有一个API可以让你访问那里的文件,好像它们是文件系统上的真实文件: developer.android.com/reference/android/content/res/... - David Given


答案:


如果你真的,真的想要你可以使用一个很长的十六进制文字作为blob文字:

insert into memes(img, name) values(X'0102030405060708090a0b0c0d0e0f', '1.jpg')

然而,这通常是一个坏主意;相反,去看看 参数化查询。它们将允许您使用占位符而不是实际值编译语句,然后多次重复使用,根据需要填充占位符:

SQLiteStatement p = sqlite.compileStatement("insert into memes(img, name) values(?, ?)");

byte[] data = loadData("1.jpg");
p.bindBlob(1, data);
p.bindString(2, "1.jpg");
p.execute();

byte[] data = loadData("2.jpg");
p.bindBlob(1, data);
p.bindString(2, "2.jpg");
p.execute();

(警告---代码未经测试。)

通常,您应该使用参数化查询 到处,因为它们是避免SQL注入攻击的可靠方法,而且通常更容易和更清晰。应该不惜一切代价避免通过将字符串粘合在一起来组装SQL查询。


16
2018-01-16 18:09



嗯,你的方法绝对有趣。如果需要使用数百个位图预填充数据库而不是少数位图,则更是如此。在这种情况下,拥有数百个插入语句变得非常不切实际。我将测试你的方法,但首先我必须找到解决所有这些图像的问题的解决方案。在拥有很多它们的情况下,将它们放在drawable文件夹中似乎也是非常不切实际的 - tulio84z
你想要的是项目中的资产目录---有一个API可以让你访问那里的文件,好像它们是文件系统上的真实文件: developer.android.com/reference/android/content/res/... - David Given


您的数据表有一些 看不见的单词 你看不到的。使用dbic工具检查db文件,例如navicat for sqlite。请注意表中的错误字。


0
2017-08-19 03:35