在这个字符串中,我将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);"
答案 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 等)