Android存储方式之SQLite

news/2024/9/17 5:01:19

前言

  • SQLite数据库操作在Android开发中非常常用
  • 今天我将带大家全面了解关于SQLite数据库的操作(增、删、查、改)

目录

1. SQLite数据库介绍

  • SQLite是Android内置的一个小型、关系型、属于文本型的数据库。

    > Android提供了对 SQLite数据库的完全支持,应用程序中的任何类都可以通过名称来访问任何的数据库,但是应用程序之外的就不能访问。
    
  • Android中,通过SQLiteOpenHelper类来实现对SQLite数据库的操作。

2. SQLiteOpenHelper类介绍

  • 定义:SQLiteOpenHelper是一个辅助类
  • 作用:管理数据库(创建、增、修、删) & 版本的控制。
  • 使用过程:通过创建子类继承SQLiteOpenHelper类,实现它的一些方法来对数据库进行操作。

    > 在实际开发中,为了能够更好的管理和维护数据库,我们会封装一个继承自SQLiteOpenHelper类的数据库操作类,然后以这个类为基础,再封装我们的业务逻辑方法。
    
  • SQLiteOpenHelper类的数据库操作方法介绍
方法名作用备注
onCreate()创建数据库创建数据库时自动调用
onUpgrade()升级数据库
close()关闭所有打开的数据库对象
execSQL()可进行增删改操作, 不能进行查询操作
query()、rawQuery()查询数据库
insert()插入数据
delete()删除数据
getWritableDatabase()创建或打开可以读/写的数据库通过返回的SQLiteDatabase对象对数据库进行操作
getReadableDatabase()创建或打开可读的数据库同上
    • *

3. 常见数据库使用

数据库操作无外乎:“增删查改”:

  1. 对于“增、删、改(更新)”这类对表内容变换的操作,需先调用getWritableDatabase()获得一个可写数据库对象,在执行的时候调用通用的execSQL(String sql)或或对应的操作API方法:insert()、delete()、update()
  2. 对“查”,需要调用getReadableDatabase()获得一个可读的数据库对象,然后使用query()或rawQuery()方法

    > 查询数据库**不能使用execSQL方法**
    

下面我将一一介绍。

3.1 创建数据库

  • 涉及的方法有onCreate()、getWritableDatabase()、getReadableDatabase()
  • 具体代码如下:

    > 假设DatabaseHelper类是SQLiteOpenHelper的子类
    

DatabaseHelper.java

//第一次创建数据库的时候回调该方法
//当使用getReadableDatabase()方法获取数据库实例的时候, 如果数据库不存在, 就会调用这个方法;//作用:创建数据库表:将创建数据库表的 execSQL()方法 和 初始化表数据的一些 insert()方法写在里面;@Override  public void onCreate(SQLiteDatabase db) {  //SQLite数据创建支持的数据类型: 整型数据,字符串类型,日期类型,二进制的数据类型  //创建了一个名为person的表String sql = "create table person(id integer primary key autoincrement,name varchar(64),address varchar(64))";  //execSQL用于执行SQL语句//完成数据库的创建   db.execSQL(sql); //数据库实际上是没有被创建或者打开的,直到getWritableDatabase() 或者 getReadableDatabase() 方法中的一个被调用时才会进行创建或者打开 //见下代码

MainActivity.java

// 创建DatabaseHelper对象
// 只执行这句话是不会创建或打开连接的SQLiteOpenHelper dbHelper = new DatabaseHelper(SQLiteActivity.this,"test_carson");// 调用getReadableDatabase()或getWritableDatabase()才算真正创建或打开数据库SQLiteDatabase sqliteDatabase = dbHelper.getReadableDatabase();//SQLiteDatabase sqliteDatabase = dbHelper.getWritableDatabase() ;

3.2 插入数据

  • 步骤:创建并打开数据库(可读/写)、插入数据
  • 涉及方法:getWritableDatabase()、insert()

    > insert()也可以使用excelSQL()代替
    
  • 具体代码如下:
//1\. 创建并打开数据库// 创建DatabaseHelper对象(记得传入最新版本的数据库)
// 只执行这句话是不会创建或打开连接的
//注意,一定要传入最新的数据库版本号SQLiteOpenHelper dbHelper = new DatabaseHelper(SQLiteActivity.this,"test_carson",2);// 调用getWritableDatabase()方法创建或打开一个可以读的数据库//通过返回的SQLiteDatabase对象对数据库进行操作SQLiteDatabase sqliteDatabase = dbHelper.getWritableDatabase();//2\. 创建并打开数据库// 创建ContentValues对象ContentValues values = new ContentValues();// 向该对象中插入键值对values.put("id", 1);values.put("name", "yangyz");//其中,key代表列名,value代表该列要插入的值//注:ContentValues内部实现就是HashMap,但是两者还是有差别的//ContenValues Key只能是String类型,Value只能存储基本类型数据,不能存储对象// 调用insert()方法将数据插入到数据库当中sqliteDatabase.insert("user", null, values);// 第一个参数:要操作的表名称// 第二个参数:SQl不允许一个空列,如果ContentValues是空的,那么这一列被明确的指明为NULL值// 第三个参数:ContentValues对象db.execSQL("insert into user (id,name) values (1,'张三')")  也可以}

3.3 修改数据(升级数据库)

  • 涉及的方法有onUpgrade()、getWritableDatabase()、update()
  • 具体代码如下:

DatabaseHelper.java

//数据库版本号private static final int DATABASE_VERSION = 1; //作用:更新数据库表结构
//调用时机:数据库版本发生变化的时候回调(取决于数据库版本)
// 创建SQLiteOpenHelper子类对象的时候,必须传入一个version参数
//该参数就是当前数据库版本, 只要这个版本高于之前的版本, 就会触发这个onUpgrade()方法,如下面代码
@Override  public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {  //使用SQL的ALTER语句String sql = "alter table person add sex varchar(8)";  db.execSQL(sql);  }  
//参数说明: 
// db : 数据库 
//oldVersion : 旧版本数据库 
//newVersion : 新版本数据库 
//注意:这里的删除等操作必须要保证新的版本必须要比旧版本的版本号要大才行。[即 Version 2.0 > Version 1.0 ] 所以这边我们不需要对其进行操作。

MainActivity.java

            // 创建一个DatabaseHelper对象// 创建SQLiteOpenHelper子类对象的时候,必须传入一个version参数
//该参数就是当前数据库版本, 只要这个版本高于之前的版本, 就会触发这个onUpgrade()方法,如下面代码
注意,一定要传入最新的数据库版本号// 传入版本号为2,大于旧版本(1),所以会调用onUpgrade()升级数据库DatabaseHelper dbHelper = new DatabaseHelper(SQLiteActivity.this,"test_carson", 2);// 调用getWritableDatabase()得到一个可写的SQLiteDatabase对象SQLiteDatabase sqliteDatabase = dbHelper.getWritableDatabase();// 创建一个ContentValues对象ContentValues values = new ContentValues();values.put("name", "zhangsan");// 调用update方法修改数据库sqliteDatabase.update("user", values, "id=?", new String[] { "1" });// 第一个参数String:表名// 第二个参数ContentValues:ContentValues对象(需要修改的)// 第三个参数String:WHERE表达式,where选择语句, 选择那些行进行数据的更新, 如果该参数为 null, 就会修改所有行;?号是占位符// 第四个参数String[]:where选择语句的参数, 逐个替换 whereClause 中的占位符;

3.4 删除数据

  • 步骤:创建并打开数据库(可读/写)、删除数据
  • 涉及方法:getWritableDatabase()、delete()

    > delete()也可以使用excelSQL()代替
    
  • 具体代码如下:
//1\. 创建并打开数据库// 创建DatabaseHelper对象
// 只执行这句话是不会创建或打开连接的
注意,一定要传入最新的数据库版本号SQLiteOpenHelper dbHelper = new DatabaseHelper(SQLiteActivity.this,"test_carson",2);// 调用getWritableDatabase()方法创建或打开一个可以读的数据库//通过返回的SQLiteDatabase对象对数据库进行操作SQLiteDatabase sqliteDatabase = dbHelper.getWritableDatabase();//2\. 删除数据//调用delete方法进行删除操作sqliteDatabase.delete("user", "id=?", new String[]{"1"});//第一个参数String:需要操作的表名//第二个参数String:where选择语句, 选择哪些行要被删除, 如果为null, 就删除所有行;//第三个参数String[]: where语句的参数, 逐个替换where语句中的 "?" 占位符;

3.5 查询数据

  • 步骤:创建并打开数据库(可读)、查询数据
  • 涉及方法:getReadableDatabase()、query() 或 rawQuery(),介绍如下:
//第一种最为简单
//将所有的SQL语句都组织到一个字符串中,使用占位符代替实际参数(selectionArgs)
db.rawQuery(String sql, String[] selectionArgs);  db.query(String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy);  
db.query(String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit);  
db.query(String distinct, String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit);  //参数说明
//table:要操作的表明
//columns:查询的列所有名称集
//selection:WHERE之后的条件语句,可以使用占位符
//groupBy:指定分组的列名
//having指定分组条件,配合groupBy使用
//orderBy指定排序的列名
//limit指定分页参数
//distinct可以指定“true”或“false”表示要不要过滤重复值//所有方法将返回一个Cursor对象,代表数据集的游标//Cursor对象常用方法如下:
c.move(int offset); //以当前位置为参考,移动到指定行  
c.moveToFirst();    //移动到第一行  
c.moveToLast();     //移动到最后一行  
c.moveToPosition(int position); //移动到指定行  
c.moveToPrevious(); //移动到前一行  
c.moveToNext();     //移动到下一行  
c.isFirst();        //是否指向第一条  
c.isLast();     //是否指向最后一条  
c.isBeforeFirst();  //是否指向第一条之前  
c.isAfterLast();    //是否指向最后一条之后  
c.isNull(int columnIndex);  //指定列是否为空(列基数为0)  
c.isClosed();       //游标是否已关闭  
c.getCount();       //总数据项数  
c.getPosition();    //返回当前游标所指向的行数  
c.getColumnIndex(String columnName);//返回某列名对应的列索引值  
c.getString(int columnIndex);   //返回当前行指定列的值
  • 具体代码如下:
//1\. 创建并打开数据库// 创建DatabaseHelper对象
// 只执行这句话是不会创建或打开连接的
注意,一定要传入最新的数据库版本号SQLiteOpenHelper dbHelper = new DatabaseHelper(SQLiteActivity.this,"test_carson",2);// 调用getReadableDatabase()方法创建或打开一个可以读的数据库//通过返回的SQLiteDatabase对象对数据库进行操作SQLiteDatabase sqliteDatabase = dbHelper.getReadableDatabase();//2\. 查询数据// 调用SQLiteDatabase对象的query方法进行查询
// 返回一个Cursor对象:由数据库查询返回的结果集对象Cursor cursor = sqliteDatabase.query("user", new String[] { "id","name" }, "id=?", new String[] { "1" }, null, null, null);// 第一个参数String:表名// 第二个参数String[]:要查询的列名// 第三个参数String:查询条件// 第四个参数String[]:查询条件的参数// 第五个参数String:对查询的结果进行分组// 第六个参数String:对分组的结果进行限制// 第七个参数String:对查询的结果进行排序// 将光标移动到下一行,从而判断该结果集是否还有下一条数据
//如果有则返回true,没有则返回falsewhile (cursor.moveToNext()) {id = cursor.getString(cursor.getColumnIndex("id"));name = cursor.getString(cursor.getColumnIndex("name"));}//也可将Cursor中的数据转为 ArrayList<Map<String, String>> 类型数据
private ArrayList<Map<String, String>> cursor2list(Cursor cursor) {  ArrayList<Map<String, String>> list = new ArrayList<Map<String,String>>();  //遍历Cursor  while(cursor.moveToNext()){  Map<String, String> map = new HashMap<String, String>();  map.put("tittle", cursor.getString(1));  map.put("content", cursor.getString(2));  list.add(map);  }  return list;  
}

3.6 关闭数据库

当我们完成了对数据库的操作后,记得调用SQLiteDatabase的close()方法释放数据库连接,否则容易出现SQLiteException。

  SQLiteOpenHelper dbHelper = new DatabaseHelper(SQLiteActivity.this,"test_carson");// 调用getReadableDatabase()方法创建或打开一个可以读的数据库//通过返回的SQLiteDatabase对象对数据库进行操作SQLiteDatabase sqliteDatabase = dbHelper.getReadableDatabase();//关闭当前数据库  sqliteDatabase.close();

3.7 删除数据库

  SQLiteOpenHelper dbHelper = new DatabaseHelper(SQLiteActivity.this,"test_carson");// 调用getReadableDatabase()方法创建或打开一个可以读的数据库//通过返回的SQLiteDatabase对象对数据库进行操作SQLiteDatabase sqliteDatabase = dbHelper.getReadableDatabase();//删除名为test.db数据库  deleteDatabase("test.db");

特别注意

其实对于上述所有的数据库操作(除了“查询”),我们都可以使用下列方法代替:

db.executeSQL(String sql);  
db.executeSQL(String sql, Object[] bindArgs);
//sql语句中使用占位符,然后第二个参数是实际的参数集

个人建议都使用SQL语句,因为:

  • SQL语句较为通用;
  • 使用insert()、delete()、query()方法具备多个参数,使用复杂

4. 实例Demo

  • Demo描述:创建数据库并对数据库进行操作(增、删、查、改)
  • 实现步骤:

    1. 实现子类继承SQLiteOpenHelper类(复写onCreat()、onUpgrade())
    2. 在MainActivity里实现需要进行的数据库操作(增、删、查、改)

4.1 具体代码如下:

建议先下载Demo再进行阅读:Carson的Github:DataBase_Demo

步骤1:实现子类继承SQLiteOpenHelper类(复写onCreat()、onUpgrade())

MySQLiteOpenHelper.java

package scut.carson_ho.database_demo;import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;public class MySQLiteOpenHelper extends SQLiteOpenHelper {//数据库版本号private static Integer Version = 1;//在SQLiteOpenHelper的子类当中,必须有该构造函数public MySQLiteOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory,int version) {//必须通过super调用父类当中的构造函数super(context, name, factory, version);}//参数说明//context:上下文对象//name:数据库名称//param:factory//version:当前数据库的版本,值必须是整数并且是递增的状态public MySQLiteOpenHelper(Context context,String name,int version){this(context,name,null,version);}public MySQLiteOpenHelper(Context context,String name){this(context, name, Version);}//当数据库创建的时候被调用@Overridepublic void onCreate(SQLiteDatabase db) {System.out.println("创建数据库和表");//创建了数据库并创建一个叫records的表//SQLite数据创建支持的数据类型: 整型数据,字符串类型,日期类型,二进制的数据类型String sql = "create table user(id int primary key,name varchar(200))";//execSQL用于执行SQL语句//完成数据库的创建db.execSQL(sql);//数据库实际上是没有被创建或者打开的,直到getWritableDatabase() 或者 getReadableDatabase() 方法中的一个被调用时才会进行创建或者打开}//数据库升级时调用//如果DATABASE_VERSION值被改为2,系统发现现有数据库版本不同,即会调用onUpgrade()方法@Overridepublic void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {System.out.println("更新数据库版本为:"+newVersion);}}

步骤2:在MainActivity里实现需要进行的数据库操作(增、删、查、改)

MainActivity.java

package scut.carson_ho.database_demo;import android.content.ContentValues;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;public class MainActivity extends AppCompatActivity implements View.OnClickListener {private Button instablish;private Button insert;private Button upgrade;private Button modify;private Button delete;private Button query;private Button delete_database;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);//绑定按钮instablish = (Button) findViewById(R.id.instablish);insert = (Button) findViewById(R.id.insert);upgrade = (Button) findViewById(R.id.upgrade);modify = (Button) findViewById(R.id.modify);delete = (Button) findViewById(R.id.delete);query = (Button) findViewById(R.id.query);delete_database = (Button) findViewById(R.id.delete_database);//设置监听器instablish.setOnClickListener(this);insert.setOnClickListener(this);upgrade.setOnClickListener(this);modify.setOnClickListener(this);delete.setOnClickListener(this);query.setOnClickListener(this);delete_database.setOnClickListener(this);}//设置每个按钮对数据库的操作进行控制@Overridepublic void onClick(View v) {switch (v.getId()) {//点击创建数据库库case R.id.instablish:// 创建SQLiteOpenHelper子类对象MySQLiteOpenHelper dbHelper = new MySQLiteOpenHelper(this,"test_carson");//数据库实际上是没有被创建或者打开的,直到getWritableDatabase() 或者 getReadableDatabase() 方法中的一个被调用时才会进行创建或者打开SQLiteDatabase  sqliteDatabase = dbHelper.getWritableDatabase();// SQLiteDatabase  sqliteDatabase = dbHelper.getReadbleDatabase();break;//点击更新数据case R.id.upgrade:// 创建SQLiteOpenHelper子类对象MySQLiteOpenHelper dbHelper_upgrade = new MySQLiteOpenHelper(this,"test_carson",2);// 调用getWritableDatabase()方法创建或打开一个可以读的数据库SQLiteDatabase  sqliteDatabase_upgrade = dbHelper_upgrade.getWritableDatabase();// SQLiteDatabase  sqliteDatabase = dbHelper.getReadbleDatabase();break;//点击插入数据到数据库case R.id.insert:System.out.println("插入数据");// 创建SQLiteOpenHelper子类对象注意,一定要传入最新的数据库版本号MySQLiteOpenHelper dbHelper1 = new MySQLiteOpenHelper(this,"test_carson",2);// 调用getWritableDatabase()方法创建或打开一个可以读的数据库SQLiteDatabase  sqliteDatabase1 = dbHelper1.getWritableDatabase();// 创建ContentValues对象ContentValues values1 = new ContentValues();// 向该对象中插入键值对values1.put("id", 1);values1.put("name", "carson");// 调用insert()方法将数据插入到数据库当中sqliteDatabase1.insert("user", null, values1);// sqliteDatabase.execSQL("insert into user (id,name) values (1,'carson')");//关闭数据库sqliteDatabase1.close();break;//点击查询数据库case R.id.query:System.out.println("查询数据");// 创建DatabaseHelper对象MySQLiteOpenHelper dbHelper4 = new MySQLiteOpenHelper(MainActivity.this,"test_carson",2);// 调用getWritableDatabase()方法创建或打开一个可以读的数据库SQLiteDatabase sqliteDatabase4 = dbHelper4.getReadableDatabase();// 调用SQLiteDatabase对象的query方法进行查询// 返回一个Cursor对象:由数据库查询返回的结果集对象Cursor cursor = sqliteDatabase4.query("user", new String[] { "id","name" }, "id=?", new String[] { "1" }, null, null, null);String id = null;String name = null;//将光标移动到下一行,从而判断该结果集是否还有下一条数据//如果有则返回true,没有则返回falsewhile (cursor.moveToNext()) {id = cursor.getString(cursor.getColumnIndex("id"));name = cursor.getString(cursor.getColumnIndex("name"));//输出查询结果System.out.println("查询到的数据是:"+"id: "+id+"  "+"name: "+name);}//关闭数据库sqliteDatabase4.close();break;//点击修改数据case R.id.modify:System.out.println("修改数据");// 创建一个DatabaseHelper对象// 将数据库的版本升级为2// 传入版本号为2,大于旧版本(1),所以会调用onUpgrade()升级数据库MySQLiteOpenHelper dbHelper2 = new MySQLiteOpenHelper(MainActivity.this,"test_carson", 2);// 调用getWritableDatabase()得到一个可写的SQLiteDatabase对象SQLiteDatabase sqliteDatabase2 = dbHelper2.getWritableDatabase();// 创建一个ContentValues对象ContentValues values2 = new ContentValues();values2.put("name", "zhangsan");// 调用update方法修改数据库sqliteDatabase2.update("user", values2, "id=?", new String[]{"1"});//关闭数据库sqliteDatabase2.close();break;//点击删除数据case R.id.delete:System.out.println("删除数据");// 创建DatabaseHelper对象MySQLiteOpenHelper dbHelper3 = new MySQLiteOpenHelper(MainActivity.this,"test_carson",2);// 调用getWritableDatabase()方法创建或打开一个可以读的数据库SQLiteDatabase sqliteDatabase3 = dbHelper3.getWritableDatabase();//删除数据sqliteDatabase3.delete("user", "id=?", new String[]{"1"});//关闭数据库sqliteDatabase3.close();break;//点击删除数据库case R.id.delete_database:System.out.println("删除数据库");MySQLiteOpenHelper dbHelper5 = new MySQLiteOpenHelper(MainActivity.this,"test_carson",2);// 调用getReadableDatabase()方法创建或打开一个可以读的数据库SQLiteDatabase sqliteDatabase5 = dbHelper5.getReadableDatabase();//删除名为test.db数据库deleteDatabase("test_carson");break;default:break;}}
}

步骤3:在主布局文件设置按钮控制数据库的操作
activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:paddingBottom="@dimen/activity_vertical_margin"android:paddingLeft="@dimen/activity_horizontal_margin"android:paddingRight="@dimen/activity_horizontal_margin"android:paddingTop="@dimen/activity_vertical_margin"tools:context="scut.carson_ho.database_demo.MainActivity"><Buttonandroid:id="@+id/instablish"android:layout_centerHorizontal="true"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="创建数据库"/><Buttonandroid:id="@+id/upgrade"android:layout_below="@+id/instablish"android:layout_centerHorizontal="true"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="更新数据库"/><Buttonandroid:id="@+id/insert"android:layout_below="@+id/upgrade"android:layout_centerHorizontal="true"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="插入数据"/><Buttonandroid:id="@+id/modify"android:layout_centerHorizontal="true"android:layout_below="@+id/insert"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="修改数据"/><Buttonandroid:id="@+id/query"android:layout_centerHorizontal="true"android:layout_below="@+id/modify"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="查询数据"/><Buttonandroid:id="@+id/delete"android:layout_centerHorizontal="true"android:layout_below="@+id/query"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="删除数据"/><Buttonandroid:id="@+id/delete_database"android:layout_centerHorizontal="true"android:layout_below="@+id/delete"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="删除数据库"/></RelativeLayout>

4.2 测试结果

  • 界面显示
  • 按顺序点击:创建 - 更新 - 插入 - 查询 - 修改 - 查询 - 删除数据

4.3 Demo下载地址

DataBase_Demo

5. 总结

  • 通过阅读本文,你将全面了解Android SQLite数据库中的所有操作

http://lihuaxi.xjx100.cn/news/240789.html

相关文章

JavaScript对象数组示例

可以用于暂时无法从数据库中拿到数据时&#xff0c;模拟数据使用 var datas [{name:囧菌,subject:JavaScript,grade:100 },{name : 双笙,subject : React,grade : 100 },{name:陈拾月,subject:Vue,grade:100 }]; 其实相当于 var datasInt [1,2,3]; 注意&#xff1a;是引号…

自然语言处理:汉语分词

NLPIR/ICTCLAS 汉语分词系统&#xff08;http://ictclas.nlpir.org&#xff09;PyNLPIR 是该汉语分词系统的 python 封装版&#xff08;http://pynlpir.readthedocs.io...&#xff09; 安装步骤&#xff1a;① pip install pynlpir② pynlpir update 官方文档的汉语分词示例&am…

显示来自多个表的数据——JOIN

表关系简介 一、语法 SELECT 字段列表FROM TABLE1 [CROSS JOIN TABLE2 ] | [NATURAL JOIN TABLE2 ] | [JOIN TABLE2 USING (字段名) ] | [JOIN TABLE2 ON (TABLE.COLUMN_NAME TABLE2.COLUMN_NAME) ] | [(LEFT | RIGHT | FULL OUT) JOIN TABLE2 ON (TABLE1.COLUMN_NAME TABL…

JavaScript封装一个注册函数解决兼容问题

我们知道JavaScript注册(绑定)事件主要有两类方式&#xff0c;第一类传统方式具有注册事件的唯一性&#xff0c;即对于同一元素的同一事件&#xff0c;不会出现两个处理函数&#xff0c;如下 var btn document.querySelector(button);btn.onclick function(){document.body.s…

排序(一)归并、快排、优先队列等(图文具体解释)

排序(一) 0基础排序算法 选择排序 思想&#xff1a;首先&#xff0c;找到数组中最小的那个元素。其次&#xff0c;将它和数组的第一个元素交换位置。再次。在剩下的元素中找到最小的元素。将它与数组的第二个元素交换位置。如此往复&#xff0c;直到将整个数组排序。 【图例】 …

练习 MongoDB 操作 —— 备份篇(三)

2019独角兽企业重金招聘Python工程师标准>>> mongodb数据备份和还原主要分为二种&#xff0c; 一种是针对于库的mongodump和mongorestore&#xff0c; 一种是针对库中表的mongoexport和mongoimport。 mongodb 数据库操作--备份 还原 导出 导入 导入与导入 导入与导出…

RabbitMQ死信队列、延时队列

介绍&#xff1a; 消息被消费⽅否定确认&#xff0c;使⽤ channel.basicNack 或 channel.basicReject &#xff0c;并且此时 requeue 属性被设置为 false 。消息在队列的存活时间超过设置的TTL时间。消息队列的消息数量已经超过最⼤队列⻓度。那么该消息将成为“死信”。“死信…

JavaScript实现智能搜索框

应用场景&#xff1a; 1. 搜索框在页面中占据的空间过小&#xff0c;希望无论浏览到什么位置&#xff0c;可以轻易地回到并聚焦搜索框。 2. 搜索框里面的文字大小过小&#xff0c;希望能够在上方开辟一块空间放大内容 解决思路&#xff1a; 1. 对整个页面添加键盘事件keyup…