android sqlite 如何设置外键

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了android sqlite 如何设置外键相关的知识,希望对你有一定的参考价值。

介绍:

安卓默认的数据是SQLite,但SQLite3.6.19之前是不支持外键的,如果有两张表需要关联,用外键是最省事的,但不支持的话怎么办呢?这里就有一个解决办法,就是用事务将两张表关联起来,并且最后生成一张视图。


现有两张表

Employees

Dept

视图

ViewEmps:显示雇员信息和他所在的部门

创建数据库

自定义一个辅助类继承SQLiteOpenHelper类

1.onCreate(SQLiteDatabase db): 当数据库被创建的时候,能够生成表,并创建视图跟触发器。

2.onUpgrade(SQLiteDatabse db, int oldVersion, int newVersion): 更新的时候可以删除表和创建新的表。
代码如下:view plain

public class DatabaseHelper extends SQLiteOpenHelper   
  
static final String dbName="demoDB";  
static final String employeeTable="Employees";  
static final String colID="EmployeeID";  
static final String colName="EmployeeName";  
static final String colAge="Age";  
static final String colDept="Dept";  
  
static final String deptTable="Dept";  
static final String colDeptID="DeptID";  
static final String colDeptName="DeptName";  
  
static final String viewEmps="ViewEmps";

构造器

public DatabaseHelper(Context context)   
  super(context, dbName, null,33);   
  

创建库中的表,视图和触发器

public void onCreate(SQLiteDatabase db)   
  // TODO Auto-generated method stub  
    
  db.execSQL("CREATE TABLE "+deptTable+" ("+colDeptID+ " INTEGER PRIMARY KEY , "+  
    colDeptName+ " TEXT)");  
    
  db.execSQL("CREATE TABLE "+employeeTable+"   
    ("+colID+" INTEGER PRIMARY KEY AUTOINCREMENT, "+  
        colName+" TEXT, "+colAge+" Integer, "+colDept+"   
    INTEGER NOT NULL ,FOREIGN KEY ("+colDept+") REFERENCES   
    "+deptTable+" ("+colDeptID+"));");  
    
  //创建触发器  
  db.execSQL("CREATE TRIGGER fk_empdept_deptid " +  
    " BEFORE INSERT "+  
    " ON "+employeeTable+  
      
    " FOR EACH ROW BEGIN"+  
    " SELECT CASE WHEN ((SELECT "+colDeptID+" FROM "+deptTable+"   
    WHERE "+colDeptID+"=new."+colDept+" ) IS NULL)"+  
    " THEN RAISE (ABORT,\'Foreign Key Violation\') END;"+  
    "  END;");  
  
//创建视图  
  db.execSQL("CREATE VIEW "+viewEmps+  
    " AS SELECT "+employeeTable+"."+colID+" AS _id,"+  
    " "+employeeTable+"."+colName+","+  
    " "+employeeTable+"."+colAge+","+  
    " "+deptTable+"."+colDeptName+""+  
    " FROM "+employeeTable+" JOIN "+deptTable+  
    " ON "+employeeTable+"."+colDept+" ="+deptTable+"."+colDeptID  
    );  

更新库中的表

public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)   
  // TODO Auto-generated method stub  
    
  db.execSQL("DROP TABLE IF EXISTS "+employeeTable);  
  db.execSQL("DROP TABLE IF EXISTS "+deptTable);  
  
  db.execSQL("DROP TRIGGER IF EXISTS fk_empdept_deptid");  
  db.execSQL("DROP VIEW IF EXISTS "+viewEmps);  
  onCreate(db);  

加入数据

SQLiteDatabase db=this.getWritableDatabase();  
ContentValues cv=new ContentValues();  
   cv.put(colDeptID, 1);  
   cv.put(colDeptName, "Sales");  
   db.insert(deptTable, colDeptID, cv);  
  
   cv.put(colDeptID, 2);  
   cv.put(colDeptName, "IT");  
   db.insert(deptTable, colDeptID, cv);  
                     db.close();

参考技术A 直接右键设置

世博sqlite外键

【中文标题】世博sqlite外键【英文标题】:Expo sqlite foreign key 【发布时间】:2019-08-09 15:28:39 【问题描述】:

是否有人使用外键约束对原生 expo 的 sqlite 数据库进行反应?可以使用类似sql的结构吗?

我正在尝试构建具有外键条件的多个表。

示例:如果我们有 2 个表 Persons 和 Orders,其中 personID 在 orders 表中被称为外键。使用 sqlite 是如何完成的?

【问题讨论】:

【参考方案1】:

你会有两个表,可能有一个列作为 rowid 列的别名,这个

例如

CREATE TABLE persons (
    personid INTEGER PRIMARY KEY, 
    personname TEXT
);

CREATE TABLE orders (
    orderid INTEGER PRIMARY KEY, 
    ordername TEXT, 
    person_reference INTEGER REFERENCES persons(personid)
);
注意,您必须打开外键处理,例如通过执行PRAGMA foreign_keys = ON;(或true)。见PRAGMA foreign_keys 在 SQLite 编码中 column_name INTEGER PRIMARY KEY 将该列定义为 rowid column 的别名,如果在插入时未为该列提供值,则将分配一个整数值。第一行的初始值为 1,随后的值通常比最高的 rowid 值大 1(阅读上面的链接,了解为什么该词通常是使用)。

如果您随后尝试为不存在的 personid 插入订单,则会出现外键冲突。

列级定义的替代方法是在表级定义外键,例如

CREATE TABLE orders (
    orderid INTEGER PRIMARY KEY, 
    ordername TEXT, 
    person_reference INTEGER, 
    FOREIGN KEY (person_reference) REFERENCES persons(personid)
);

例如,考虑以下内容:-

INSERT INTO persons (personname) VALUES 
    ('Fred'),
    ('Mary'),
    ('Sue'),
    ('Tom')
;
INSERT INTO orders (ordername, person_reference) VALUES
    ('Order 1 for Fred',1),
    ('Order 2 for Sue',3),
    ('Order 3 for Fred',1),
    ('Order 4 for Mary',2)
;   
INSERT into orders (ordername, person_reference) VALUES
    ('Order 5 for nobody',100);

结果是:-

INSERT INTO persons (personname) VALUES ('Fred'),('Mary'),('Sue'),('Tom')
> Affected rows: 4
> Time: 0.453s


INSERT INTO orders (ordername, person_reference) VALUES
  ('Order 1 for Fred',1),('Order 2 for Sue',3),('Order 3 for Fred',1),('Order 4 for Mary',2)
> Affected rows: 4
> Time: 0.084s


INSERT into orders (ordername, person_reference) VALUES
  ('Order 5 for nobody',100)
> FOREIGN KEY constraint failed
> Time: 0s

即最后一个,因为在 personid 表中没有 personid 为 100 的行,那么最后一个插入(在它自己的 doe 演示中)失败。

您不妨参考SQLite Foreign Key Support

【讨论】:

以上是关于android sqlite 如何设置外键的主要内容,如果未能解决你的问题,请参考以下文章

SQLite Expert Professional 如何设置主键和外键

SQLite Expert Professional 如何设置主键和外键

SQLite Expert Professional 如何设置主键和外键

如何与SQLite建立关系(外键)

Android中使用SQLite的外键约束?在删除级联

CoreData:从字典数组插入到SQLite数据库中发生未排序 - 因此无法设置外键