Hoc nbiÌỲìg kbái niệm cơ sở d ữ liộn I'à Stnicliired Qiierỵ Langỉiage MySQL và SQLiie M Tniy tìm các record cơ sứ d ũ liệu iĩới PHP • ỉỉiộii lực bóa và htli d ữ liệu ĩihập Cíta ngííời dũ
Trang 1Th.S: NGUYỄN MINH - LƯƠNG PHÚC
♦ T rọii bộ 2 tậ p hạ n s ẽ có cơ h ộ i cọ x á t đ ẻ n ân g cao Icỹ
n ăiig lậ p trm li tliôiig q u a v iệc tliự c h à n h s ủ dm iíỊ các
t ín h năn g cao cáp, c h ẳ n g h ạ n n h u các vấii íiti cơ sd
d ứ liệii, MySQỊv, SQ Ịvite v à P D O c tia P H P
♦ Với phươiiq p h áp hiíớnQ d ản t à n g ví d ụ b ạ n sẽ Idiỗnp
Iiliửng d ể dàiiíỊ n ắ m b ắ t các Id iá i mộiTL c ă n b ả ii, nâng cao liơii ciiiiẹỊ Iiliit c á c h SI^ dxuig các côniỊ cxx lậ p trù ili ciia P H P đ ễ v iế t c á c c h tíớ n g t r ì n h P I Ỉ P c ă n bảii
^ Mỗi chương cồn có n h iề u b à i tậ p tliụ c liảiứá n ià b ạ n
n ê n là m th e o đ ể n ắ m vũnữ, n ộ l d ting đtíỢc tr ìn h bày,
b a o g è m s ự cài đ ặ t p h lu i m ề m , c ú p h á p n g ô n ngiì, các
c ẩ u trứ c d ữ K ệư
hướng d ẫ n r ẩ t đ ơ n g iả n v à cỢc kỳ d ề tiế p tìiư
NHÀ XƯẤT BẢN HỒNG ĐỨC
Trang 3đ ơ n g iả n v à cự c Icỳ d ể tiế p ứ iu
T liự c vậy, với p h ư ơ n g p h á p h ư ớ n g d ẫ n b ằ n g v í d ụ b ạ n
s ẽ Id iô n g n h ữ n g d ễ d à n g n ắ m b ắ t cá c I d iá i n iệ m c ă n b ả n ,
m à tliồ n g q u a đ ó s ẽ d ầ n trở n ê n q u e n tíiu ộ c với cá c Id iá i
n iè in , c ú p h á p n g ô ii n g ữ , các c ấ u ta*úc đ ữ liệ u , cá c th tíờ n g
I x m li đ i c u I d i i t n , c á c l i à n i c à i s ẵ n , v à n liiề a i t á c Aại liữ íi
íc h k h á c
H y vọ n g s á c h s ẽ là n iộ t tà i liệ u h ọ c t ậ p h ữ u íc h c h o b ạ n
đ ọ c tr o n g q u á t r ì n h ti-ỏ tlià n h m ộ t c h u y ê n g ia v ề P H P
T ấ c g iả
Trang 5C h ư ơ n g 7 : Làm v iệ c v ớ i c á c cơ sỏ dữ liệu và S Q L
Chươĩtg 10: X ử lý c á c lỗi Chiừýiìg 11: B ảo v ệ an toàn PHP Cbươềig 12: M ờ rộng PH P
Trang 68 C h ư ớ n g 7: Làm v iệ c v ớ i c á c cơ sỏ dữ liêu và SQ L
Làm việc với các cơ sd dữ
liệu vò SQL
Ể! Hoc nbiÌỲìg kbái niệm cơ sở d ữ liộn I'à Stnicliired Qiierỵ Langỉiage
MySQL và SQLiie
M Tniy tìm các record cơ sứ d ũ liệu iĩới PHP
• ỉỉiộii lực bóa và htli d ữ liệu ĩihập Cíta ngííời dũng sang mộ! cơ sở dữ
ìiC>ti ì'ới PHP
» Viết các cbỉỉơtìg trình điền khiền bàng cơ sở đ ữ liệu kbả chìtyển
(portable)
ngôn ngữ v iế t scrip t Web là nó hỗ trợ m ột dãy rộng các hệ
th ố n g dữ liệu quan hệ Sự hỗ trợ làm cho các n h à p h á t triể n Web dễ d àng tạ o các Web site điều k h iể n b ằng dữ liệu v à tạo nguyên mẫu các ứng dụng Web m ột cách n h a n h chóng v à hiệu quả
Trang 7C h ư ơ n g 7 : Làm v iệ c với các c ơ s ỏ dữ liệu và SQL
P H P hỗ trợ h ơ n 15 bộ m áy cơ sở dữ liệu khác nh au bao gồm Microsoft SQL S erver, IBM DB2, PostgreSQ L, và Oracle Cho đến P H P 5, sự hỗ trợ này đă được cung cấp qua các extension cơ sở dữ iiệu riêng, mỗi extension
có chức n ă n g v à tín h n ăn g riên g của nó Tuy nhiên, điều này đ ã làm cho các
n h à p h á t triể n kh ó th a y đổi từ m ộ t bộ m áy cơ sở dữ liệu này sa n g m ột bộ
m áy cơ sở đữ liệu khác PH P 5 đ ã giải quyết tìn h huống n ày b ằ n g việc giới
th iệu m ột A PI chung cho sự tru y cập cơ sở dữ liệu: extension P H P D ata Objects (PDO), cung cấp m ột giao diện hợp n h ấ t để là m việc với cơ sở dữ Uệu %'à giúp các n h à p h á t triể n xử lý những cơ sở dữ liệu k h ác n h au một cách n h ấ t quán
T rong P H P 5.3, extension PDO đã được cải tiế n th ê m nữa với sự hỗ trợ cho các bộ m áy cơ sở dữ liệu m ới v à những tối ưu h ó a th ê m nữa cho an n in h
v à hiệu su ất Đ ể đ ạ t được k h ả n ă n g tương thích ngược, các extension cơ sở
dữ liệu riê n g cũng tiếp tục dược hỗ trợ Bởi vì b ạn sẽ thư ờng tự n h ậ n th ấy
m ình đã chọn giữa m ột extension riêng của m ình (m à có th ể n h a n h hcm hoặc đưa r a n h iều tín h n àn g hơn) hoặc PDO (đưa r a tín h k h ả chuyển và tín h n h ấ t quán qua các bộ m áy cơ sở dữ liệu), chương n ày đề cập d ến h a i tùy chọn; chương giới th iệu về PDO v à cũng th ả o luận h a i tro n g sô’ các exten- sion riê n g th ó n g dụng n h ấ t của PH P, extension MySQL Im proved và ex- ten sio n SQLite
Giới ỉh iệ u các cơ sở dữ liệu và SQL
Trong th ờ i đại In te rn e t, th ô n g tin không còn được tr ìn h bày tro n g các tủ đựng hồ sơ nữa T hay vào đó, nó được lưu trữ dưới d ạng các số 1 và số 0 tro n g cấc kiểu dữ liệu điện tử vốn là những "hộp chứa" lưu trữ dữ liệu áp dặt
m ột cấu trúc n h ấ t định về th ô n g tin N hững cơ sở dữ liệu điện tử này không chỉ chiếm í t không gian v ậ t lý hơn không gian gỗ và kim loại tương ứng m à chúng còn chứa đầy những công cụ để giúp người dùng lọc và tru y tìm
n h a n h th ô n g tin sử dụng những tiêu chí khac ưhau Cụ th ế hầu h ế t các cơ
sở dữ liệu điện tử ngày nay là những cơ sở dữ liệu quan h ệ (relational database) cho p h ép người dùng d ịn h nghĩa mối quan h ệ giữa các b ản g cơ sở
dữ liệu k h ác n h au để tìm kiếm v à p hân tích hiệu quả hơn
H iện có sẵn m ột số lớn các h ệ thông quản lý cơ sở dữ liệu, m ột số thương
m ại và m ột số m iễn phí Có lẽ b ạn đã nghe đến m ột vài hệ th ô n g này: Oracle, M icrosoft Access, My SQL, và PostgreSQL N hững h ệ th ô n g cơ sở
dữ liệu n ày là nhữ ng ứng dụng p h ần m ềm m ạnh, phong phú tín h n ăn g có
k h ả n án g tổ chức v à tìm kiếm h à n g triệu record với nhữ ng tốc độ r ấ t cao;
do đó chúng dược sử dụng rộng rã i với các doanh n g h iệp v à v ă n phòng
Trang 810 C h ư ơ n g 7: Làm việ c với các cờ s ở dữ liệ u v à SQ L
chính phủ, thư ờng cho nhữ ng mục đích r ấ t quan trọng Trước k h i đi vào chi tiế t cụ th ể của việc xử lý các record cơ sở dữ liệu với P H P , trước tiê n cần
p h ải hiểu rõ các k h á i niệm cơ sở dữ liệu cơ bản Nếu b ạ n m ới là m quen với
cơ sở dữ liệu này, các p h ầ n sau dầy cung cấp m ột n ề n tả n g v à cũng cho b ạn
th ử nghiệm với m ột bài tậ p thực tiễ n tro n g S tru c tu red Q uery Language (SQL) T hông tin này sẽ hữu dụng để hiểu nội dung n â n g cao hơn tro n g các
hàny hoặc record (bản ghi) chứa thòng tin cho m ôt vị rri v a n ă m kỉiác Mồi recorđ được p h â n chia trở th à n h các cột hoặc field (trường) với mỗi trường chứa m ột đoạn thông tin khác Cấu trúc d ạng b ản g n ày làm cho dễ tìm kiếm tr ê n b ản g để tìm r a các record khớp với tiêu chí (criteria) cụ th ể: ví
dụ, t ấ t cả vị tr í có doanh sô' lớn hơn $10,000 hoặc d o an h s ố cho t ấ t cả vị trí
tro n g n ăm 2008
Các record tro n g b ản g không được sắp xếp th eo b ấ t kỳ th ứ tự cụ th ể - chúng có th ể được p h ân loại th eo thứ tự b ảng chữ cái, th e o n ăm , th eo tổng doanh số, th eo vị trí hoặc th eo b ấ t kỳ tiêu chí m à b ạ n chọn xác định Do đó
để làm cho dễ n h ậ n dạn g m ột record cụ th ể , cần p h ả i th ê m m ộ t thuộc tín h
n h ậ n d ạn g duy n h ấ t vào mỗi record chẳng h ạ n n hư m ột số se ria l hoặc m ã trìn h tự T ro n g ví dụ trước, mỗi record được n h ậ n d ạ n g b àn g m ột trường 'record ID' duy n h ất; trường này ảược gọi là p rim ary key (khóa chính) clio bảng
Trang 9C h ư ơ n g 7: Làm v iệ c với các cơ sở dữ liệu và SQL 11
Thủ thuật
M ộ t cách dễ dàng đ ể hiểu những khái niệm này là bằng m ộ t sự tương dồng
H ăy xem m ộ t c ơ sở dữ liệu như là m ột th ư viện và m ỗi bảng là m ột kệ sách bên tro n g th ư viện này D o đó m ột record là sự dại diện diện tử của m ột cuốn sách trê n m ộ t kệ sách vớ i tựa dề của cuốn sách là khóa chính của record Nếu thiếu tựã đề này, không th ể dễ dàng phân b iệ t m ột cuốn sách này với m ột cuô'n sách khác (Cách duy n h ấ t d ể làm điều nàỵ là m ở m ỗi cuô'n sách và kiểm tra nội dung của nó - m ộ t tiế n trìn h mâ't thời gian m à khóa c h ín h sẽ giúp bạn tránh
được)
M ột k h i bạn đ ã đưa thông tin vào m ột bảng, bạn thư ờng muốn sử dụng
aó để tr ả lời các câu hỏi cụ th ể ■ ví dụ, bao nhiêu vỊ trí có doanh số lớn hơn
$5000 tro n g 2008? N hữ ng câu hỏi này được gọi là các query (mẫu tru y vấn)
và k ế t quả được t r ả về bởi cơ sở dữ liệu n h ằm p hản hồi lạ i nhữ ng query này được gọi là các tậ p hợp k ế t quả (result set) Các query được thực th i sử dụng
S tructured Query Language
Tìm hiểu các m ối quan hệ và khóa ngoại (Poreign Key)
B ạn đ ã b iế t rằ n g m ột cơ sở dữ liệu có th ể chứa nhiều bảng Trong m ột hệ
th ô n g cơ sở dữ liệu quan hệ, những bảng này có th ể được liên k ết với nhau
b ằng m ột hoặc n h iều trường chung được gọi là các kh ó a ngoại (foreign key)
N hững k h ó a ngoại này làm cho có th ể tạo các mô’i q uan h ệ m ột đô'i một (one-to-one) hoặc m ột đối nhiều (one-to-many) giữa các b ảng k h ác n hau và
k ế t hợp dữ liệu từ n h iều b ản g để tạo các tậ p hợp k ế t quả to à n diện hơn
Để m inh họa, h ãy xem xét h ìn h 7.2 trìn h bày b a b ản g được liên kết
G a it t lD
1 H oítoí
2 Crim c Roni;mcc
Trang 10H ìn h 7.2 m in h h ọ a b a bảng, chứa thông tin về các tá c giả (bảng A), các
th ể loại (bảng G), v à các sách (bảng B) Các b ản g G và B k h á đơn giản: chúng chứa m ột d a n h sách các tê n th ể loại (genre) và tá c giả, với mỗi record được n h ậ n d ạng b ằng m ột kh ó a ch ín h duy n h ấ t B ỗng B hơi phức tạp hơn: mọi sách tro n g bản g được liên k ế t với m ộ t th ể loại cụ th ể bằng
kh ó a ch ín h của g en re (từ b ảng G) và với m ột tác g iả cụ th ể qua kh ó a chính của au th o r (từ b ả n g A)
B ăng cách dò th e o nhữ ng kh ó a n ày đi đến các b ản g nguồn tuơng ứng caa chúng, b ạ n có th ể dễ d àn g n h ậ n dạng tác giả và th ể loại cho m ộ t cuốn sách
cụ thể Ví du, cú th ể tliây vằng tựa đề "The Shin.ing" được v iế t bởi "Stephon ĩliiig" và thuộc về th ể loại "HoiTOr" Tương tự, b ắ t đầu từ dầu k ia có t}iể
th ấ y rằ n g tác giả "M ichael Connelly" đ ã v iết hai cuôn sách "The Overlook'
v à "Trunk Music"
N hững mố.l quaii hệ n(iư vậy được thấy trong ỉiình 7.2 tạo nen n éii tả n g của m ột hệ th ố n g cơ sd dử liệu quan hệ Liẻn k ế t các b ảng sử dụng các khóa ngoại cũng hiệu quả hơn lựa chọn khác: tro n g k h i tạ o m ột b ản g mọi thứ
ngoại trừ bồn rửa n h à bếp để chứa tấ t cả thông tin th o ạ t n h ìn trô n g tiệ n
lợi, cập n h ậ t m ột b ả n g n hư vậy luôn là m ột tiế n tr ìn h th ủ cóng (và dễ sai sót) để tìm mọi trư ờ ng hợp của m ột giá trị cụ th ể v à th a y t h ế nó b ằn g m ột giá trị mới P h â n ch ia th ô n g tin th à n h các b ản g độc lậ p và liê n k ế t những
b ảng n ày b ằn g các k h ó a ngoại sẽ bảo đám rằ n g m ộ t m ẫu th ô n g tin cụ th ể
x u ất h iệ n m ột lầ n v à chỉ m ột lầ n tro n g cơ sở dữ liệu; điều này loại bỏ những
p h ần dư thừa, đơn giản hóa các th a y đổi (bằng việc cục bộ h ó a chúng sang
m ột vị trí) v à làm cho cơ sô dữ liệu gọn hơn và dễ q u ản lý hơn
T iến trìn h hợp lý hóa m ột cơ sd dữ liệu b ằn g việc d in h n g h ĩa v à thực th i các môi quan h ệ m ột đôi m ột và m ột đôi nhiều giữa các b ản g th à n h p hần của nó được gọi là sự chuẩn hóa cơ sớ dữ liẹu (d ata b ase norm alization) và
nó là m ột tá c vụ ch ín h m à m ột kỹ sư cơ sở dữ liệu p h ả i đối m ậ t k h i tạo m ột
cơ sd dữ liệu mới T rong tiế n trìn h chuẩn hóa, kỹ sư cơ sở dữ liệu cũng n h ận dạng các mô'i qu an hệ chéo v à những sự phụ thuộc k h ô n g ch ín h xác giữa các bảng và tối ưu hóa việc tổ chức dữ liệu sao cho các query SQL thực th i với hiệu su ấ t tố i đa C ũng có m ột sô" dạng chuẩn giúp b ạ n te s t p h ạm vi m ột cơ
sở dữ liệu được chuẩn hóa; những dạng chuẩn n ày cung cấp n h ữ n g hướng dẫn hữu dụng đ ể giúp bảo đảm việc th iế t k ế cơ sở dữ liệu vừa n h ấ t quán về cấu trúc vừa hiệu quả
Trang 11C h ư d n g 7 : Làm v iệ c v ớ i c á c c o s ò dữ liệ u và S Q L _1 3
Tìm hiểu các câu lệnh SQL
S tru ctu red Q uery Language hoặc SQL là ngôn ngữ chuẩn được sử dụng
đ ể giao tiế p với m ộ t cơ sở dữ liệu, th ê m hoặc th a y đổi các record v à các đặc quyền người dùng v à thực th i các query Ngôn ngữ n ày tr ỏ th à n h m ộ t chuẩn ANSI vào n à m 1989 v à h iệ n được sử dụng bởi hầu n h ư t ấ t cả RDBM thương
m ại n gày nay
Các câu lệ n h SQL bao gồm m ột tro n g b a h ạ n g mục:
• Data DeýìniHon Language (DDL) DDL gồm nhũng câu lệnh định
nghĩa cấu tníc và những mối quan hệ của một cơ sở d ĩỉ Ỉiệỉi và các bảng của nó Nhũng căn ỉệnh này tbĩCờng được sứ dụng đ ể tạo, xóa và chỉnh sửa các cơ sở d ữ liệu và bảng; xác định các tên và loại tníờngi và xác lập các index.
K D a ta M a niupulation Language (DML) Các căn lệnh DML liên quan
đ ến việc thav đổi và trích X i i ấ t d ũ liệu từ một cơ sở d ữ liệu Những câu lệnh này điíợc sứ dụng đ ể thêm các record vào và xóa các record ra khỏi m ột cơ sỗ d ữ liệu; thực thi các query, tniv tìm các record bảng khớp ifớí một hoặc nhiều tiêu cbí do ngtcời dùng xá c định; và nối các bảng lại I)ới nhan sứ dụng các tníờng chung của chứng.
It Data Controỉ Language (DCL) Các căn lệnh DCL điiợc sử dụng để định nghĩa các cấp tniy cập và các đăc quyền an ninh trong một cơ sở
d ứ liệu B ạ n thĩCờng 5ÍỈ’ dụng nhũng cân lệnh nàv đ ể cho phép hoặc từ chối các đặc quyền ngtíời dùng; p h ã n công các I>ai trò; thay đổi các passỉiorđ- x e m cá c qtiyền (permission); í>à tạ o c á c tậ p b ợ p q u v tắ c (n ú o s e t)
đ ề bảo vệ việc tniy cập d ữ liộu.
Các lện h SQL giống n hư tiến g A nh nói, n h ằ m lầm cho ngôn ngữ dễ học hơn Cú p háp cũng k h á trực giác: Mọi câu lệ n h SQL b ắ t đẩu với m ột "từ
h à n h động ' n h ư D ELETE, INSERT, ALTER, hoặc DESCRIBE và k ẽ t thúc
b ằn g m ộ t dấu chấm phẩy K hoảng trắn g , các ta b v à các ký tự trở về đầu đòng được bỏ qua Sau đây là m ột vài ví dụ về nhữ ng câu lệ n h SQL hợp lệ:
CREATE DATABASE library ;
SELECT movie FROM movies WHERE rating > 4;
DELETE FROM cars WHERE year_of_manufacture < 1980;
B ảng 7.1 liệ t k ê cú p h áp cho m ột sô' câu lện h SQL phổ biến với các giải
th ích
Trang 1214 C h ư d n g 7: Làm v iệ c với c á c c ơ sở dữ liệu v à SQ L
INSERT INTO table-name
(lìeldl, rield2,„) VALUES
(valuel, vali:e2, )
UPDATE table-nam e SET
íie ld l= v a lje l, fíeld2-value2,
(WHERE condition)
DELETE FROM tabỉe-name
{VVHERE conaitionl
SELECT fỉeld l, íieM2,
FROM table-nam e iWHERE
Thực hành 7.1: Tạo và tập hợp lại m ột cơ sở dữ liệu
Bây giờ k h i b ạ n đ ă hiểu những điểm cơ bản, h ã y th ử m ộ t bài tậ p thực
h à n h giúp b ạ n là m quen với việc sử dụng cơ sở dữ liệu và SQL T rong p hần
Trang 13này b ạ n sẽ sử dụng C lient dòng lệ n h MySQL tương tá c đ ể tạ o m ộ t cơ sở dữ
liệu v à các bảng, th ê m v à b iê n tậ p các record và tạ o các tậ p hợp k ế t quả khớp với nhữ ng tiê u chí khác nhau
-C h ư d n g 7 : Làm v iệ c vcii các cơ sò dữ liệu và SQL 15
Qua suốt bài tập sau đây, chữ in đậm biểu íhị các lệnh mà bạn nên
gõ nhập tại dòng nhắc dồng lệnh MySQL Các lệnh có thể được nhập bằng hoặc chữ hoa hoặc chữ thường Trước khi bắt đầu vổi bài tập, hãy chắc chắn rằng bạn đã cài đặt, câu hình và test hệ thống cơ sở dữ liệu MySQL theo những hướng dẫn trong những phụ lục của sách này
B ắ t đầu b ằ n g việc khởi động Client dòng lệ n h MySQL v à k ế t nôi với cơ
sở dữ liệu M ySQL b ằng usernam e v à password:
shell> m ysq l -u user -panel
Passvvord: ****■•*
Nếu mọi th ứ đều diễn ra tố t đẹp, b ạn sẽ th ấ y m ột th ô n g báo chào đón và
m ột dòng n h ắc SQL tương tác n h ư sau:
m ysql >
Bây giờ b ạ n có th ể tiế n h à n h n h ậ p các câu lệ n h SQL tạ i dòng nhắc này
N hững câu lệ n h n ày sẽ dược chuyển sa n g v à được thực th i tr ê n server MySQL và k ế t quả sẽ được h iể n th ị tr ê n các dòng sau dòng nhắc N hớ k ết thúc mồi câu lệ n h b ằn g m ột dấu chấm phẩy
Vì t ấ t cả b ả n g được lưu trữ tro n g m ột cơ sở dữ liệu, bước đầu tiê n là tạo
m ột cơ sở dữ liệu, sử dụng câu lệ n h CREATE DATABASE:
m ysql> CREATE DATABASE m usic;
Query OK, 1 row affected (0, 05 sec)
T iếp theo, chọn cơ sở đữ liệu mới tạo này làm cơ sở dữ liệu m ặc định cho
t ấ t cả lệ n h tương lai b ằng câu lệ n h USE:
mysql> USE m usic;
Database changeđ
Thêm các bảng
M ột k h i b ạ n đ ã khởi tạo cơ sở dữ liệu, đ ã đến lúc th ê m m ộ t sô' b ảng vào
nó L ệnh SQL đ ể thực h iệ n điều n ày là câu lện h CREATE TABLE, câu lện h
Trang 14n ày đòi hỏi m ộ t tê n b ản g v à m ột mô tả chi t iế t về các trư ờ n g của bạn Sau đây là m ột ví dụ:
m ysql> CREATE TABLE a rtis ts (
-> a r tis L id INT(4) NOT NULL PRIMARY KEY AUTO.INCREMENT,
•> a rtis L n a m e VARCHAR (50) NOT NULL, -> a rtis L c ũ u n tĩV CHAR (2) NOT NULL
-> ):
Ouery OK, 0 rows affected (0.Ư7 sec)
Cău lệ n h n ày tạo m ột b ản g có tê n là a rtis ts có ba trư ờ n g a r tis t.id , artist_ n am e, và artist_country Chú ý rằ n g theo sau mỗi tê n trư ờng là một
p h ần k h ai báo kiểu (type declaration); p h ần kh ai báo n ày n h ậ n dạn g kiểu
dữ liệu ntà tiư ò n g sẽ chứa chũ dù là striiig (chuỗi), n u m eiic (số), tem poral (thớỊ giaiu, hoặc Booleai'- MySQL hỗ trợ m ột 30' kíểi dữ liệu k h ác nh au và các kiểu dữ liệu quan trọiig nhấc được tóm t á t iro n g b ản g 7.2-
Có th ê m m ột vài rà n g buộc (modifier) được xác lập cho b ản g tro n g câu lện h trước:
# Modiỷier NOTNỤLL bảo đảm rằng tníờng không th ể chấp nhận m ột giá
írị NULL sau m ỗi định nghĩa tncờng.
K Modiýier PRIMARY KEY đánh dấu tníờng tương icng là khóa chinh (pri- tnary key) của bảng.
!ẵ ModiJỉerAUTO_INCREMENT, chỉcósãnchocáctníờ ngsố, vêỉtcẩuMySQL
tự động tạo một giá trị cho mcờng n à y mòi lần một record mới đĩcợc chèn i>ào bảng, tdinggiá trị tntòc lên 1.
Bằng 7.2 Các kiểu dữ liệu MySQL
Trang 15YEAR Một trường cự thể cho năm hiển th ị trong
dãy 1901 đến 2155 theo định dạng YYYY
một chiều dài khả biến
từ một danh sách các giá trị có thề có được định nghĩa trước dó
nhiều giá trị từ một tậ p hợp giá trị có th ể có được định nghĩa trước dó
Bây giờ h ãy tiế n h à n h tạo th êm hai b ảng sử dụng các câu lệ n h SQL này:
m ysql> CREATE TABLE ratings (
-> ra tin g _ id INT{2) NOT NULL PRIMARY KEY, -> ratin g_n a m e VARCHAR (50) NOT NULL
-> ):
Query OK, 0 rows atíected (0,13 sec)
m ysql> CREATE TABLE songs (
-> s o n g id 1NT(4) NOT NULL PRIMARY KEY AUTO.INCREMENT, -> s o n g _ title VARCHAR(IOO) NQT NULL,
-> lk _ s o n g _ a rtis í INT{4) NOT NULL, -> lk_son g _ra tÌn g 1NT(2) NOT NULL
■> ):
Query OK, 0 rows affected (0,05 sec)
Thêm các Record
T hêm m ột record vào m ột bản g chỉ đơn giản là gọi câu lệ n h INSERT với
nh ữ n g giá tr ị th íc h hợp Sau đây là m ột ví dụ, ví dụ n ày th ê m m ộ t record vào b ản g a rtis ts b ằ n g việc xác định các giá trị cho các trư ờng a rtist_ id và
a r t i s t n a m e :
C h ư ớ n g 7: Làm việ c với các c o sõ dữ liệu và SQL Ị_7
Trang 161 8 _C h ư ờ n g 7: Làm v iệ c v d i c á c c ờ s ò d ư liệ u v à S Q L
m ysql> INSERT INTO a rtis ts (a rtis t_ id , a rlis L n a m e , a rtis L c o u n try )
-> VALUES c r , 'Aerosm ith', ‘US’);
Query OK, 1 row affected (0.00 sec)
Từ p h ần trước b ạn sẽ nhớ rằ n g trường a rtist_ id đ ã được đ á n h dấu b ằng
cờ (flag) AUTO_INCREM ENT Đây là m ột p h ầ n m ô rộ n g MySQL cho SQL chuẩn yêu cầu M ySQL tự động g án m ột giá tr ị vào trư ờng n ày nếu nó không
dụng cáu lệ n h sau đây;
m ysql> INSERT INTO a rtis ts (artist n3m e, artỉst_cQiintry>
> VALUES ( ‘A hba’ , ‘ SE’ );
Query OK, 1 row affented (O.GO sec)
Tương tự, th ẳ m m ột số rccord vàc b ảng rEtings:
n y s q l> INSERT INTO ra tin g s ( r a t in g jd , ra tin g _n a m e ) VA1.UES (4, ‘ Goort’ }- Query OK, 1 row affected (0.00 sec)
m y s q b INSERT INTO ratings ( r a t in g jd , ra tin g _ n a m e ) VALUES (5, ‘ ExGel-
le n t'):
Query OK, 1 row affected (0.00 sec)
Thêm m ột số record vào b ản g songs:
mysq[> INSERT INTO songs (so n g _títle , fk _ s o n g „a rtis t, fk_so n g _ra tin g ) -> VALUES ( ‘JanieVs Got A Gun’ , 1, 4);
Query OK, 1 row affecteđ (0.04 sec)
m ysql> INSERT INTO songs (s o n g J ỉtle , fk _ s o n g _ a rtis t, !k _ s o n g ,ra tin q ) -> VALUES ( ‘ Crazy’ , 1, 5);
Query OK, 1 row affected (0,00 sec)
Chú ý rằ n g các record tro n g bản g songs được liên k ế t với các record tro n g các bảng a rtis ts và ratin g s thông qua các khóa ngoại (foreign key) B ạn sẽ
th â y trực tiếp n h ừ n g môi queưi h ệ khóa ngoại n ày tro n g p h ầ n tiếp theo
Q i i d a
Nguồn lưu trữ mã cho sách này có một danh sách đầy đỏ các câu lệnh SQL INSERT để tập hỢp lại ba đoạn được sử dụng trong bài tập này, Chạy các câu lệnh này và hoàn tất việc xây dựng các bảng _t r ự ^ khi_^ ^ 'n ^ á c phần tiếp theo
Trang 176 rows in set (0.00 sec)
T rong h ầu h ế t các trường hợp, bạn sẽ muốn th ê m các bộ lọc (filter) vàoquery để giảm kích cỡ của tậ p hợp k ế t quả và bảo đảm rằ n g nó chứa chỉ cácrecord k h ớ p với nhữ ng tiêu chí n h ấ t định Điều này được h o àn t ấ t bằn g việc
th ê m m ộ t m ệ n h đ ề W HERE vào câu lệnh SELECT cùng với m ộ t hoặc nhiều biểu thức có điều k iện Sau đáy là m ột ví dụ, ví dụ này liệ t k ê chỉ các nghệ
sĩ từ nước Mỹ:
m ysql> SELECT a r tis U d , artist_nam e FROM artists
-> WHERE a rtis L c o u n try = ‘US’ ;
a rtist_ld artisL na m e
2 rows in set (0.00 sec)
T ấ t cả to á n tử so sá n h chuẩn m à bạn đã quen thuộc từ P H P được hỗ trợ bởi SQL Ví dụ trước m inh h ọa to án tử đảng thức (=); ví dụ tiế p th e o sau đây
m inh h ọ a to á n tử lớn hơn hoặc bằn g {>=) b ằng việc liệ t kê t ấ t cả b ản nhạc
Trang 187 rows in set ^0.00 sec)
B ạn co th ể k ế i hợp những biểu thức có điều k iệ n sử dụng cấc to á n tứ logic AND, OR, vè MOT ín h ư v đ i câu lệnh có điếu k iệ n P K P thóiig thường)
quốc Anh:
mysql> SELECT a rtist_n a m e, arti3t_ccuntry PRCIVI a rtis ts
> VVHERE ă rtis t CGuMry = ‘US -> OR a rtis L c o u n try = UK’ ;
a rtis L n a m e artist_CDuntfy
■■■ake T h ít UK Girls Alũud UK
4 rows in set (0.02 sec)
Another Crack In My Heart Apologize
Babe
Trang 19C h ư ớ n g 7 : L à m v iệ c v ổ i các c d s ỏ d ũ liệu v à S Q L _21
Crazy Dancing Queen
En Las Delicious Gimme Gimme Gimme Janie’s Got A Giin Pray
SOS Sure Voijlez Vous
12 rows in set (0.04 sec)
Đ ể p h â n loại đảo ngược đ a n h sách này, th êm m odiíĩer DESC như trong
ví dụ tiế p theo:
m ysql> SELECT so n g _title FROM songs
-> ORDER BY s o n g title DESC;
s o n g J itle
s o n g J ỉtle Sure SOS Pray Jariie's Got A Gun Gimme Qimme Gimme
En Las Delicious Dancing Queen Crazy
Babe Apologize Another Crack In My Heart
12 rows in seí (0,00 sec)
SQL cũng cho bạn giới h ạ n bao nhiêu record x u ất h iệ n tro n g tậ p hợp k ế t quả bằn g từ k h ó a LIM IT, từ k h ó a này chấp n h ậ n h a i th a m sô': o íĩset record
để b ắ t đầu {bắt đầu với 0) và số record để hiển th ị Ví dụ, để h iể n th ị các
h àn g 4-9 của m ột tậ p hợp k ế t quả, sử dụng câu lệ n h sau dây:
Trang 20m ysql> SELECT s o n g titie FROM songs
-> ORDER BY s o n g J ille -> LIM IT 3.6;
song_tit[e Crazy Dancing Cueen
En Las Deliciủus Gimme Gimme Gimme Janie's Got A Gun Pray
5 rows in set {0.00 sec)
S ử dụng các ký lự đại diện (Wiỉdcard)
Câu lệnh SQL SELECT cũng hỗ trợ m ột m ệnh đề LIKE, m ệnh đề này có
th ể được sử dụng để tìm kiếm b ên tro n g các trường te x t sử dụng n h ữ n g k j
tự đại diện (vvildcard) Cõ hai ioại vvildcard được cho p hép tro n g m ột m ệnh
đề LIKE: ký tự % được sử dụng để báo hiệư zero hoậc n h iều trường hợp của
m ột ký tự v à ký tự _ được sử đụng để báo hiệu chính xác m ột trường hợp của
m ột ký tự
Ví dụ sau đây m in h họa tiếp m ột m ệnh dề LIKE, tìm kiếm các tự a đề
b ản n h ạc có ký tự 'g' tro n g đó:
mysql> SELECT s o n Q _ id , s o n g J itle FROM songs
-> WHERE s o n g _ title LIKE ‘ % g % ’ ; song,Jd song ,title
và h iể n th ị m ột tậ p hợp k ế t quả k ế t hợp v ề m ặ t kỹ th u ậ t, đây được gọi là
2 2 _ C h ư ớ n g 7: Làm việ c với các Cờ s ò dư liệu v à S QL
Trang 21m ột jo in vì nó đòi hỏi "nối" các b ảng khác nhaư tạ i các trường chung (các
k hóa ngoại) đ ể tạo các view mới của dữ liệu
• • • • • • •
Thủ thuật
K hi nối các bảng, b á t đầu m ỗi tên trưèmg bằng tên của bảng m à nó thuộc về để trá n h sự nhầm lẫn phòng hờ các trường tro n g các bảng khác nhau có cùng m ột tên.
Sau đây là m ột ví dụ về việc nối các bảng songs v à a r tis ts lại với n hau sử dụng trường a rtist_ id chung (m ệnh đề WHERE được sử dụng để á n h xạ các trư ờng chung sang với nhau)
m ysql> SELECT song_id, s o n g J itle , a rtis L n a m e PROIVl songs, artists -> WHERE s o n 9 S fk _ so n g _ a rtlst = a rtis ls a rtis L id ;
C h ư ớ n g 7: Lám v iệ c với các Cd sở dữ liệu v à SQL _ ^
12 rows in set (O.ũũ sec)
Và đây là m ột \-í dụ về việc nối cả b a bảng lại với n hau và saư đó lọc tậ p hợp k ế t quả th ậ m chí nhiều hơn nữa để bao hàm chỉ các b ả n nhạc có m ột
ra tin g là 4 trở lê n v à có các nghệ sĩ không phái ở Mỹ;
m ysql> SELECT s o n g _ tiile , a rlist_nam e, rating_nam e
•> FROM songs, artists, ratings -> WHERE songs,fk_song_artist = a rtists.a rỉist_id -> AND songs.ík_song_rating = ra tin g s ra ỉin g id -> AND ra tin g s ra tin g _ id >= 4
Trang 222 4 C h ư ơ n g 7: Làm v iệ c vớ i c á c c ơ s ỏ d ữ íiê u v à S Q L
-> AND a rtis ts a rtis L c o u n try != ‘US’ ;
En Las Delicious Cubanismo Excellent
4 rows ỉn set (0.Ũ2 Sfic)
Chỉnh sửa và loại bỏ các Record
TươPg tự n h ư bạn INSERT các reccrd vào m ột bảng, bọn cũng cc th ể xóa các record b ằn g câu lệ n h DELETE Điển hình, b ạn thường chọn m ột tậ p hợp con các h àn g cụ th ể cần xóa b ằn g việc th êm m ệ n h đề W HERE vào câu lện h DELETE n hư tro n g ví dụ tiếp theo, ví dụ này xóa t ế t cả b ản nhạc c<^
m ysql> DELETE FROM songs
-> WHERE fk_song_raỉỉng <= 3;
Query OK, 5 rows affected (0.02 sec)
Cũng có m ột câu lệnh UPDATE, câu lện h này có th ể được sử dụng để
th a y đổi nội dung của m ột record; câu lện h này cũng :h ấ p n.hận m ột m ệnh
đề W HERE để b ạ n có th ể áp đụng những th a y đổi vào chỉ các record khớp với nhữ ng tiêu chí riên g biệt Xem x é t ví dụ sau đây, ví dụ này th a y đổi
ra tin g 'E xcellent' th à n h T a n ta stic ':
m ysql> UPDATE ratings SET rating_nam e = T a n ta s tic ’
-> WHERE ía lin ịj_ n a m e = ‘ E xceílent’ ; ũuery OK, I fũw affected (0.00 sec)
Rows matched; 1 Changed: 1 VVarnings: ũ
B ạn có th ể th a y đổi nhiều trường bằng việc tách b iệ t chúng b ằn g các dấu phẩy Sau dây là m ột ví dụ cập n h ậ t m ột record bản n h ạc cụ th ể tro n g bảng songs, th a y đổi cả tự a đề của nó và ra tin g của nó:
m ysql> UPDATE songs SET so n g _title = ‘VVaterloo’ ,
•> lk _ s o n g _ ra tỉn g = 5
-> WHERE s o n g J [ỉ = 9;
Ouery OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 VVarnings; ũ
Trang 23C h ư đ n g 7 : Làm v iệ c v ớ i các c ơ sở dư liệu và S Q L 25
Hỏi chuyên gia
H ỏ i: T ô i đ a n g s ủ d ụ n g _ cơ s ở d ữ liệ u v à n ó k h ô n g h ỗ t r ợ kiểu trư ờ n g , T ô i p h ả i làm gì b â y giờ?
Đ á p : C á c c ơ s ỏ d ữ !iệu k h á c nhau c ó cú p h á p k h á c n h a u c h o c á c k iể u dữ liệ u trư ờ n g V i d ụ , M y S Q L gọi c á c trư ờ n g s ố n g u y ê n là IN T , tro n g khi
S Q L ite g ọ i c á c trư ờ n g y n h ư th ế là IN T E G E R T u y n h iê n , h ầ u n h ư m ọi
c ơ s ở d ữ liệ u s ẽ hổ tr ợ - tố i th iể u - c á c kiểu d ữ liệ u c h o n hữ ng g iá trị số
n g u y ê n (in te g e r), g iá trị d ấ u đ ộ n g (flo a d in g *p o in t), g iá trị c h u ỗ i (s trin g ),
g iá trị nhị p h â n (b in a ry ) v à g iá trị N U LL, T ấ t c ả n h ữ n g gl bạn c ầ n làm là
d ò tìm tà i liệ u c ơ s ở d ữ liệ u và xá c định cú p h á p đ ể s ử d ụ n g c h ín h xá c
n h ữ n g k iể u đ ữ liệ u đ ó tro n g c á c câu lệ n h S Q L
H ỏ i: T ạ i s a o tô i c ẩ n liệ t kê tấ t cả trư ờ n g b ắ t b u ộ c tro n g c â u lệ n h S E L E C T ?
T ó i k h ô n g th ể s ử d ụ n g ký tự đại d iệ n * để n h ậ n đ ư ợ c trỏ lại tấ t c ả trư ờ n g
c ó sẳn p h ả i k h ò n g ?
Đ á p : T ro n g k h i S Q L h ỗ trợ ký tự đại d iệ n dấu s a o (*) đ ể đ ạ i d iệ n c h o “ tất
c ả trư ờ n g tro n g m ộ t b ả n g “ , ưu tiê n luôn đ ặ t tê n cụ th ể c á c trư ở n g m à
b ạ n m u ố n th ấ y tro n g tậ p h ợ p kết q u ả Đ iể u n à y c h o p h é p ứ n g d ụ n g
s ố n g s ó t sa ư n h ữ n g th a y đ ổ i cấu trú c tro n g b ả n g c ủ a nó và th ư ờ n g c ũ n g
c ó h iệ u q u ả h ơ n v ề k h ía cạ n h bộ nhớ bởi vì tậ p h ợ p k ế t q u ả sẽ kh ô n g
c h ứ a d ữ liệ u k h ô n g m o n g m u ố n h o ặ c d ữ liệ u k h ô n g liê n q u a n
Sử dụng E xtension MySQL của PHP
N hư được g iải th íc h trước đó, PH P cho phép các n h à p h á t triể n tương tác với nhữ ng cơ sd dữ liệu b ăng hai cách: b ằng việc sử dụng m ột extensioii riên g b iệ t của cơ sở dữ liệu được tùy biến hoặc b ằn g việc sử dụng extension
PH P D ata O bjects (PDO) tru n g hòa với cơ sở dữ liệu T rong k h i extension PDO có tín h k h ả chuyển (portable) hơn, nhiều n h à p h á t triể n v ẫn th ấ y sử dụng ex ten sio n cơ sở dữ liệu riêng th ì ưu tiê n hơn đặc b iệ t khi extension riêng có hiêu s u ấ t tố t h ơ n hoặc nhiều tín h n ăn g hơn p h iên b ản PDO.Trong số n h ữ n g bộ m áy cơ sở dữ liệu khác n hau được hỗ trợ bởi PH P, cho đèíi băy giờ bộ m áy cơ sở dữ liệu thông đụng n h ấ t la MySQL Kliông khó hiểu tạ i sao: C ả P H P và MySQL đều là những dự á n nguồn m ở v à bằn g việc
sử dụng chúng cùng với nhau, các n h à p h á t tr iể n có th ể có lợi từ những khoảng tiế t k iệm lớn về chi p h í bản quyền của nhữ ng lựa chọn m ang tín h thương m ại Trước đây P H P cũng đã hỗ trợ từ bên ngoài cho MySQL kể từ
PH P 3 và chỉ hợp lý k h i tậ n dụng lượng suy nghĩ đ án g k ể m à các n h à p h á t triể n P H P v à M ySQL đã đ ặ t vào việc bảo đảm rằ n g h a i gói (package) làm việc cùng với n h au m ộ t cách thông suốt v à trơ n tru
Trang 24N goài việc hỗ trợ MySQL thông qua extension P H P D a ta O bjects (được
th ả o lu ậ n tro n g p h ầ n tiế p theo), P H P cũng có m ột extension M ySQL tùy ý
có tê n là M ySQL Im proved (MySQL) m ang lại nhữ ng lợi ích về tốc độ và tín h n ă n g so với p h iê n b ả n PDO v à là m ột lựa chọn tô't cho các dự á n p h á t
tr iể n d à n h riê n g cho MySQL- Các p h ần tiế p th eo th ả o luận chi tiế t hơn
ex ten sio n này
// attem pt database connection
SiTivsqli = 'ie w -■nysqii(‘ lo';alnost", 'us^ỉr”, ‘pass’ , '
it ($m ysqii ==:= falS8) I
die('‘ ERROR: Could not connect " , m ysqíi_connect_error());
1
/ / attem pt query execiition
/ / ilerate over resuỉt set
/ / p rin t each record and its tields
/ / output: “ 1:Aerosmith \n 2:Abba \n ."
$sql = “ SELECT a rtis L id , aríisL na m e FROM artists";
if ($result = $m ysq)i->quefy($sql)) {
if ($resuỉt->nijm _row s > 0) I
w hí!e($row = $result->fetch_array()) i echo $ ro w [0 ] $row [1] "\n";
I
$result->close();
} else i echo "No recorcls matching your query were íound,";
Trang 25C h ư ở n g 7: Làm việ c với các cơ sô dữ liệu và SQL 2 7
Kình 7.3 Truy tìm các record từ một cơ sở dữ liệu MySQL với PHP
H ình 7.3 m in h họa k ế t quả của script này
N hư bạn có th ể th ấ y sử dụng P H P để nh ận dữ liệu từ cơ sở dữ liệu đòi hỏi
m ột sô' bước được mô tả ở đây:
1 Để b ắ t đầu giao tiế p với serv er cơ sở dữ liệu MySQL, trước tiê n b ạn
cần mở m ộ t nô'i k ế t với server T ấ t cả sự giao tiế p giữa P H P và server cơ sở dữ liệu xảy r a qua nối kết này
Để khởi tạ o nô'i k ế t này, khởi tạo m ột instance của class M ySQL và chuyển đến phương thức tạo đối tượng bôn đối số: tê n h o st của se rv e r MySQĨ để k ấ t nối, m ột usernam e và password hợp lệ để tru y cập nó vào tê n cơ sở dữ liệu để sử dụng
Giả sử nỗ lực k ế t nối th à n h công, instance (tối tượng n ày tượng trư n g cho nôl k ế t cơ sd dữ liệu cho t ấ t cả hoạt động tương lai v à phơi bày những phương thức đê' truy vấn, truy Um và xử lý các tậ p hợp k ế t quả Nếu nỗ lực k ế t nối không th à n h còng, in stan ce đối tượng sẽ trở
th à n h false; m ột th ô n g báo lỗi giải thích lý do t h ấ t bai b ây giờ có th ể
• • • • • • •
Thủ thuật
Nếu server c ơ sờ dữ liệ u và W eb server đểu chạy trê n cùng m ộ t m áy v ậ t lý , bạn
có th ể sử dụng localhost làm tên servcr.
2 Bước tiếp th e o là tạo và thực th i query SQL Điều n à y được thự c h iệ n bằng việc gọi phương thức queryO của đối tượng M ySQLi v à chuvển
Trang 26đ ến nó query cần được thực th i Nếư query không th à n h công, phương thức tr ả về Boolean false và m ột th ô n g báo giải th íc h nguyên n h ân
t h ấ t bại được lưu trữ tro n g thuộc tín h 'erro r' của đối tượng MySQLi
3 M ặt khác, nếu query th à n h công và tr ả về m ột hoặc n h iều record, giá trị tr ả về của phương thức query 0 là m ộ t đối tượng khác, đối tượng n ày là m ột in stan ce của class M ySQLi_Result Đô'i tượng này
nhữ ng phương thứ c khác nhau d àn h cho việc xứ lý nhữ ng record riên g lẻ tro n g tậ p hợp k ế t quả
Một phương thức như vậy là phương Ihức fetch._array () Mòi lẩn fetch_array 0 được gọi ra, nó tr ả về record tiế p theo tro n g tậ p hợp
k ế t quả dưđi d ạ n g m ộ t m ảng Đ iều n à y là m cho phư ơng thức
fetch_an'ay {) Lất th ích hợp để sử dụiig tio iíg rrjột vòiig lập w hiìe
hoậc for Bộ dếm vòng lặp (loop counter) quyếĩ d ịnii vòng lậ p í;êu chạy bao nhiêo lần ; giá trị này cò được lừ thuộc tin h 'num _rows' ?úa đối tượng M ySQLi_Result, thuộc tín h này lưu tr ữ số h à n g dược trà
về bởi query Các trường riêng ỉẻ từ record có th ể được tru y cập dưới
d ạng các p h ần tử m ảng, sử dụng index trường hoặc tê n trường
— -Thuộc tính ’num_rows' chỉ có ý nghĩa khi được sử dụng với các query ưả về dữ liệu chẳng hạn như các query SELECT; nó không nên đưỢc sử dụng vđi những query INSERT, UPDATE hoặc DE- _L Ẹ IẸ i_ _
4 Mỗi tầ p hợp k ế t quả được tr ả về sau m ột ouery chiếm m ột lượnơ bộ
n h ớ nào đó M ột k h i tậ p hợp k ế t quả được xử lý, n ên tiê u hủy dối tượng M ySQLi_Resưlt, và giải phóng bộ n h ơ được sử dụng bằn g việc gọi phương thức close 0 cùa đối tượng Và m ột k h i b ạn đ á là m việc xong với cơ sở dữ liệu b ạn cũng n ên hủy bỏ đõ'i tượng MySQLi chính
m ột cách tương tự b ằng việc gọi phương thức close 0 của nó
Trả về các Record dưới dạng các m ảng và đối tượng
L istin g trước đã m inh họa m ột phương p h áp xử lý m ột tậ p hợp k ế t quả: phương thức fetch _ array 0 của đối tượng M ySQLi_Result P hương thức này
tr ả về m ột record từ tậ p hợp k ế t quả dưới dạng m ột m ản g chứa các key được tạo index số và các key được tạo index chuỗi; điều n ày cho các n h à p h át triể n sự tiệ n lợi cho việc th a m chiếu đến những trường riê n g lẻ của mồi record b ằn g tê n index hoặc tê n trường
Trang 27L istin g trước m in h họa cách tru y tìm những trường riên g lẻ sử dụng sô' index trường L istin g sau dây tương đương listin g trước thực h iệ n cùng một
tá c vụ sử dụng các tê n trường:
<?ptíp
// attem pt database connection
Sm ysqli = new mysqlỉ(''!ocalhost", “ user", “ pass” , ‘'music");
íf {Sm ysqli === íaise) {
die(“ ERROR: Could not connecl “ m ysqli_connect_error());
}
// attem pt query execution
/ / iterate over result set
// p rin t each record and its íields
// ouíput: "1 :Aerosmith \n 2:Abba \n .”
$sql = "SELECT artist_id, artist_name FROM artists” ;
if {$result » $m ysqii->query($sql)) {
if {$result->num _rows > 0) i
w hile($row = $result->fetch_array()) { echo $ ro w ['a rtis tJ d '] , $row ['artist_nam e’] “ \n ” ;
(
$result->close();
I else { echo "No records matching your query were foưnd.":
C h ư ớ n g 7 : Làm v iệ c với các co sỏ dữ liệu và SQ L _ ^
Trang 28được tru y cập sử dụng ký hiệu $object-> p ro p erty chuẩn L istin g sau đây
m inh họa phương p h áp này:
<?php
/ / attem pt database connection
Smysqlỉ » new m ysq li(“ localhost’’ “ user", “ pass", ‘'m usic");
if (Smysqli === íalse) i
tíie(“ ERROR: Cùuld not connect, ' , m ysqli_connect_errcr()), I
// atíem pt qutìry executíon
/ / iterate over result seí
/7 print each record and its íieids
/ / outpiít: ‘"!:Aerosm ith \n 2:Abba \n .”
$sqi = “ SE l E C Ĩ artist_id, artisM ia rn e FRO!VI a ilis ts ’ ,
if ($resu!t = $m ysqli->query($sql)) I
if ($result->num _rows > 0) { whỉle($row = $result->fetch_ũbject()) { echo $ ro w -> a rtisL id , , $row->artist_nam e "\n";
}
$result->close();
} else { echo “ No records matching your query were found.” :
Thêm hoặc chỉnh sửa dữ liệu
Thực th i m ột query vốn th a y dổi dữ liệu tro n g cơ sở dữ liệu cho dù nó là
m ột INSERT, UPDATE, hoặc DELETE th ì đơn giản n h ư nhau Ví dụ sau đày m in h h ọ a b ăn g việc th ê m m ột record m ới vào b ản g a rtis ts ;
3 0 _ C h ư ớ n g 7 ; Làm v iệ c vái các cơ s ò dữ liệu và SQ L
Trang 29C h ư ớ n g 7: L à m v iệ c v ớ i c á c c d s ò dữ íiệu và S Q L 31
<?php
/ / attem pt database connection
Sm ysqli * new m ysqli('‘ localhost” , "user", “ pass” , "m usic” );
if {$m ysqli =s= talse) {
die("ERROR: Coulđ not connect, " m ysqli_connect_error());
1
/ / attem pt query execution
/ / add a new record
/ / output: “ New a rtist w ith id:7 added."
$sql = “ INSERT !NTO artisís (artist_nam e, artist_country) VALUES
N hư b ạ n sẽ th ấ y lập tr ìn h n ày không khác m ấy so với lập trìn h cần
th iế t để thực th i m ột query SELECT Thực tế, nó hơi đơn giỏn hơn bởi vì không có tậ p hợp k ế t quả để xử lý T ấ t cả những ^ cần là te s t giá trị t r ả về của phương thức query 0 và kiểm t r a xem query đ ã được thực th i th à n h công h a y không C ũng chú ý việc sử dụng một thuộc tín h mới, thuộc tín h 'in sert_ id ': thuộc tín h này t r ả về ID được tạo r a bởi query INSERT cuô’i cùng (chỉ hữu dụng n ếu b ản g m à INSERT xảy ra tro n g đó chứa m ột trường
tự động tăn g )
Còn về việc cập n h ậ t m ột record h iệ n có th ì sao? T ấ t cả nhữ ng ^ cần
th iế t là th a y đổi chuỗi query SQL:
<?php
/ / attem pt database connection
$m ysq li s new m ysq li(‘1ocalhost” , “ user", "pass", “ music” ):
if (Sm ysqli === false) I
Trang 303 2 _ C h ư ớ n g 7 ; Làm v iệ c v ó i c á c c d s ò d ữ liệ u v à S Q L
die(“ ERROR: Couíd not connect, “ , m ysqlLconnect_error()):
}
// attem pt query execution
/ / add a new record
/ / oưtput; "1 row (s) updated,”
$sql = “ UPDATE artists SET artist_nam e = ‘ Em inem ’ , a rtis t country = ‘US’ WHERE
K hi thự c th i m ột UPDATE hoặc DELETE, sô' h à n g bị ả n h hưởng bởi câu
lệ n h sẽ iược liíu t n ì tro n g thuộc tín h 'r,fĩ?ct.ed_rows' của đôì tượng MySQLi
L istin g trước m in h h ọ a thuộc tín h n ày đang được sử dụng
S ử dụng các cầu lệnh được chuẩn bị
T rong trư ờng hợp b ạ n cần thực th i m ột query cụ th ể n h iều lầ n với những giá tr ị k h á c n h au - ví dụ, m ột lo ạ t các câu lệ n h IN SE R T - se rv e r cơ sd dữ liệu M ySQL hỗ trợ các câu lệ n h được chuẩn bị (p re p ared sta te m e n t) cung cấp m ột phương tiệ n hiệu quả hơn để hoàn th à n h tá c vụ n à y so vời liên tục gọi phương thức $m ysqli->query ()
Về cơ b ản , m ột câu lệ n h được chuẩn bị là m ột khuôn m ẫu (tem plate) query SQL chứa các b iế n placeholder cho nhữ ng g iá tr ị cần được chèn hoặc được ch ỉn h sửa Câu lệ n h n à y được lưu trữ trê n d a ta b ase se rv e r v â được gọi
ra bao n h iêu lầ n tùy mức cần th iế t với các p laceholder được th a y t h ế b ằng nhữ ng g iá tr ị thực sự vào mỗi lầ n thực th i Bởi vì câu lệ n h được lưu tr ữ trê n
d a ta b ase serv er, m ột câu lệ n h được chuẩn bị thư ờng n h a n h hơn cho các
h o ạt động lô đòi hỏi chạy cùng m ột query SQL lặ p đi lặ p lạ i n h iều lầ n với nhữ ng g iá trị k h ác nhau
Trang 31C h ư ơ n g 7 : Làm việ c với các cơ sỏ dữ liệu và SQ L _ w
Hỏi chuyên gia
H ò i: Các câu lệ n h dược chuẩn bị m ang lại hiệu su ấ t tó t hơn n h ư t h ế nào?
Đ á p : T ro n g tiế n trìn h bình thường, mỗi lần m ột câu lệ n h SQL dược thự c th i tr ê n datab ase server, server phải p h â n tích m ă SQL và
k iểm tr a cú p h áp và cấu trúc của nó trước khi cho nó thực th i Với
m ột câu lệ n h được chuẩn bị, câu lện h SQL được lưu trữ tro n g m ột
vị tr í tạ m th ờ i trê n datab ase server và do dó chỉ cần được p h â n tíc h v à được hiệu lực hóa m ột lần Hơn nữa câu lệ n h mỗi lầ n được thực th i, chỉ các giá trị placeholder mới cần được chuyển đến
se rv e r th a y vì câu lện h h oàn chỉnh
Để th ấ y trự c tiế p m ột câu lện h được chuẩn bị, xem x é t sc rip t sau đây,
sc ríp t n ày ch èn n h iều b ảng vào cơ sở dữ liệu sử dụng m ột câu lệ n h được chuẩn bị với ex ten sio n MySQli của PHP:
<?php
/ / define values to be inserted
Ssongs = array(
array('Patience’ , 4, 3), array{‘ Beaưtiful W orld’ 4, 4), array(‘Shine’, 4, 4),
array{'Hũld On’, 4, 3),
);
/ / attem pt đatabase connection
$m ysqll = new m ysqli(“ localhost’’, “ user", "pass" "m usic” ):
if ($m ysqii === íaíse) I
d ie (“ ERROR: Could not connect “ m ysqli_connect_error());
I
/ / prepare query template
/ / execute multiple times
$sql = "INSERT INTO songs (songJitle, fk_song_artist, fk_song_rating)
VALUES (?, ?, ?)■’;
Trang 32I else ( echo “ ERROR: Coulđ not exfiCift3 qưery: $3Q| •' $ m y3 qli-> e rro f
)
I } else {
echo "ERROR: Could not prepare query; $sql “ $m ysqli->error' ì
/ ; close connection
$m ysqli->close();
?>
N hư listin g này m in h họa, sử dụng m ột câu lệ n h dược chuẩn bị đòi hỏi
m ột th ủ tục k h ác với th ủ tục m à b ạn đ ang th ấ y từ nhữ ng ví dụ trước
Để sư dụng m ột câu lệ n h được chuẩn bị trước tiê n cần p h ải đ ịn h nghĩa chuỗi query SQL m à sẽ được thực th i nhiều lần Chuỗi query n à y thường chứa m ột hoặc nhiều pìaceholder để biểu th ị b àn g các dấu hỏi (?) Các placeholder n ày sẽ được th a y th ế bằn g những giá tr ị thực sự vào mỗi lần thực th i câu lệ n h Chuỗi query với các placeholder của nó sau đó được chuyển đến phương thức p rep are 0 của đối tượng MySQLi, phưưng thưc này kiểm t r a SQL để tìm cáo lỗi v à trả về m ột dối tượng M yS Q L i.Stm tượnị; trưng cho câu lệ n h được chuẩn bị
Thực th i câu lệ n h được chuẩn bị bây giờ là m ột vấn đề thực h iệ n hai
h àn h động, thường là bên tro n g m ột vòng lặp:
1 L iên k ế t các giá trị với câu lệ n h được chuẩn bị Các giá tr ị m à cần được nội suy vào câu lệ n h p h ải được liên k ế t với các p laceholđer của chúng b ằn g phương thức bind_param () cùa đối tượng M ySQ LLStm Đối số đầu tiê n cho phương thức này ph ải là m ột tr ìn h tự chuỗi có ký
tự biểu th ị các kiểu dữ liệu của các giá trị cần được nội suy (s cho strin g , i cho in te g er, d cho double-precision n u m b er (sô' độ ch ín h xác kép)); sau dó đối số n ày thường được th eo sau bởi n h ữ n g giá tr ị thực
Trang 33sự T rong lis tin g trước chuỗi 'sii' biểu thị rằn g các giá trị cần dược
n ộ i suy vào câu lệ n h dược chuẩn bị sẽ, theo tr ìn h tự, là m ột kiểu chuỗi (tựa đề b ản nhạc), m ột kiểu số nguyên (khóa ngoại a rtis t), và
m ột kiểu sô' nguyên (khóa ngoại rating)
2 Thực th i câu lệ n h được chuẩn bị M ột khi các giá tr ị đ ã được liê n k ết với các p laceholder của chúng; câu lện h được chuẩn bị được thực th i
b ằn g việc gọi phương thức executeO của đôi tượng MySQLi_Smt Phương thứ c n ày th a y th ế các placeholder tro n g câu lệ n h dược chuẩn
bị b ằn g n h ữ n g giá trị thực sự và thực th i nó tr ê n server
Do đó, sử dụng m ột câu lệnh được chuẩn bị m ang lại nhữ ng lợi ích hiệu
su ấ t k h i b ạn cần thực th i cùng m ột câu lện h nhiều lần với chỉ các th a y đổi
th a y đổi vào m ỗi lầ n thực th i Hầu h ế t các cơ sở dữ liệu th ô n g dụng bao gồm MySQL, PostgreSQ L , O racle, v à InterB ase, hỗ trợ các câu lệ n h được chuẩn
bị và tín h n ă n g n ày n ên được sử dụng nơi có sẵn để làm cho các h o ạ t động
lô SQL hiệu quả hơn
Xử lý các lỗi
Nếu m ă cơ sở dữ liệu không làm việc như mong đợi, đừng lo lắ n g - extension M ySQLi có m ột chùm các hàm có th ể cho b ạn b iế t tạ i sao B ạn đã
th ấ y trực tiế p n h ữ n g h àm này ở những nơi khác n hau tro n g các listing
trước, như ng sau đây ià m ột d an h sách hoàn chỉnh:
# Thuộc tinh 'crror' của đối tượng MySQLi chứa thông báo ỉễi sau cũng
đìtợc tạo ra bởi daiabase sen/er.
9 Thuộc tinh 'ermo' cùa đối ucợngMvSQLi chừa mã lỗi sau cùng được trà I>ề hởi database semer.
u Hằm mysqìi_connect_error 0 trả về ihông báo lỗi được lạo ra bời nỗ lực kết r.ổi sau a ìn g (thất bại).
» H àm mysqỉi_connect_error o trả về mà lỗi dược tạo ra bời nỗ lực kết
nối sau củng (thất bại).
• • • • • • •
Thủ thuật
Đ ể làm cho ứng dụng m ạnh hơn trư ớc các lỗi và để làm cho dễ tìm kiếm và giải quyết các lỗ i hơn, bạn nên sử dụng các hàm xử lý lỗ i này m ộ t cách tự do bên tro n g mã.
C h ư ớ n g 7 : Làm v iệ c với các co sò dũ liệu v à SQL _ ^
Trang 343 6 C h U ò n g 7: Làm v iệ c v ớ i c á c Cd s ỏ d ữ liệ u v à S Q L
Thực hành 7.2: Thêm các nhân viên vào m ột ctf sở dữ liệu
Bây giờ k h i b ạn b iế t m ột số điểm cơ b ản về việc sử dụng extension MySQLi của PH P, hây áp dụng những p bạn đã học tro n g p h ầ n trước vào
m ột ứng dụng "thực tế", ứ n g dụng ở đây là m ột W eb form cho p hép m ột người đùng n h ậ p các tê n n h â n viên vào m ột cơ sở dữ ỉiệu n h â n viên dựa vào MySQL Các giá trị dược n h ậ p vào form được hiệu lực hóa sử dụng P H P và được biến đổi th à n h các record cơ sở dữ liệu sử dụng ex ten sio n P H P MySQÍii
Để b ắ t đầu xây dựng các ứng dụng này, đầu tiê n h ã y khởi động Clientdòng lệ n h MvSQL và khdi tạo m ột cơ sở dữ liệii rỗng:
Mysql> CREATÍ: DATABASE emplayees;
Querv OK, 1 row affecteđ {0 20 sec)
Tiếp theo, tạo m ột b ản g để chứa các rpcord p h â n v>ên:
rry s q b USE cm ployces;
Database changed
m ysqi> CREATE TABLE em ployees (
-> ỉd INT(4) NOT NULL AUTO.INCREMENT PRIMARY KEY, -> nam e VARCHAR(255) NŨT NULL,
•> designation VARCHAR(25S) NOT NULL
■> );
Quety OK, 0 rows affected (0.26 sec)
Bước tiế p theo là xây dirtig m ột Web form để chấp n h ậ n dữ iiệu n h â n viên - tro n g trư ờng hợp này, tê n và chức vụ của mỗi n h â n viên Sau k h i gởi,
bộ xữ lý íòrm sẽ kiểm t r a đầu vào v à nếu hợp lệ, tạ o m ộ t query IN SE R T để ghi nó saiig b à n g cơ sỏ dữ liệu đuợc tạ o d buớc trưức
Sau đây là sc rip t (employee.php):
<!DOCTYPE htm l PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
“ DTD/xhtm l1-transit!onal,dtcl” >
<htm l x m ln s *'’http;//w w w w 3.org/1999/xhtm r' xm l:lang="en" lang="en">
<head>
<íitle>Proiect 7-2: Ađding Employees to a Database</title>
<style type=” text/css” >
div#message { text-aligr»:center;
Trang 35C h ư ớ n g 7 : L à m việc v đ i cá c c ơ s ò dữ liệ u v à S Q L _ 3 7
margin*left;auto;
m argin-right:auto;
w idth:40% ; border: solid 2px green I
</style>
</head>
<body>
<h2>Project 7-2: Adding Employees to a Database</h2>
<h3>Add New Employee</h3>
<?php
/ / ií form submitted / / process íorm input
if (isset($_POST['submit’l) ) I / / attem pt connection to MySQL ơatabase
$m ysqli » new m ysqli("localhost", “ user” , “ pass", “ employees” );
if {empty($_POST('emp_name’])) { echo 'ERROR: Please enter a valiđ employee name’;
Trang 36$sq! = "INSERT INTO employees (ram e, designation)
VALUES {'$name’ , ‘$designation')” ;
if ($m ysqli->query($sql) true) { echo 'New empioyee record added W!th ID: ' $ m ysq li-
>inserLicl;
) else { echc “ ERROR; Could not execute query: $sql " $mysqli-
Trang 37C h ư ơ n g 7: Làm v iệ c với các cơ sỏ dũ iiệu và SQL 3 9
K h i sc rip t n ày được gọi ra, nó tạo một Web form có các trư ờ ng d à n h cho
tê n v à chức vụ của m ột n h â n viên H ìn h 7.4 m inh họa diện mạo của form ban dầư
7 - 2 : A 4 M tn q F rT o l0 T e c s to 4 0 « 4 a b « s * 'N 0 đ A d F ire C p ff* *iilMiMMNMiaMMlaMlvMMlMiiÉiÉBiVliaBM
Project 7-2: Aclỉỉỉng Employees tữ a Database
K h i form được gởi, sc rip t tiế n h à n h khởi tạo m ột đối tượng MySQLi mới
v à m ớ m ột n ố i k ế t đ ến d atab ase serv er MySQL Sau đó nó kiểm tr a các trường form để bảo đ ảm rằ n g chúng chứa những giá trị đầu vào hợp lệ Nếu hợp lệ, m ỗi g iá t r ị đầu vào được ’'sanitize" (kiểm t r a vệ sin h ) sử dụng phương thứ c escap e_ strin g 0 cùa đối tượng MSQLi, phương thức này tự động th o á t n h ữ n g ký tự đặc b iệ t tro n g đầu vào n hư là bước m ở đầu để chèn
nó vào cơ sở dữ liệu và sau đó được nội suy vào query INSERT, vôn được
th ự c t h i th ô n g q u a p h ư ơ n g th ứ c q u e ry 0 của đô'i tư ợ n g đ ể lưu n h ữ n g g iá t r ị
sang cơ sở dừ liệu, Các lỗi, nếu có sẽ được hiển th ị sử dụng thuộc tín h e rro r của đối tượng MySQLi
H ìn h 7.5 m in h h ọ a đầu r a k h i m ột record được th ê m th à n h công và h ìn h 7.6 m inh h ọ a đầu r a k h i m ột trường n h ập liệu không vượt qua việc hiệu lực hóa
Bây giờ, còn v ề việc ch in h sửa scrip t này sao cho ngoài việc cho phép
b ạn th ê m n h ữ n g n h â n viên m ới vào cơ sở dữ liệu, nó cũng h iể n th ị các record n h â n viên h iệ n có từ cơ sở dữ liệu th ì sao? Điều n ày k h ô n g khó cho lám - th ê m m ộ t lệ n h gọi k h ác vào phương thức query 0 , lầ n n ày với m ột query SELECT, v à xử lý tậ p hợp k ế t quả sử dụng m ộ t vòng lặp Sau đây là
m ã đươc ch ỉn h sửa:
Trang 384 0 C h ư ơ n g 7: Làm việc vdi các cơ sỏ dữ liệu và SQL
<!DOCTYPE htm l PUBLIC "-/m C /ỉữ ĩD XHTML 1.Ũ Transìtional//EN’‘
“ DTD/xhtm l1-transitional.dt(J’’>
<htm l xm lns=” http://w w w w 3.org/1999/xhtm [” xm l:lan9 ="en" lang="en” >
<head>
<title>Project 7-2; Adding Employees to a Database</title>
<style type=” text/css” >
div#Tiessage { text-a lign xe n te r;
1
ir.h e ad iiig { font-w eight: bolder;
<h2>Project 7-2; Adding Employees to a Database</h2>
<ti3>Add New Employee</h3>
<?php
/ / attem pt connection to MySQL database Smysqli = new m ysqli("localhost” , "user", "pass” , "em ployees” );
Trang 39Chướng 7: Làm việc với các cđ sò dữ liệu và SQL _ ^
if ($m ysqli === talse) I die("ERROR: Couid not connect to database “ mysqíLconnecí_error{));
}
/ / if form submiíted / / process íorm input
if (isset($_PŨST[‘subm it’])) 1 // open message block echo '<div id="message” >';
// retrieve and check input values SinputError = íalse;
if (em pty{$_POST['em p_nam e'])} I echo 'ERROR: Please enter a valid employee name';
/ / add values to đatâbase using INSERT query
if (SỉnpưtError '= frufì) {
$sql = “ INSERT INĨO empioyees (name, designation)
VALUES ('$rìame’ 'Sdesignation’) ’';
if ($mysqli->query($sql) írue) { echo 'New employee record added w ith ID: ‘ $m ysqli->insert_id;
I else { echo “ ERROR: Could not execute query: $sql ’■, $m ysqli->error;
}
Trang 4042 _ Chường 7: Làm việc với các Cd sò dữ íiệu và S Q L
// close message block echo '</rfiv>':
ecìio “ <tr class=VT.ea[jingV’> 'ji’';
echo “ <td>ID</td>\n’’;
echo " <tđ>Name</td>\n” ; ectio “ <td>Deslgnation</td>\n” ; echo “ < /tr> \n ” :
w hile{$row = $resu!t->fetch_object()) {
echo " <tr>\n";
echo " < t d > " $ ro w -> ict, '‘</td>\n’’ ; echo “ <td>" $ ro w -> n a m e '■</td>\n";
echo “ < t d > " $row->deslgnation "<Ad>\n";