为什么SQLite从我的整数中生成BLOB?

时间:2017-09-08 14:16:48

标签: android sqlite android-sqlite

在这个字符串中,我将Spinner的索引放到数据库中:

values.put(LinkDbHelper.COLUMN_TYPE, spinner.getSelectedItemPosition());

但是当我在手机上检查.db文件时,我看到了BLOB。 为什么BLOB如果这个字段的类型是INTEGER NOT NULL DEFAULT?

完全创建表字符串:

"CREATE TABLE " + TABLE_NAME
            + " (" + BaseColumns._ID + " INTEGER PRIMARY KEY AUTOINCREMENT, "
            + COLUMN_TYPE + " INTEGER  NOT NULL DEFAULT 0, "
            + COLUMN_NAME + " TEXT NOT NULL, "
            + COLUMN_LINK + " TEXT NOT NULL, "
            + COLUMN_IMAGE + " BLOB);"

1 个答案:

答案 0 :(得分:1)

我相信你的问题是,你实际上已经在COLUMN_TYPE中存储了一个blob。

SQLite非常灵活,包括能够在任何地方存储任何类型的数据(下面的激励): -

  

SQLite版本3数据库中的任何列,但INTEGER PRIMARY除外   KEY列,可用于存储任何存储类的值。   Datatypes In SQLite Version 3 - 2. Storage Classes and Datatypes

我做了一些测试并得出以下结果: -

09-09 15:27:31.347 5114-5114/? D/TBCRT: CREATE TABLE table1(_id INTEGER PRIMARY KEY, type INTEGER NOT NULL DEFAULT 0, alt1 BLOB, name TEXT NOT NULL, link TEXT NOT NULL, image BLOB)
09-09 15:27:31.365 5114-5114/? D/DBINFO: Row 0
09-09 15:27:31.366 5114-5114/? D/DBINFO:    
                                         Column Name=_id   Value=1  
                                         Column Name=type   Value=unobtainable  
                                         Column Name=alt1   Value=unobtainable  
                                         Column Name=name   Value=1504934851322 
                                         Column Name=link   Value=10101111001100101000110110111001011111010 
                                         Column Name=image   Value=2.45678  
                                         Column Name=TYPE_TYPECOLUMN   Value=blob   
                                         Column Name=TYPE_ALT1COLUMN   Value=blob   
                                         Column Name=TYPE_NAMECOLUMN   Value=text   
                                         Column Name=TYPE_LINKCOLUMN   Value=text   
                                         Column Name=TYPE_IMAGECOLUMN   Value=real
09-09 15:27:31.366 5114-5114/? D/DBINFO: Row 1
09-09 15:27:31.366 5114-5114/? D/DBINFO:    
                                         Column Name=_id   Value=2  
                                         Column Name=type   Value=-1    
                                         Column Name=alt1   Value=-1    
                                         Column Name=name   Value=FRED  
                                         Column Name=link   Value=MYLINK    
                                         Column Name=image   Value=unobtainable 
                                         Column Name=TYPE_TYPECOLUMN   Value=integer    
                                         Column Name=TYPE_ALT1COLUMN   Value=integer    
                                         Column Name=TYPE_NAMECOLUMN   Value=text   
                                         Column Name=TYPE_LINKCOLUMN   Value=text   
                                         Column Name=TYPE_IMAGECOLUMN   Value=blob
09-09 15:27:31.366 5114-5114/? D/DBINFO: Row 2
09-09 15:27:31.366 5114-5114/? D/DBINFO:    
                                         Column Name=_id   Value=3  
                                         Column Name=type   Value=0 
                                         Column Name=alt1   Value=100   
                                         Column Name=name   Value=Bert  
                                         Column Name=link   Value=noweher   
                                         Column Name=image   Value=unobtainable 
                                         Column Name=TYPE_TYPECOLUMN   Value=integer    
                                         Column Name=TYPE_ALT1COLUMN   Value=integer    
                                         Column Name=TYPE_NAMECOLUMN   Value=text   
                                         Column Name=TYPE_LINKCOLUMN   Value=text   
                                         Column Name=TYPE_IMAGECOLUMN   Value=blob
09-09 15:27:31.366 5114-5114/? D/DBINFO: Row 3
09-09 15:27:31.366 5114-5114/? D/DBINFO:    
                                         Column Name=_id   Value=4  
                                         Column Name=type   Value=unobtainable  
                                         Column Name=alt1   Value=unobtainable  
                                         Column Name=name   Value=1504934851362 
                                         Column Name=link   Value=10101111001100101000110110111001100100010 
                                         Column Name=image   Value=2.45678  
                                         Column Name=TYPE_TYPECOLUMN   Value=blob   
                                         Column Name=TYPE_ALT1COLUMN   Value=blob   
                                         Column Name=TYPE_NAMECOLUMN   Value=text   
                                         Column Name=TYPE_LINKCOLUMN   Value=text   
                                         Column Name=TYPE_IMAGECOLUMN   Value=real

由于第一行显示使用 INTEGER NOT NULL DEFAULT 0 创建类型列,因此使用创建 alt1 BLOB

第0行的输出表示类型列的类型为 blob ,但是对于第1行,则显示类型具有整数的类型。第2行反映与第1行和第3行相同的类型,与第0行相同。

请注意!如果用于尝试获取BLOB,Cursor getString方法将抛出异常,因此在这种情况下,该值显示为无法获取

简而言之,您可以看到列类型的动态性以及创建表时指定的内容并不是一种快速(静态类型)。

为了实现上述目的,我在DBHelper中使用了以下内容: -

public class DBHelper extends SQLiteOpenHelper {

    private static final String DBNNAME = "mydatabase";
    private static final int DBVESRION = 1;
    private static final String TABLENAME = "table1";
    private static final String IDCOLUMN = "_id";
    private static final String TYPECOLUMN = "type";
    private static final String ALT1COLUMN = "alt1";
    private static final String NAMECOLUMN = "name";
    private static final String LINKCOLUMN = "link";
    private static final String IMAGECOLUMN = "image";

    DBHelper(Context context) {
        super(context, DBNNAME, null, DBVESRION);
    }


    @Override
    public void onCreate(SQLiteDatabase db) {

        String crtsql = "CREATE TABLE " + TABLENAME + "(" +
                IDCOLUMN + " INTEGER PRIMARY KEY, " +
                TYPECOLUMN + " INTEGER NOT NULL DEFAULT 0, " +
                ALT1COLUMN + " BLOB, " +
                NAMECOLUMN + " TEXT NOT NULL, " +
                LINKCOLUMN + " TEXT NOT NULL, " +
                IMAGECOLUMN + " BLOB" +
                ")";
        Log.d("TBCRT",crtsql);
        db.execSQL(crtsql);

    }
    @Override
    public void onUpgrade(SQLiteDatabase db, int oldversion, int newversion){

    }

.....(更多内容)

以上代码按照以下方式创建数据库和单个表: -

CREATE TABLE table1(_id INTEGER PRIMARY KEY, type INTEGER NOT NULL DEFAULT 0, alt1 BLOB, name TEXT NOT NULL, link TEXT NOT NULL, image BLOB)

上面的代码后跟3个方法: -

insertRow - 以通常的方式插入行。

public void insertRow(int type, int alt, String name, String link, byte[] image) {
    ContentValues cv = new ContentValues();
    cv.put(TYPECOLUMN,type);
    cv.put(ALT1COLUMN,alt);
    cv.put(NAMECOLUMN,name);
    cv.put(LINKCOLUMN,link);
    cv.put(IMAGECOLUMN,image);

    this.getWritableDatabase().insert(TABLENAME,null,cv);
}

insertAlternativeRow 以插入具有强制类型的行。

public void insertAlternativeRow() {
    ContentValues cv = new ContentValues();
    cv.put(TYPECOLUMN,new byte[]{100,100,100,100,100});
    cv.put(ALT1COLUMN,new byte[]{25,25,25,25,25,25,67,45,23,43,17,89,56,34,32,111,21,31,41,51,61,71,81,91,
            25,25,25,25,25,67,45,23,43,17,89,56,34,32,111,21,31,41,51,61,71,81,91,
            25,25,25,25,25,67,45,23,43,17,89,56,34,32,111,21,31,41,51,61,71,81,91
            ,25,25,25,25,25,67,45,23,43,17,89,56,34,32,111,21,31,41,51,61,71,81,91
            ,25,25,25,25,25,67,45,23,43,17,89,56,34,32,111,21,31,41,51,61,71,81,91
            ,25,25,25,25,25,67,45,23,43,17,89,56,34,32,111,21,31,41,51,61,71,81,91
            ,25,25,25,25,25,67,45,23,43,17,89,56,34,32,111,21,31,41,51,61,71,81,91});
    cv.put(NAMECOLUMN,Long.toString(System.currentTimeMillis()));
    cv.put(LINKCOLUMN,Long.toBinaryString(System.currentTimeMillis()));
    cv.put(IMAGECOLUMN,2.45678d);
    this.getWritableDatabase().insert(TABLENAME,null,cv);
}

viewRowsWithTypes 根据typeof函数输出包含列名,存储值和列类型的行。

public Cursor viewRowsWithTypes() {
     return this.getWritableDatabase().query(TABLENAME,
            new String[] {
            "*, " +
                    "typeof(" + TYPECOLUMN + ") AS TYPE_TYPECOLUMN, " +
                    "typeof(" + ALT1COLUMN + ") AS TYPE_ALT1COLUMN, " +
                    "typeof(" + NAMECOLUMN + ") AS TYPE_NAMECOLUMN, " +
                    "typeof(" + LINKCOLUMN + ") AS TYPE_LINKCOLUMN, " +
                    "typeof(" + IMAGECOLUMN + ") AS TYPE_IMAGECOLUMN "
    },
            null,null,null,null,null);
}

activty_main.xml 中,我编写了一个基本的微调器,其id为 myspinner

MainActivity 中我编码: -

    myspinner = (Spinner) findViewById(R.id.myspinner);
    dbhlpr.insertAlternativeRow(); //Insert a row with forced types
    dbhlpr.insertRow(myspinner.getSelectedItemPosition(),
            myspinner.getSelectedItemPosition(),
            "FRED","MYLINK",new byte[]{0,7,5,4,3,2,8,10,16,32,64,127});
    dbhlpr.insertRow(0,100,"Bert","noweher",new byte[]{100,100,100,100,100});
    dbhlpr.insertAlternativeRow();
    Cursor csr = dbhlpr.viewRowsWithTypes();
    String logdata;
    while (csr.moveToNext()) {
        Log.d("DBINFO","Row " + csr.getPosition());
        logdata = "";
        for (int i =0; i < csr.getColumnCount(); i++) {
            String val;
            try {
                val = csr.getString(i);
            }
            catch (Exception e) {
                val = "unobtainable";
            }
            logdata = logdata + "\t\nColumn Name=" +
                    csr.getColumnName(i) +
                    "   Value=" + val;
        }
        Log.d("DBINFO",logdata);
    }
    csr.close();

所以第一行(第0行)是使用强制类型插入的,即列类型 alt1 的有效BLOB数据。

第二行(第1行)是使用典型插入类型插入的,alt1通过Spinner getSelectedItemPosition 方法获取其值(注意到Spinner没有填充,因此-1)。

第三行(第2行)是插入,再次使用类型列中的典型插入,并且 alt1 被赋予直接值(0和100)。

最后一行(第3行)只是第一行的复制。

然后调用 viewRowsWithTypes 方法返回一个Cursor,然后遍历该输出以输出正在处理的Row,然后输出每列具有列名称的行,数据输入列(注意只使用了getString)。请注意,列 TYPE _ ???? 保存的值反映了名为 ???? typeof函数(列类型) >(即 TYPE_TYPECOLUMN 显示列的类型 TYPE 等)