Cách nối bảng sqlite trong Android?

Mọi người cho em hỏi chút. VD e có 2 bảng là học sinh gồm các cột: id_hs , ten_hs , tuoi và bảng lớp gồm các cột : id_lop , ten_lop . Em muốn nối 2 bảng thành 1 bảng vs các cột id_hs , ten_hs , ten_lop để hiển thị. Vậy lúc em truy vấn để lấyy kết quả 3 cột thì lấy làm sao ạ? Vì nếu e lấy học sinh thì lại không có thuộc tính ten_lop nên không thể get đc…

Bảng học sinh phải có thuộc tính id_lop nữa chứ, không thì làm sao biết được học sinh này thuộc lớp nào.

Giả sử có bảng hocsinh

id_hs        ten_hs      tuoi         id_lop
----------  ----------  ----------  ----------  
1           Thuy        32          1 
2           Hoang       25          1       
3           Thanh       23          1      
4           Nga         25          2   
5           Dung        27          2      
6           Kim         22          3 
7           Hai         24          3

và bảng lop

id_lop      ten_lop
----------  ----------  
1           CNPM
2           ATTT
3           KHMT  

Muốn lấy được id_hs, ten_hs, ten_lop, bạn sử dụng lệnh inner join để nối 2 bảng tạo 1 bảng virtual (bảng tạm)

SELECT id_hs, ten_hs, ten_lop FROM hocsinh INNER JOIN lop
      ON hocsinh.id_lop = lop.id_lop;

nó sẽ ra

id_hs        ten_hs     ten_lop
----------  ----------  ----------  
1           Thuy        CNPM          
2           Hoang       CNPM            
3           Thanh       CNPM             
4           Nga         ATTT          
5           Dung        ATTT             
6           Kim         KHMT         
7           Hai         KHMT       

giờ muốn filter thì dùng WHERE

1 Like

Cái cột tên lớp ấy thì mình lấy dữ liệu làm sao ạ? vì nếu lấy đối tượng là học sinh thì sẽ không có thuộc tính là tên lớp

Thế thì nó phải có 1 bảng nữa, nối 2 bảng này với nhau ^^

id_hs        id_lop
----------  ----------
1           1                  
2           1                   
3           1                    
4           2                   
5           2                     
6           3                  
7           3        

Kiểu vậy, giờ là join cả 3 bảng với nhau để tạo 1 virtual table ^^

1 Like

không phải đâu ạ. Anh nối 2 bảng như lúc đầu là giống vs cái bảng em đang làm rồi nhưng em ko biết truy vấn ra tên lớp thì mình phải dùng kiểu gì ấy ạ?

Không hiểu ý của bạn lắm vì rõ ràng kết quả có tên lớp rồi mà.
Hay ý bạn là filter theo tên lớp
… thêm vào WHERE ten_lop = ‘KHMT’

Hay ý bạn là do đã bind vào ORM, mà entity Hocsinh thì không có tên lớp
Hocsinh
+id_hocsinh
+ten
+tuoi


Lop
+id_lop
+ten

Có rất nhiều cách thiết kế ORM trong trường hợp này:
+Giả lập RDBMS: thêm id_lop vào class HocSinh
+Thêm thuộc tính Lop vào class HocSinh (nhúng class lớn vào bé, ở đây quan hệ là has-a, 1-n)
+Thêm thuộc tính HocSinh[] là mảng các học sinh vào class Lop.
+Thêm thuộc tính hocsinh_id[] là mảng các học sinh id vào class Lop.

1 Like

Hay quá nhỉ. Thế mà e lại không nghĩ ra là cách thêm thuộc tính Lớp vào class Học Sinh. Em chỉ nghĩ ra là thêm thuộc tính tên lớp vào class Học Sịnh. Như thế cũng đc nhưng giả sử mình có nhiều cột mà Học Sinh không có thì khi thêm như vậy cũng không phải là cách hay…

À anh cho em hỏi thêm với. Khi mình tạo dc cái bảng nối như kia r thì làm sao mà khi mình thay đổi mã hs của bảng học sinh thì bảng nối sẽ tự động thay đổi theo ?

À, thêm tên lớp cũng là 1 cách làm rất hay mà (gọi là Decorator: khi nào cần thêm thuộc tính nào thì mình decorate thêm, ví dụ như tên_lớp).

Cái này chắc bạn làm với Android sử dụng SQLiteOpenHelper ah?

  • Nếu thiết kế class mà nhúng 1 class # vào làm thuộc tính (hầu hết các ORM đều làm vậy) thì có thể việc build object này sẽ khá to. Ngoài ra, việc search kiểu mixing như thuộc 2 lớp có id_lop là 12, 23 hoặc ten_lop là KHMT và HTTT sẽ khó khăn? Ví dụ nếu dùng SQLiteOpenHelper, bạn sẽ phải làm 2 QueryBuilder: builder thứ nhất lấy lop_id của KHMTT và HTTT trên bảng lop, sau đó builder thứ hai search theo id_lop. Hoặc bạn phải có 1 danh sách HocSinh, sau đó search vét cạn trên tập đó.
  • Nên khi dùng ORM cũng k nhất thiết phải tuân thủ theo nó, nhiều khi cứ raw SQL mà viết rồi lấy kết quả, bind nó vào object decorator và hiển thị lên view. Vừa nhanh vừa gọn (thậm chí không cần bind data vào object cũng được ^^. Tuy nhiên, nếu output trực tiếp lên view thì sau nếu cần obj này thì lại phải gọi SQL lại)

Còn cái virtual table là được tạo dynamic bạn ah. Nên bạn thay đổi id_hocsinh thì hiển nhiên, output ra cũng sẽ thay đổi. Chứ nó không phải cached table (một số CSDL như postgre cho phép giữ lại cache table)

2 Likes

Em mới học nên đặt câu hỏi chưa đc rõ ràng lắm. Anh thông cảm nhá :grinning: Trong bảng học sinh có id_lop, vậy lúc em thay đổi id_lop ở bảng Lớp thì làm sao mà bảng học sinh đấy cũng thay đổi theo đc vậy ạ???

ID chỉ để làm reference, việc gì mà phải thay đổi hả bạn?

Còn nếu bạn muốn các thay đổi này thì các CSDL đều cho thiết lập “data integrity” (toàn vẹn dữ liệu). Ví dụ nếu bạn xóa 1 lớp hay thay đổi id của lop, thì trong bảng hocsinh, các reference này gọi là orphan (mồ côi). Để tránh mồ côi, bạn khai báo foreign key, ví dụ bảng hocsinh có foreignkey là id_lop, thiết lập
OnDelete
OnUpdate

theo các rule như
Restrict: cấm không được đổi
NoAction: không làm gì
Cascade: thay đổi theo tương ứng (cái này đúng yêu cầu này)
SetNull: trỏ về null

Khi lập trình nên thiết lập data integrity mặc dù mình sẽ phải validate rất nhiều, nhưng nó sẽ giống như lớp bảo vệ cuối cùng giúp data trở nên đúng đắn và app sẽ không bị lỗi vặt. Còn nếu không set, app sau này sẽ có rất nhiều orphan và bạn sẽ phải sửa code để làm việc với các dữ liệu không chuẩn ^^

2 Likes

Nhưng nếu em cho bảng học sinh có cột A không phải là khóa chính, bảng Lớp cũng có cột A. Vậy thì mình không thể dùng khóa ngoại đc. Như thế thì e phải làm sao để bảng học sinh vẫn tự động cập nhật đc thông tin khi mình thay edit cột A từ bảng Lớp? Nếu được thì a cho e xin code luôn nhé…

83% thành viên diễn đàn không hỏi bài tập, còn bạn thì sao?