GVKun编程网logo

使用查询字符串在Android SQLiteDatabase中执行插入/更新/删除的正确方法是什么?

10

在本文中,我们将带你了解使用查询字符串在AndroidSQLiteDatabase中执行插入/更新/删除的正确方法是什么?在这篇文章中,同时我们还将给您一些技巧,以帮助您实现更有效的-Android数

在本文中,我们将带你了解使用查询字符串在Android SQLiteDatabase中执行插入/更新/删除的正确方法是什么?在这篇文章中,同时我们还将给您一些技巧,以帮助您实现更有效的-Android 数据库 SQLiteDatabase 的使用、android SQLiteDatabase、Android SQLiteDatabase SELECT查询需要很长时间、Android SQLiteDatabase 的使用

本文目录一览:

使用查询字符串在Android SQLiteDatabase中执行插入/更新/删除的正确方法是什么?

使用查询字符串在Android SQLiteDatabase中执行插入/更新/删除的正确方法是什么?

我一直在看官方文档(http://developer.android.com/reference/android/database/sqlite/SQLiteDatabase.html)并与StackOverflow帖子和实际观察到的行为进行交叉引用,并且该文档似乎是在某些方面具有误导性,甚至可能是错误的。

我正在尝试执行参数化查询来插入/更新/删除,就像选择rawQuery(String sql, String[]arguments).要执行的操作一样,我需要通过查询而不是通过使用SQLiteDatabase类上的insert / update /
delete方法来进行选择,因为在许多情况下,查询跨越多个表,在任何情况下,我们都在所有平台上编写了用于此应用程序的大量查询(也为SQLite编写),因此按原样使用它是更可取的。

这是我感到困惑/误导的地方:

  • 该文档说,rawQuery该语句 不能 以分号结尾,但实际上似乎没有任何区别。这对我来说很重要,因为我们有一个巨大的XML文档,其中填充了我在多个平台上的应用程序中使用的查询,并且我希望尽可能保持相同。

  • rawQuery似乎不适用于插入内容(是的,我尝试使用和不使用分号)。这位医生对此一无所知。我确实看到它返回了一个Cursor,我想这可能是一个斜线提示,它仅适用于select,但不一定如此-当没有结果集时,它可以简单地返回零长度或null的Cursor。

  • execSQL(String sql, Object[] bindArgs)明确地说,它并 没有 与插入工作,但实际上它呢!

  • 此外,尽管execSQL(String, Object[])明确告诉您不要尝试CRUD操作,但其无参数版本不包含此类警告,并且也可以正常工作(缺点是不允许使用SQL参数)。

所有这些的结果是,我能找到的成功执行带有参数化参数的插入的唯一方法是使用 docs明确指示您 不要 用于该目的的一种工作方法。

另外,rawQuery不适用于插入/更新/删除,真是令人不寒而栗,因为我们有一个通用的数据层,如果我们可以使用一个统一的API调用来在数据库。

那么这是怎么回事?该文档是否过时了?使用execSql进行插入,更新等可以吗?有没有人成功使用rawQuery进行插入?


附录:

针对OS运行:Android 4.3。

示例查询(有效,无效)

// Worksdb.execSql("INSERT into MyTable (Col1, Col2) VALUES (?, ?)", new String[] { "Foo", "Bar" });db.execSql("INSERT into MyTable (Col1, Col2) VALUES (?, ?);", new String[] { "Foo", "Bar" });// No exception thrown, but no changes made to the databasedb.rawQuery("INSERT into MyTable (Col1, Col2) VALUES (?, ?)", new String[] { "Foo", "Bar" });db.rawQuery("INSERT into MyTable (Col1, Col2) VALUES (?, ?);", new String[] { "Foo", "Bar" });

答案1

小编典典

你是对的。该文档令人困惑。总体而言,该设计尝试围绕sqlite3 C
API提供一个方便的Java包装器。在大多数情况下,如果按照设计人员的预期使用它(例如使用CRUD操作的便捷方法),它就可以正常工作。但是,他们还需要提供原始查询方法,execSQL()以及rawQuery()在便利性CRUD方法功能不足或根本不适用的情况下(CREATETABLE等等)。这导致泄漏抽象。

该文档说,rawQuery该语句不能以分号结尾,但实际上似乎没有任何区别。这对我来说很重要,因为我们有一个巨大的XML文档,其中填充了我在多个平台上的应用程序中使用的查询,并且我希望尽可能保持相同。

该文档是不好的。实际上,Android
SQLiteDatabase本身使用分号终止的查询字符串进行调用rawQuery

rawQuery似乎不适用于插入内容(是的,我尝试使用和不使用分号)。这位医生对此一无所知。我确实看到它返回了一个Cursor,我想这可能是一个斜线提示,它仅适用于select,但不一定如此-
当没有结果集时,它可以简单地返回零长度或null的Cursor。

确实可以 工作,但是您需要了解它在本机级别如何工作。

想想execSQL()作为sqlite3_exec()运行查询,并返回成功或错误代码。

可以认为rawQuery()sqlite3_prepare()可以编译查询但尚未运行它。要实际运行它,请使用上的一种moveTo...()方法Cursor。认为这是sqlite3_step()。结合任何rawQuery()moveTo...()居然会改变数据库。

execSQL(String sql, Object[] bindArgs) 明确表示它不适用于选择,但实际上可以!

此外,尽管execSQL(String,Object[])明确告诉您不要尝试CRUD操作,但其无参数版本不包含此类警告,并且也可以正常工作(缺点是不允许使用SQL参数)。

它适用于所有CRUD操作。对于CRUD的R读取部分,根本无法获取所选数据。

-Android 数据库 SQLiteDatabase 的使用

-Android 数据库 SQLiteDatabase 的使用

高春辉、王春生、朱峰:关于开源创业的 15 件小事

Android 提供了三种数据存储方式:
第一种是文件存储。
第二种是 SharedPreferences 存储。
第三种是数据库 SQLiteDatabase 存储。

文件存储我就不多说了,而 SharedPreferences 可以存取简单的数据 (int,double,float.etc),它经常用于数据缓存,因为它读取存储简单。详细可以参见本系列《Android 高手进阶教程》7.Android Preferences 的使用

今天我们将讲一下 Android SQLiteDatabase 的使用。而掌握 SqliteDatabase,将会我们接下来掌握 ContentProvider 打下良好的基石。

为了让大家更好的掌握,我们手把手完成该节的 Demo。

第一步:新建一个 Android 工程,命名为 SQLiteDatabaseDemo

SQLiteDatabaseDemo

第二步:创建一个新的类 BooksDB.java 这个类要继承于 android.database.sqlite.SQLiteOpenHelper 抽象类,我们要实现其中两个方法:onCreate (),onUpdate。具体代码如下:

package com.android.tutor;
 
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
 
public class BooksDB extends SQLiteOpenHelper {
private final static String DATABASE_NAME = "BOOKS.db";
private final static int DATABASE_VERSION = 1;
private final static String TABLE_NAME = "books_table";
public final static String BOOK_ID = "book_id";
public final static String BOOK_NAME = "book_name";
public final static String BOOK_AUTHOR = "book_author";
 
public BooksDB(Context context) {
// TODO Auto-generated constructor stub
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
 
// 创建 table
@Override
public void onCreate(SQLiteDatabase db) {
String sql = "CREATE TABLE " + TABLE_NAME + " (" + BOOK_ID
+ " INTEGER primary key autoincrement, " + BOOK_NAME
+ " text, " + BOOK_AUTHOR + " text);";
db.execSQL(sql);
}
 
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
String sql = "DROP TABLE IF EXISTS " + TABLE_NAME;
db.execSQL(sql);
onCreate(db);
}
 
public Cursor select() {
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db
.query(TABLE_NAME, null, null, null, null, null, null);
return cursor;
}
 
// 增加操作
public long insert(String bookname, String author) {
SQLiteDatabase db = this.getWritableDatabase();
/* ContentValues */
ContentValues cv = new ContentValues();
cv.put(BOOK_NAME, bookname);
cv.put(BOOK_AUTHOR, author);
long row = db.insert(TABLE_NAME, null, cv);
return row;
}
 
// 删除操作
public void delete(int id) {
SQLiteDatabase db = this.getWritableDatabase();
String where = BOOK_ID + " = ?";
String[] whereValue = { Integer.toString(id) };
db.delete(TABLE_NAME, where, whereValue);
}
 
// 修改操作
public void update(int id, String bookname, String author) {
SQLiteDatabase db = this.getWritableDatabase();
String where = BOOK_ID + " = ?";
String[] whereValue = { Integer.toString(id) };
 
ContentValues cv = new ContentValues();
cv.put(BOOK_NAME, bookname);
cv.put(BOOK_AUTHOR, author);
db.update(TABLE_NAME, cv, where, whereValue);
}
}

第三步:修改 main.xml 布局如下,由两个 EditText 和一个 ListView 组成,代码如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<EditText
android:id="@+id/bookname"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
<EditText
android:id="@+id/author"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
<ListView
android:id="@+id/bookslist"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
</LinearLayout>

第四步:修改 SQLiteDatabaseDemo.java 代码如下:

package com.android.tutor;
 
import android.app.Activity;
import android.content.Context;
import android.database.Cursor;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
 
public class SQLiteDatabaseDemo extends Activity implements
AdapterView.OnItemClickListener {
private BooksDB mBooksDB;
private Cursor mCursor;
private EditText BookName;
private EditText BookAuthor;
private ListView BooksList;
 
private int BOOK_ID = 0;
protected final static int MENU_ADD = Menu.FIRST;
protected final static int MENU_DELETE = Menu.FIRST + 1;
protected final static int MENU_UPDATE = Menu.FIRST + 2;
 
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
setUpViews();
}
 
public void setUpViews() {
mBooksDB = new BooksDB(this);
mCursor = mBooksDB.select();
 
BookName = (EditText) findViewById(R.id.bookname);
BookAuthor = (EditText) findViewById(R.id.author);
BooksList = (ListView) findViewById(R.id.bookslist);
 
BooksList.setAdapter(new BooksListAdapter(this, mCursor));
BooksList.setOnItemClickListener(this);
}
 
@Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
 
menu.add(Menu.NONE, MENU_ADD, 0, "ADD");
menu.add(Menu.NONE, MENU_DELETE, 0, "DELETE");
menu.add(Menu.NONE, MENU_DELETE, 0, "UPDATE");
return true;
}
 
public boolean onOptionsItemSelected(MenuItem item) {
super.onOptionsItemSelected(item);
switch (item.getItemId()) {
case MENU_ADD:
add();
break;
case MENU_DELETE:
delete();
break;
case MENU_UPDATE:
update();
break;
}
return true;
}
 
public void add() {
String bookname = BookName.getText().toString();
String author = BookAuthor.getText().toString();
// 书名和作者都不能为空,或者退出
if (bookname.equals("") || author.equals("")) {
return;
}
mBooksDB.insert(bookname, author);
mCursor.requery();
BooksList.invalidateViews();
BookName.setText("");
BookAuthor.setText("");
Toast.makeText(this, "Add Successed!", Toast.LENGTH_SHORT).show();
}
 
public void delete() {
if (BOOK_ID == 0) {
return;
}
mBooksDB.delete(BOOK_ID);
mCursor.requery();
BooksList.invalidateViews();
BookName.setText("");
BookAuthor.setText("");
Toast.makeText(this, "Delete Successed!", Toast.LENGTH_SHORT).show();
}
 
public void update() {
String bookname = BookName.getText().toString();
String author = BookAuthor.getText().toString();
// 书名和作者都不能为空,或者退出
if (bookname.equals("") || author.equals("")) {
return;
}
mBooksDB.update(BOOK_ID, bookname, author);
mCursor.requery();
BooksList.invalidateViews();
BookName.setText("");
BookAuthor.setText("");
Toast.makeText(this, "Update Successed!", Toast.LENGTH_SHORT).show();
}
 
@Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
 
mCursor.moveToPosition(position);
BOOK_ID = mCursor.getInt(0);
BookName.setText(mCursor.getString(1));
BookAuthor.setText(mCursor.getString(2));
 
}
 
public class BooksListAdapter extends BaseAdapter {
private Context mContext;
private Cursor mCursor;
 
public BooksListAdapter(Context context, Cursor cursor) {
 
mContext = context;
mCursor = cursor;
}
 
@Override
public int getCount() {
return mCursor.getCount();
}
 
@Override
public Object getItem(int position) {
return null;
}
 
@Override
public long getItemId(int position) {
return 0;
}
 
@Override
public View getView(int position, View convertView, ViewGroup parent) {
TextView mTextView = new TextView(mContext);
mCursor.moveToPosition(position);
mTextView.setText(mCursor.getString(1) + "___"
+ mCursor.getString(2));
return mTextView;
}
 
}
}

第五步:运行程序效果如下:

程序效果1

程序效果2

程序效果3

程序效果4

程序效果5

程序效果6

第六步:查看我们所建的数据库。有两种方法:第一种用命令查看:adb shell ls data/data/com.android.tutor/databases。

另一种方法是用 DDMS 查看,在 data/data 下面对应的应用程序的包名 下会有如下数据库,如图所示:

File Explorer


android SQLiteDatabase

android SQLiteDatabase

转载地址: http://blog.sina.com.cn/s/blog_6fff321b0100onw8.html

SQLiteDatabase

[功能]

SQLiteDatabase 是关于数据库操作的 可用于 insert delete update query 等操作可惜美中不足的是:

1. 其不支持创建数据库

2. 其不支持版本更新 或者说其不知道如何做 因为具体数据的差异

鉴于以上的缺陷 有一个辅助类可以完成上面功能 那就是:SQLiteOpenHelper

[代码]

1. 定义 SQLiteOpenHelper 并完成 创建 更新 功能

  1. publicclassDBHelper extendsSQLiteOpenHelper { 
  2. publicstaticfinalString TB_NAME = "mycountry"
  3. publicstaticfinalString ID = "_id"
  4. publicstaticfinalString COUNTRY = "country"
  5. publicstaticfinalString CODE = "code"
  6. publicDBHelper(Context context, String name, 
  7. CursorFactory factory,intversion) { 
  8. super(context, name, factory, version); 
  9. publicvoidonCreate(SQLiteDatabase db) { 
  10. db.execSQL("CREATE TABLE IF NOT EXISTS "
  11. + TB_NAME + " ("
  12. + ID + " INTEGER PRIMARY KEY,"
  13. + COUNTRY + " VARCHAR,"
  14. + CODE + " INTEGER)"); 
  15. publicvoidonUpgrade(SQLiteDatabase db, 
  16. intoldVersion, intnewVersion) { 
  17. //TODO 删除数据库之前 做数据备份
  18. db.execSQL("DROP TABLE IF EXISTS "+TB_NAME); 
  19. onCreate(db); 

2. 从 SQLiteOpenHelper 得到 SQLiteDatabase 的实例

  1. DBHelper helper = newDBHelper(this, DB_NAME, null, VERSION); 
  2. SQLiteDatabase db = helper.getWritableDatabase(); 

3. SQLiteDatabase 的一些操作:

* 插入数据:

  1. ContentValues values = newContentValues(); 
  2. values.put(DBHelper.COUNTRY, "中国"); 
  3. values.put(DBHelper.CODE, 86); 
  4. db.insert(DBHelper.TB_NAME,DBHelper.ID, values); 

* 改动数据

  1. db.insert(DBHelper.TB_NAME,DBHelper.ID,null); 
  2. values.clear(); 
  3. values.put(DBHelper.COUNTRY, "意大利"); 
  4. values.put(DBHelper.CODE, 39); 
  5. db.update(DBHelper.TB_NAME, values,DBHelper.ID + " = 2",null); 

* execSQL 执行 SQL 语言

  1. db.execSQL("INSERT INTO "
  2. + DBHelper.TB_NAME + "("
  3. + DBHelper.COUNTRY + ","
  4. + DBHelper.CODE + ") VALUES "
  5. "('' 洪都拉斯 '',504)"); 

* 查询数据

  1. Cursor c = db.query(DBHelper.TB_NAME,null,null,null,null,null
  2. DBHelper.CODE+" DESC"); 

* 删除数据所有数据

  1. db.delete(DBHelper.TB_NAME,null,null); 

数据库的生成 调用 getWiterAbleDatabase getReadAbleDatabase 生成数据库 i

android 嵌入式数据库 为单用户数据库 所以 可以不调用 db.close () 来关闭数据库这样反而可以提高性能

Android SQLiteDatabase SELECT查询需要很长时间

Android SQLiteDatabase SELECT查询需要很长时间

我在TABLE_CONTACT中有大约1500条记录.我获取联系人的代码:

public ArrayList<SBContact> getAllContacts() {
    sqliteDatabase database = dbHelper.getWritableDatabase();
    ArrayList<SBContact> mContacts = new ArrayList<SBContact>();
    String selectQuery = "SELECT  * FROM " + SBDatabaseHelper.TABLE_CONTACT;
    Cursor cursor = database.rawQuery(selectQuery, null);

    if (cursor.movetoFirst()) {
        do {
            SBContact result = new SBContact(cursor.getString(cursor.getColumnIndex(SBDatabaseHelper.CONTACT_NUMBER)),
                    cursor.getString(cursor.getColumnIndex(SBDatabaseHelper.CONTACT_NAME)), cursor.getInt(cursor.getColumnIndex(SBDatabaseHelper.EXITS_USER)));
            mContacts.add(result);
        } while (cursor.movetoNext());
    }
    return mContacts;
}

问题是:第一次运行此方法大约需要15毫秒. 5秒后,我再次运行此方法,大约需要20秒.

以类似的方式,在第一次调用之后(15秒后),再次运行方法,大约需要10秒钟. 2分钟后,再次运行此方法,第一次运行大约需要15毫秒.

此时,没有其他线程对数据库进行读/写查询.

我不明白sqliteDatabase的作用.是否需要时间释放内存或执行某些操作?

已编辑
抱歉,这不是sqliteDatabase的问题.有关此案例的更多详细信息,请参见我的回答.

解决方法:

每次查询后关闭光标

Android SQLiteDatabase 的使用

Android SQLiteDatabase 的使用

Java 代码 
  1. package com.shawn.test;  
  2. import android.content.ContentValues;  
  3. import android.content.Context;  
  4. import android.database.Cursor;  
  5. import android.database.sqlite.SQLiteDatabase;  
  6. import android.database.sqlite.SQLiteOpenHelper;  
  7. import android.util.Log;  
  8. publicclass DatabaseAdapter{  
  9. privatestaticfinal String DB_NAME = "Test.db";    // 数据库名
  10. privatestaticfinalint    DB_VERSION = 1;         // 数据库版本
  11. privatestaticfinal String DB_TABLE = "my_order";  // 表名
  12. privatestaticfinal String KEY_ID = "_id";         //id
  13. privatestaticfinal String KEY_ORDER_ID = "order_id";  // 订单号
  14. privatestaticfinal String KEY_TYPE = "_type";         // 订单类型
  15. privatestaticfinal String KEY_STATE = "_state";       // 订单状态
  16. private Context context;  
  17. private DatabaseHelper mDatabaseHelper;  
  18. private SQLiteDatabase mSQLiteDatabase;  
  19. privatestaticclass DatabaseHelper extends SQLiteOpenHelper{  
  20. // 创建数据库语句
  21. privatestaticfinal String DB_CREAT = "CREATE TABLE "
  22.                 + DB_TABLE  
  23.                 + " (" + KEY_ID + " INTEGER PRIMARY KEY,"
  24.                 + KEY_ORDER_ID + " TEXT,"
  25.                 + KEY_TYPE + " INTEGER,"
  26.                 + KEY_STATE + " INTEGER)";  
  27. public DatabaseHelper(Context context) {  
  28. super(context, DB_NAME,  null , DB_VERSION);  
  29.         }  
  30. @Override
  31. publicvoid onCreate(SQLiteDatabase db) {  
  32. // TODO Auto-generated method stub
  33.             db.execSQL(DB_CREAT);  
  34.         }  
  35. @Override
  36. publicvoid onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {  
  37. // TODO Auto-generated method stub
  38.             db.execSQL("DROP TABLE IF EXISTS "+DB_TABLE);  
  39.             onCreate(db);  
  40.         }  
  41.     }  
  42. public DatabaseAdapter(Context context) {  
  43. this.context = context;  
  44.     }  
  45. // 开启
  46. publicvoid open() {  
  47.         mDatabaseHelper = new DatabaseHelper(context);    
  48.         mSQLiteDatabase = mDatabaseHelper.getWritableDatabase();  
  49.     }  
  50. // 关闭
  51. publicvoid close() {   
  52.         mSQLiteDatabase.close();  
  53.         mDatabaseHelper.close();  
  54.     }  
  55. // 增
  56. publiclong insertData(String orderId, int type) {    
  57.         ContentValues values = new  ContentValues();     
  58.         values.put(KEY_ORDER_ID, orderId);   
  59.         values.put(KEY_TYPE, type);  
  60.         values.put(KEY_STATE, Config.STATE_APPLY);   
  61. long id = mSQLiteDatabase.insert(DB_TABLE, KEY_ID, values);   
  62. return id;  
  63.     }  
  64. // 删
  65. publicboolean deleteData(Context context, long id) {  
  66. boolean delete = mSQLiteDatabase.delete(DB_TABLE, KEY_ID + "=" +id, null)>0;  
  67. return delete;  
  68.     }  
  69. // 改
  70. publicboolean updateData(long id, int state) {  
  71.         ContentValues values = new  ContentValues();    
  72.         values.put(KEY_STATE, ""+state);   
  73. boolean update = mSQLiteDatabase.update(DB_TABLE, values, KEY_ID + "=" +id, null)>0;  
  74. return update;  
  75.     }  
  76. // 查
  77. public Cursor fetchData(String selection) {  
  78.         Cursor mCursor = mSQLiteDatabase.query(DB_TABLE, new String[]{KEY_ID, KEY_ORDER_ID, KEY_TYPE, KEY_STATE}, selection, nullnullnullnull);  
  79. if(mCursor != null)  
  80.             mCursor.moveToFirst();  
  81. return mCursor;  
  82.     }  
  83. }  

今天关于使用查询字符串在Android SQLiteDatabase中执行插入/更新/删除的正确方法是什么?的介绍到此结束,谢谢您的阅读,有关-Android 数据库 SQLiteDatabase 的使用、android SQLiteDatabase、Android SQLiteDatabase SELECT查询需要很长时间、Android SQLiteDatabase 的使用等更多相关知识的信息可以在本站进行查询。

本文标签: