Nh p mụn SQL/CLI ậ

Một phần của tài liệu Tài liệu Giáo trình Ngôn ngữ SQL docx (Trang 138)

L IM ĐU ỞẦ

3.4.1 Nh p mụn SQL/CLI ậ

M t chộ ương trỡnh được vi t trong ngụn ng C và s d ng SQL/CLI sế ữ ử ụ ẽ ch a file đ u sqlcli.h, t đú nú nh n đứ ầ ừ ậ ược m t s l n cỏc hàm, cỏc đ nhộ ố ớ ị nghĩa ki u, cỏc c u trỳc và cỏc h ng ký hi u. Sau đú chể ấ ằ ệ ương trỡnh cú thể t o ra và làm vi c v i 4 lo i b n ghi:ạ ệ ớ ạ ả

1. Mụi trường: M t b n ghi ki u này độ ả ể ượ ạc t o ra b ng m t chằ ộ ương trỡnh ng d ng (client) trong vi c chu n b cho m t ho c nhi u k tứ ụ ệ ẩ ị ộ ặ ề ế n i đ n server c s d li u. ố ế ơ ở ữ ệ

2. K t n i: M t trong cỏc b n ghi này đế ố ộ ả ượ ạc t o ra đ k t n i chể ế ố ương trỡnh ng d ng v i c s d li u. M i k t n i t n t i bờn trong m tứ ụ ớ ơ ở ữ ệ ỗ ế ố ồ ạ ộ mụi trường nào đ y.ấ

3. Cõu l nh: M t chệ ộ ương trỡnh ng d ng cú th t o ra m t ho c nhi uứ ụ ể ạ ộ ặ ề b n ghi cõu l nh. M i b n ghi gi thụng tin v m t l nh SQL đ nả ệ ỗ ả ữ ề ộ ệ ơ gi n bao g m m t cursor m c nhiờn n u cõu l nh là m t truy v n.ả ồ ộ ặ ế ệ ộ ấ cỏc th i đi m khỏc nhau, cựng m t l nh CLI cú th bi u di n cỏc

Ở ờ ể ộ ệ ể ể ễ

l nh SQL khỏc nhau. M i m t cõu l nh CLI t n t i bờn trong m tệ ỗ ộ ệ ồ ạ ộ k t n i nào đ y. ế ố ấ

4. Mụ t : Cỏc b n ghi này gi thụng tin v cỏc b ho c v cỏc thamả ả ữ ề ộ ặ ề s . Chố ương trỡnh ng d ng ho c mỏy ch c s d li u s thi t l pứ ụ ặ ủ ơ ở ữ ệ ẽ ế ậ cỏc thành ph n c a cỏc b n ghi mụ t đ ch ra tờn và ki u c a cỏcầ ủ ả ả ể ỉ ể ủ thu c tớnh và/ho c cỏc giỏ tr c a chỳng. M i cõu l nh cú nhi u cỏcộ ặ ị ủ ỗ ệ ề b n ghi đả ượ ạc t o ra m t cỏch khụng tộ ường minh nh v y, và ngư ậ ười dựng cú th t o ra nhi u h n n u c n. Trong trỡnh bày c a chỳng taể ạ ề ơ ế ầ ủ v CLI, cỏc b n ghi mụ t n i chung là s khụng nhỡn th y.ề ả ả ố ẽ ấ

M i m t b n ghi này đỗ ộ ả ược bi u di n trong chể ễ ương trỡnh ng d ngứ ụ b ng m t handle, đú là m t con tr đ n b n ghi. File sqlcli.h cung c p cỏcằ ộ ộ ỏ ế ả ấ ki u đ i v i cỏc handle mụi trể ố ớ ường, k t n i, cõu l nh, mụ t tế ố ệ ả ương ngứ là: SQLHENV, SQLHDBC,SQLHSTMT, SQLHDESC, m c dự chỳng ta cúặ th nghĩ v chỳng nh cỏc bi n tr ho c cỏc s nguyờn. Chỳng ta s sể ề ư ế ỏ ặ ố ẽ ử d ng cỏc ki u này và m t s ki u đụ ể ộ ố ể ược đ nh nghĩa khỏc v i cỏc gi i thớchị ớ ả rừ ràng, nh là SQLCHAR và SQLINTEGER. Cỏc ki u này đư ể ược cung c pấ trong sqlcli.h.

Chỳng ta s khụng đi đ n chi ti t v vi c cỏc mụ t đẽ ế ế ề ệ ả ược thi t l p vàế ậ đượ ử ục s d ng nh th nào. Tuy nhiờn ta s bàn v ba ki u b n ghi khỏcư ế ẽ ề ể ả đượ ạc t o ra b ng cỏch s d ng m t hàmằ ử ụ ộ

Trong đú, ba tham s là:ố

1. hType là ki u c a handle mong mu n. Sể ủ ố ử d ngụ SQL_HANDLE_ENV cho m t mụi trộ ường m i,ớ SQL_HANDLE_DBC cho m t k t n i m i, ho cộ ế ố ớ ặ SQL_HANDLE_STMT cho m t cõu l nh m i. ộ ệ ớ

2. hIn là m t handle c a ph n t m c cao trong dú ph n t v a m iộ ủ ầ ử ứ ầ ử ừ ớ t o ra s ng. Tham s này là SQL_NULL_HANDLE n u chỳng taạ ố ố ế mu n m t mụi trố ộ ường; tờn c a mụi trủ ường là m t h ng độ ằ ược đ nhị nghĩa núi v i SQLAllocHandle r ng khụng cú giỏ tr thớch h p đõy.ớ ằ ị ợ ở N u chỳng ta mu n m t handle k t n i thỡ hIn là handle c a mụiế ố ộ ế ố ủ trường mà trong đú cú t n t i k t n i. N u chỳng ta mu n m tồ ạ ế ố ế ố ộ handle cõu l nh, thỡ hIn là handle c a k t n i mà trong đú cõu l nhệ ủ ế ố ệ s t n t i.ẽ ồ ạ

3. hOut là đ a ch c a handle do SQLAllocHandle t o ra.ị ỉ ủ ạ

SQLAllocHandle cũng tr l i m t giỏ tr thu c ki u SQLRETURN (m tả ạ ộ ị ộ ể ộ s nguyờn). Giỏ tr này là 0 n u khụng cú l i nào x y ra, và là m t giỏ trố ị ế ỗ ả ộ ị khỏc 0 n u cú xu t hi n l i. ế ấ ệ ỗ

Vớ d 3.18ụ Chỳng ta hóy xem hàm HangLuong c a hỡnh 3.4 s b t đ uủ ẽ ắ ầ trong CLI nh th nào. (Hàm HangLuong đó đư ế ược chỳng ta s d ng nhử ụ ư m t vớ d v SQL nhỳng). Nh l i r ng hàm này kh o sỏt t t c cỏc bộ ụ ề ớ ạ ằ ả ấ ả ộ c a NHÂNVIấN và x p lo i lủ ế ạ ương c a chỳng. Cỏc bủ ước đ u tiờn đầ ược ch ra hỡnh 3.1.8:ỉ ở

1) #include sqlcli.h 2) SQLHENV MyEnv; 3) SQLHDBC MyCon; 4) SQLHSTMT execStat

5) SQLRETURN errorCode1, errorCode2, errorCode3; 6) ErrorCode1=SQLAllocHandle(SQL_HANDLE_ENV,

SQL_NULL_HANDLE, &myEnv); 7) If(!errorCode1)

8) ErrorCode2 = SQLAllocHandle(SQL_HANDLE_DCB, myEnv, &myCon); 9) If(!errorCode2) 10) ErrorCode3=SQLAllocHandle(SQL_HANDLE_STMT,myCon,&exe cStat); Hỡnh 3.18: Mụ t và t o ra m t mụi trả ạ ộ ường, m t k t n i và m t l nh.ộ ế ố ộ ệ

Cỏc dũng t 2) đ n 4) mụ t handle cho m t mụi trừ ế ả ộ ường, k t n i và cõuế ố l nh tệ ương ng. Tờn c a chỳng là myEnv, myCon và execStat tứ ủ ương

ng. Chỳng ta d ki n r ng execStat s bi u di n l nh

ứ ự ế ằ ẽ ể ễ ệ

SELECT Luong FROM NHÂNVIấN ;

gi ng nh con tr execCursor đó làm trong hỡnh 3.4 nh ng v n ch a cúố ư ỏ ư ẫ ư l nh SQL nào đệ ược liờn k t v i execStat. Dũng 5) khai bỏo ba bi n mà cỏcế ớ ế l i g i hàm cú th đ t tr l i c a chỳng vào đú và ch ra m t l i. M t giỏờ ọ ể ặ ả ờ ủ ỉ ộ ỗ ộ tr 0 ch ra khụng cú l i nào x y ra trong l i g i và chỳng ta đang mong đ iị ỉ ỗ ả ờ ọ ợ trường h p đú. ợ

Dũng 6) g i SQLAllocHandle, yờu c u m t handle mụi trọ ầ ộ ường (đ i s thố ố ứ nh t), cung c p m t handle null trong đ i s th hai (b i vỡ khi chỳng taấ ấ ộ ố ố ứ ở đang yờu c u m t handle mụi trầ ộ ường thỡ chỳng ta khụng c n gỡ c ) và cungầ ả c p m t đ a ch c a myEnv nh là đ i s th ba; handle đấ ộ ị ỉ ủ ư ố ố ứ ượ ạc t o ra sẽ được đ t đõy. N u dũng 6) là thành cụng, cỏc dũng 7) và 8) s d ngặ ở ế ử ụ handle mụi trường đ nh n m t handle k t n i trong myCon. Gi thi tể ậ ộ ế ố ả ế r ng l i g i đú cũng thành cụng, cỏc dũng 9) và 10) nh n m t handle l nhằ ờ ọ ậ ộ ệ cho execStat.

3.4.2 X lý cỏc l nhử

cu i c a hỡnh 3.18, m t b n ghi l nh cú handle là execStat đó đỞ ố ủ ộ ả ệ ượ ạc t o ra. Tuy nhiờn b n ghi này v n ch a đả ẫ ư ược n i v i l nh SQL. Ti n trỡnhố ớ ệ ế k t n i và th c hi n cỏc l nh SQL v i cỏc handle tế ố ự ệ ệ ớ ương t nh SQL đ ngự ư ộ được mụ t trong ph n 3.1.10. đõy, chỳng ta k t h p văn b n c a m tả ầ Ở ế ợ ả ủ ộ l nh SQL v i m t “ bi n SQL” b ng cỏch s d ng PREPARE và sau đúệ ớ ộ ế ằ ử ụ th c hi n nú b ng cỏch s d ng EXECUTE.ự ệ ằ ử ụ

Tỡnh tr ng trong CLI hoàn toàn tạ ương t n u chỳng ta nghĩ v “ bi nự ế ề ế SQL” nh là m t handle l nh. Cú m t hàmư ộ ệ ộ

SQLPrepare (sh, st, sl), nú l y:ấ 1. M t handle l nh shộ ệ

2. M t bi n tr đ n m t l nh SQL st, vàộ ế ỏ ế ộ ệ

3. M t đ dài sl cho xõu ký t do st ch đ n. N u chỳng ta khụng bi t độ ộ ự ỉ ế ế ế ộ dài, m t h ng độ ằ ược đ nh nghĩa SQL_NTS yờu c u SQLPrepare t tớnhị ầ ự nú t xõu. Cú th là xõu là m t “xõu k t thỳc b ng null” vàừ ể ộ ế ằ SQLPrepare ki m tra nú cho đ n khi g p d u h t xõu ‘\0’ là đ . ể ế ặ ấ ế ủ Hi u qu c a hàm này là chu n b đ cho l nh đệ ả ủ ẩ ị ể ệ ược handle sh tr đ nỏ ế bõy gi bi u th l nh SQL c th st. ờ ể ị ệ ụ ể

M t hàm khỏcộ

SQLExecute(sh)

làm cho l nh do sh tr đ n đệ ỏ ế ược th c hi n. Đ i v i nhi u d ng l nhự ệ ố ớ ề ạ ệ SQL, ch ng h n nh cỏc l nh chốn ho c cỏc l nh xúa, hi u qu c a vi cẳ ạ ư ệ ặ ệ ệ ả ủ ệ th c hi n l nh này trờn c s d li u là hi n nhiờn. Khi l nh SQL do shự ệ ệ ơ ở ữ ệ ể ệ tham chi u đ n là m t truy v n, hi u qu c a l nh kộm rừ ràng h n. Nhế ế ộ ấ ệ ả ủ ệ ơ ư chỳng ta s th y trong ph n 8.4.3, cú m t con tr n cho l nh này, con trẽ ấ ầ ộ ỏ ẩ ệ ỏ đú là m t ph n c a chớnh b n ghi l nh. V nguyờn t c l nh s độ ầ ủ ả ệ ề ắ ệ ẽ ược th cự hi n, vỡ v y chỳng ta cú th tệ ậ ể ưởng tượng r ng t t c cỏc b c a tr l iằ ấ ả ộ ủ ả ờ đang n m m t n i nào đú s n sàng đ đằ ở ộ ơ ẵ ể ược truy c p. Chỳng ta cú thậ ể l y ra cỏc b , m i l n m t b b ng cỏch s d ng con tr n gi ng nhấ ộ ỗ ầ ộ ộ ằ ử ụ ỏ ẩ ố ư chỳng ta làm vi c v i cỏc con tr th t trong cỏc ph n 3.1 và 3.2.ệ ớ ỏ ậ ầ

Vớ d 3.19ụ : Chỳng ta hóy ti p t c v i hàm HangLuong vớ d 3.18. Haiế ụ ớ ở ụ l i g i hàm sau đõy s liờn k t truy v n SELECT Luong FROMờ ọ ẽ ế ấ NHANVIEN v i l nh do handle exectStat tr đ n:ớ ệ ỏ ế

11) SQLPrepare(execStat, “SELECT Luong FROM NHANVIEN “, SQL_NTS);

Hai l nh này cú th xu t hi n ngay sau dũng 10) c a hỡnh 3.18. Nh l iệ ể ấ ệ ủ ớ ạ r ng SQL_NTS yờu c u SQLPrepare xỏc đ nh đ dài c a xõu k t thỳcằ ầ ị ộ ủ ế b ng null do đ i s th hai c a nú tham chi u đ n. ằ ố ố ứ ủ ế ế

Gi ng nh v i SQL đ ng, cỏc bố ư ớ ộ ược chu n b và th c hi n cú th đẩ ị ự ệ ể ược t h p thành m t n u chỳng ta s d ng hàm SQLExecDirect. M t vớ dổ ợ ộ ế ử ụ ộ ụ v t h p cỏc dũng 110 và 12) nh sau:ề ổ ợ ư

SQLExecDirect(execStat, “SELECT Luong FROM NHANVIEN “, SQL_NTS);

3.4.3 L y d li u ra t k t qu truy v nấ ữ ệ ừ ế

Hàm tương ng v i l nh FETCH trong SQL nhỳng ho c PSM làứ ớ ệ ặ SQLFetch(sh)

trong đú sh là m t handle l nh. Chỳng ta gi thi t l nh do sh tr đ n đóộ ệ ả ế ệ ỏ ế được th c hi n, ho c vi c l y ra s gõy ra m t l i. SQLFetch, gi ng nhự ệ ặ ệ ấ ẽ ộ ỗ ố ư t t c cỏc hàm CLI, tr l i m t giỏ tr ki u SQLRETURN ch ra ho cấ ả ả ạ ộ ị ể ỉ ặ thành cụng ho c b l i. Chỳng ta cú th nh n th y r ng giỏ tr tr v doặ ị ỗ ể ậ ấ ằ ị ở ề h ng ký hi u SQL_NO_DATA bi u th , ch ra r ng khụng b nào cũn l iằ ệ ể ị ỉ ằ ộ ạ trong k t qu truy v n. Gi ng nh trong cỏc vớ d trế ả ấ ố ư ụ ước đõy c a chỳng taủ v vi c l y ra, giỏ tr này s đề ệ ấ ị ẽ ược s d ng đ đi ra kh i vũng l p màử ụ ể ỏ ặ trong đú chỳng ta l y ra liờn ti p cỏc b t k t qu truy v n. ấ ế ộ ừ ế ả ấ

Tuy nhiờn, n u chỳng ta đ t sau SQLExecute c a vớ d 8.19 m t ho cế ặ ủ ụ ộ ặ nhi u dũng g i SQLFetch thỡ b xu t hi n đõu? Cõu tr l i là cỏc thànhề ọ ộ ấ ệ ở ả ờ ph n c a nú đi vào m t trong cỏc b n ghi mụ t liờn k t v i l nh màầ ủ ộ ả ả ế ớ ệ handle c a nú xu t hi n trong l i g i SQLFetch. Chỳng ta cú th rỳt raủ ấ ệ ờ ọ ể cựng m t thành ph n t i m i l n th b ng cỏch liờn k t thành ph n v iộ ầ ạ ỗ ầ ử ằ ế ầ ớ m t bi n ngụn ng ch trộ ế ữ ủ ước khi chỳng ta b t đ u l y ra. Hàm làm nhi mắ ầ ấ ệ v đú là ụ

SQLBindCol (sh, colNo, colType, pVar, varSize, varInfo) í nghĩa c a sỏu đ i s này là:ủ ố ố

2. colNo là s c a thành ph n (bờn trong b ) mà chỳng ta nh n giỏ tr c aố ủ ầ ộ ậ ị ủ nú

3. colType là mó c a ki u c a bi n mà giỏ tr c a thành ph n đủ ể ủ ế ị ủ ầ ược đ tặ vào đ y. Vớ d v cỏc mó do sqlcli.h cung c p là SQL_CHAR đ i v iấ ụ ề ấ ố ớ cỏc m ng ho c cỏc xõu ký t , SQL_INTEGER đ i v i cỏc s nguyờn.ả ặ ự ố ớ ố 4. pVar là m t bi n tr ch đ n bi n mà giỏ tr độ ế ỏ ỉ ế ế ị ược đ t vào đú.ặ

5. varSize là đ dài tớnh b ng byte c a giỏ tr c a bi n độ ằ ủ ị ủ ế ược pVar chỉ đ n.ế

6. varInfor là bi n tr ch đ n m t s nguyờn cú th đế ỏ ỉ ế ộ ố ể ược SQLBinCol sử d ng đ cung c p thụng tin ph v giỏ tr đụ ể ấ ụ ề ị ượ ảc s n xu t ra.ấ

Vớ d 3.20ụ . Chỳng ta làm l i toàn b hàm HangLuong t hỡnh 3.4 b ngạ ộ ừ ằ cỏch s d ng cỏc dũng g i CLI thay cho SQL nhỳng. Chỳng ta b t đ u tử ụ ọ ắ ầ ừ Hỡnh 3.18 nh ng đ ng n g n, chỳng ta b qua cỏc ki m tra l i tr ki mư ể ắ ọ ỏ ể ỗ ừ ể tra xem cú ph i SQLFetch ch ra r ng khụng cũn b nào xu t hi n hayả ỉ ằ ộ ấ ệ khụng. Chương trỡnh được ch ra hỡnh 3.19:ỉ ở

1) #include sqlcli.h 2) void H nglạ ương () { 3) int i, Chuso, Đem[15]; 4) SQLHENV MyEnv; 5) SQLHDBC MyCon;

6) SQLHSTMT execStat

7) SQLINTEGER luong, luongInfo;

8) SQLAllocHandle(SQL_HANDLE_ENV,SQL_NULL_HANDLE, &myEnv);

9) SQLAllocHandle(SQL_HANDLE_DCB,myEnv, &myCon); 10) SQLAllocHandle(SQL_HANDLE_STMT,myCon,&execStat); 11) SQLPrepare(execStat, “SELECT Luong FROM NHANVIEN “, SQL_NTS);

12) SQLExecute(execStat) ;

13) SQLBindCol(execStat, 1, SQL_INTEGER, &luong, size(luong), &luongInfo);

14) While(SQLFetch (execStat != SQL_NO_DATA { 15) Chuso = 1;

16) while((LuongNV /= 10) > 0) Chuso++;

8) if(Chuso <= 14) Dem[Chuso]++; } 9) for (i=0; i<15; i++)

10) printf(“chuso = %d: so nhan vien = %d\n”, i, Dem[i]); }

Hỡnh 3.19 Đ m s nhõn viờn cú lế ố ương g m 1 ch s , 2 ch s , ….ồ ữ ố ữ ố Dũng 3) khai bỏo cỏc bi n c c b gi ng nh trong SQL nhỳng và cỏcế ụ ộ ố ư dũng 4) và 7) khai bỏo cỏc bi n c c b thờm b ng cỏch s d ng cỏc ki uế ụ ộ ằ ử ụ ể được sqlcli.h cung c p.ấ

3.5 GIAO TÁC TRONG SQL

Cho đ n lỳc này, mụ hỡnh cỏc thao tỏc trờn c s d li u c a chỳng ta làế ơ ở ữ ệ ủ m t ngộ ườ ử ụi s d ng đang truy v n và s a đ i c s d li u. Nh v y, cỏcấ ử ổ ơ ở ữ ệ ư ậ thao tỏc trờn c s d li u đơ ở ữ ệ ược th c hi n m t l n m t thao tỏc, và tr ngự ệ ộ ầ ộ ạ thỏi c s d li u đ l i sau m i thao tỏc là tr ng thỏi mà thao tỏc ti pơ ở ữ ệ ể ạ ỗ ạ ế theo s hành đ ng trờn đú. H n n a, chỳng ta hỡnh dung r ng cỏc thao tỏcẽ ộ ơ ữ ằ được th c hi n trong tr ng thỏi nguyờn v n c a nú (“m t cỏch nguyờnự ệ ạ ẹ ủ ộ t ”). Nh v y, chỳng ta đó gi thi t r ng ph n c ng và ph n m m khụngử ư ậ ả ế ằ ầ ứ ầ ề th h ng gi a thao tỏc, đ l i c s d li u trong tỡnh tr ng khụng thể ỏ ở ữ ể ạ ơ ở ữ ệ ạ ể gi i thớch đả ược nh là k t qu c a thao tỏc th c hi n trờn nú. ư ế ả ủ ự ệ

Cu c s ng th c thộ ố ự ường là ph c t p h n nhi u. Trứ ạ ơ ề ước tiờn chỳng ta xem xột cỏi cú th x y ra làm cho c s d li u tr ng thỏi khụng ph n ỏnhể ả ơ ở ữ ệ ở ạ ả cỏc thao tỏc th c hi n trờn nú và sau đú chỳng ta s xem xột cỏc cụng cự ệ ẽ ụ SQL cung c p cho cỏc ngấ ườ ử ụi s d ng đ đ m b o r ng nh ng v n đ đúể ả ả ằ ữ ấ ề khụng x y ra.ả

3.5.1 X p hàng theo th tế ứ ự

Trong cỏc ng d ng nh là ngõn hàng ho c đăng ký vộ mỏy bay, m iứ ụ ư ặ ỗ giõy cú hàng trăm thao tỏc cú th th c hi n trờn c s d li u. Cỏc thao tỏcể ự ệ ơ ở ữ ệ này b t đ u t i m t trong hàng trăm ho c hàng nghỡn tr m nh là mỏy trờnắ ầ ạ ộ ặ ạ ư bàn c a m t đ i lý du l ch, nhõn viờn hàng khụng, …. Vi c chỳng ta cú thủ ộ ạ ị ệ ể cú hai thao tỏc th c hi n trờn cựng m t tài kho n ho c m t chuy n bay vàự ệ ộ ả ặ ộ ế ch ng chộo th i gian là đi u hoàn toàn cú th x y ra. N u nh v y, chỳngồ ờ ề ể ả ế ư ậ cú th tể ương tỏc theo cỏc cỏch l lựng. Đõy là m t vớ d v cỏi cú th d nạ ộ ụ ề ể ẫ đ n sai l m n u nh h qu n tr c s d li u khụng b ràng bu c đ y đế ầ ế ư ệ ả ị ơ ở ữ ệ ị ộ ầ ủ đ i v i th t mà theo th t đú nú thao tỏc trờn c s d li u. Chỳng taố ớ ứ ự ứ ự ơ ở ữ ệ nh n m nh r ng cỏc h c s d li u khụng x s m t cỏch bỡnh thấ ạ ằ ệ ơ ở ữ ệ ử ự ộ ường theo cỏch này. Và r ng ngằ ười ta cú th đi ra theo cỏch c a ngể ủ ười ta đ làmể cho cỏc lo i sai làm này x y ra khi s d ng m t h qu n tr thạ ả ử ụ ộ ệ ả ị ương m i. ạ

1) EXEC SQL BEGIN DECLARE SECTION; 2) int flight ; /* s chuy n bay */ố ế

3) char date[10] ; /*ngày bay theo khuụn d ng SQL */ạ

Một phần của tài liệu Tài liệu Giáo trình Ngôn ngữ SQL docx (Trang 138)

Tải bản đầy đủ (PDF)

(180 trang)