queryExecute dalam CFML: parameter, cache dan metadata
Panduan queryExecute dalam CFML: parameter bernama dan berkedudukan, struct options dengan cfsqltype, null dan list, metadata hasil, transaksi dan caching.

Kandungan
- queryExecute dalam CFML: parameter, cache dan metadata
- queryExecute menggantikan cfquery
- Parameter bernama dan berkedudukan
- Struct options dan kekunci parameter
- Mengelak suntikan SQL dengan parameter
- Membaca metadata hasil
- Hasil kosong dan NULL
- queryExecute dalam transaksi
- Caching hasil dengan cachedWithin
- Bila caching berbahaya
- Jadual cfsqltype yang biasa digunakan
- Jadual perbandingan queryExecute lawan cfquery
- Soalan Lazim (FAQ)
- Sumber
- Senarai semak
queryExecute dalam CFML: parameter, cache dan metadata
queryExecute() ialah fungsi CFML yang menjalankan satu arahan SQL dan memulangkan objek query. Ia padanan moden bagi tag cfquery, tetapi ditulis sebagai fungsi cfscript, jadi ia boleh dipanggil di dalam fungsi, komponen dan gelung tanpa keluar dari blok skrip. Artikel ini merangkumi parameter, metadata hasil, transaksi dan caching, bersama perbandingan dengan cfquery.
queryExecute menggantikan cfquery
Gaya tag memerlukan anda keluar dari cfscript setiap kali mahu bertanya kepada pangkalan data, dan hasilnya disimpan dalam pemboleh ubah bernama. queryExecute() memulangkan query sebagai nilai, jadi anda boleh menyimpannya, memulangkannya dari fungsi, atau menghantarnya sebagai argumen. Contoh paling ringkas:
<cfscript>
q = queryExecute(
sql = "SELECT id, nama, emel FROM ahli WHERE aktif = :aktif ORDER BY id",
params = { aktif = { value = 1, cfsqltype = "cf_sql_integer" } },
options = { datasource = "mydb" }
);
writeOutput(q.recordCount);
</cfscript>
Dari segi prestasi, kedua-duanya menggunakan enjin pelaksanaan yang sama, jadi perbezaan kelajuan boleh diabaikan. Kelebihan queryExecute() ialah kemudahan penulisan, bukan kelajuan. Nama datasource seperti mydb bergantung pada tetapan anda; baca panduan konfigurasi datasource untuk mendaftarkannya.
Parameter bernama dan berkedudukan
Parameter bernama menggunakan titik bertindih di hadapan nama, dan params memadankan nama dengan struktur nilai:
<cfscript>
q = queryExecute(
sql = "SELECT id, nama FROM produk WHERE id IN (:id)",
params = { id = { value = "1,2", cfsqltype = "cf_sql_integer", list = true } },
options = { datasource = "mydb" }
);
</cfscript>
Parameter berkedudukan menggunakan tanda soal dan tatasusunan mengikut susunan:
<cfscript>
q = queryExecute(
sql = "SELECT id, nama FROM ahli WHERE id IN (?, ?)",
params = [
{ value = 1, cfsqltype = "cf_sql_integer" },
{ value = 2, cfsqltype = "cf_sql_integer" }
],
options = { datasource = "mydb" }
);
</cfscript>
Kedua-dua bentuk menghasilkan pertanyaan berparameter yang sama. Gunakan bentuk bernama apabila pertanyaan panjang supaya kod mendokumenkan dirinya sendiri, dan bentuk berkedudukan apabila senarai pendek.
Struct options dan kekunci parameter
Argumen ketiga ialah struktur options; kekunci yang paling kerap ialah datasource. Dalam params, setiap parameter membawa kunci tambahan selain value dan cfsqltype. null bernilai true menghantar SQL NULL dan mengabaikan value, maxlength menambah semakan panjang, dan list bernilai true memperluas nilai untuk operator IN:
<cfscript>
transaction {
queryExecute(
sql = "INSERT INTO pelanggan (id, nama, emel, telefon) VALUES (88, 'Uji', :emel, :tel)",
params = {
emel = { null = true, cfsqltype = "cf_sql_varchar" },
tel = { value = "0130000000", cfsqltype = "cf_sql_varchar", maxlength = 20 }
},
options = { datasource = "mydb" }
);
transactionRollback();
}
</cfscript>
Blok ini dibungkus transaksi dan digulingkan semula supaya selamat dijalankan berulang kali.
Mengelak suntikan SQL dengan parameter
Suntikan SQL berlaku apabila nilai pengguna dicantum ke dalam rentetan SQL. queryExecute() tidak menjadikan pertanyaan selamat secara automatik; ia selamat hanya apabila setiap nilai dinamik melalui params. Pertanyaan yang tidak selamat:
<cfscript>
nama = "' OR '1'='1";
q = queryExecute(
"SELECT * FROM ahli WHERE nama = '" & nama & "'",
[],
{ datasource = "mydb" }
);
writeOutput(q.recordCount); // 3, semua baris terbocor
</cfscript>
Versi selamat mengikat nilai sebagai parameter, dan input yang sama kini memulangkan sifar padanan:
<cfscript>
nama = "' OR '1'='1";
q = queryExecute(
sql = "SELECT * FROM ahli WHERE nama = :nama",
params = { nama = { value = nama, cfsqltype = "cf_sql_varchar" } },
options = { datasource = "mydb" }
);
writeOutput(q.recordCount); // 0, tiada padanan
</cfscript>
Peraturannya tidak berkompromi: apa-apa nilai dari pengguna mesti melalui params. Penjelasan penuh bersama jenis serangan yang dicegah ada dalam panduan mencegah suntikan SQL.
Membaca metadata hasil
Objek query membawa maklumat hasilnya sendiri tanpa pertanyaan kedua:
<cfscript>
q = queryExecute("SELECT id, nama FROM ahli WHERE id = 1", [], { datasource = "mydb" });
writeOutput(q.recordCount); // bilangan baris, 1
writeOutput(q.columnList); // "ID,NAMA"
meta = getMetaData(q); // tatasusunan metadata lajur
writeOutput(meta[1].name); // "ID"
writeOutput(meta[1].typeName); // "INTEGER"
</cfscript>
recordCount memberi bilangan baris dan columnList senarai nama lajur dipisahkan koma. getMetaData() memulangkan tatasusunan struktur dengan kekunci name, typeName dan isCaseSensitive. Tiada sifat columnMeta pada objek query, jadi gunakan getMetaData().
Hasil kosong dan NULL
Pertanyaan tanpa padanan tidak melempar ralat; ia memulangkan recordCount sifar, dan anda mesti menyemaknya sebelum membaca nilai:
<cfscript>
q = queryExecute("SELECT id, nama FROM ahli WHERE id = 9999", [], { datasource = "mydb" });
if (q.recordCount == 0) {
writeOutput("Tiada rekod dijumpai");
}
</cfscript>
NULL pula bermaksud tiada nilai, berbeza daripada rentetan kosong. Untuk menulis NULL, gunakan null = true dalam parameter. Untuk menapis lajur NULL, gunakan IS NULL dan bukan = NULL, kerana = NULL tidak pernah benar dalam kebanyakan pangkalan data.
queryExecute dalam transaksi
Transaksi mengumpulkan beberapa pertanyaan menjadi satu unit yang sama ada berjaya atau gagal sepenuhnya. Dalam cfscript, queryExecute() berfungsi dalam blok transaction, dan anda boleh membatalkan semuanya dengan transactionRollback():
<cfscript>
transaction {
queryExecute(
"UPDATE ahli SET aktif = 0 WHERE id = :id",
{ id = { value = 1, cfsqltype = "cf_sql_integer" } },
{ datasource = "mydb" }
);
transactionRollback();
}
</cfscript>
Jika pertanyaan dalam blok melempar pengecualian, Lucee menggulingkan transaksi secara automatik. Butiran komit, rollback dan savepoint ada dalam panduan cftransaction.
Caching hasil dengan cachedWithin
Apabila pertanyaan sama dijalankan berulang kali dan datanya jarang berubah, anda boleh menyimpan hasilnya supaya panggilan berikutnya tidak menyentuh pangkalan data:
<cfscript>
q = queryExecute(
sql = "SELECT id, nama FROM ahli WHERE id = 1",
params = [],
options = {
datasource = "mydb",
cachedwithin = createTimeSpan(0, 0, 0, 60),
result = "hasil"
}
);
writeOutput(hasil.cached); // false kali pertama, true selepas itu
</cfscript>
cachedwithin menerima tempoh masa dari createTimeSpan(), dan cachedafter menerima tarikh. Untuk cache dikira padanan, SQL, parameter, datasource dan nama query mesti sama. Struktur result membawa bendera cached dan executionTime dalam mikrosaat untuk mengesahkan cache berfungsi. Atribut lama seperti cache boolean, cacheId dan cacheName sudah lapuk atau tidak dilaksanakan dalam Lucee semasa; gunakan cachedwithin dan cachedafter.
Bila caching berbahaya
Caching menyimpan jawapan lama, dan jawapan lama menjadi salah sebaik sahaja data berubah. Untuk jadual yang kerap dikemas kini seperti stok atau status pesanan, caching berisiko memaparkan maklumat lapuk, lebih buruk daripada pertanyaan perlahan. Gunakan cachedwithin hanya untuk data yang berubah perlahan, seperti senarai negeri atau kategori produk, dan tetapkan tempoh pendek berbanding kekerapan perubahan. Jika anda menyambung kepada MySQL, semak panduan sambungan MySQL dengan Lucee sebelum memikirkan cache.
Jadual cfsqltype yang biasa digunakan
Menetapkan cfsqltype yang betul membantu Lucee menukar jenis dengan tepat dan menolak nilai yang salah jenis sebelum sampai ke pangkalan. Nilai boleh ditulis dengan atau tanpa awalan CF_SQL_.
| Jenis data | Kegunaan | Contoh nilai |
|---|---|---|
| varchar | Rentetan teks, jenis lalai | "thalhah" |
| integer | Nombor bulat | 42 |
| bigint | Integer besar | 9007199254740993 |
| decimal / double / money | Nombor perpuluhan atau kewangan | 19.90 |
| boolean / bit | Nilai benar atau salah | true |
| date / time / timestamp | Tarikh dan masa | createDate(2026,10,6) |
| binary / blob | Data binari | fileReadAsBinary(f) |
Jadual perbandingan queryExecute lawan cfquery
| Aspek | queryExecute | cfquery |
|---|---|---|
| Bentuk | Fungsi cfscript | Tag CFML |
| Hasil | Nilai dipulangkan | Pemboleh ubah bernama |
| Skop hasil | Anda tentukan tempat simpan | variables atau local |
| Parameter | Struktur params atau tatasusunan | Tag cfqueryparam |
| Dalam blok skrip | Boleh terus | Perlu keluar dari skrip |
| Prestasi | Enjin sama, tanpa overhed tag | Enjin sama |
Kedua-duanya bukan musuh. Kod gaya tag kekal dengan cfquery, kod cfscript memilih queryExecute(). Yang penting ialah konsisten dalam satu fail.
Soalan Lazim (FAQ)
Adakah queryExecute lebih pantas daripada cfquery?
Tidak secara bermakna. Kedua-duanya menggunakan enjin yang sama, jadi perbezaan kelajuan boleh diabaikan. Kelebihan queryExecute() ialah kemudahan penulisan dalam cfscript.
Bagaimana saya menghantar senarai nilai untuk operator IN?
Gunakan list = true pada parameter dengan nilai senarai atau tatasusunan, dan Lucee menaip setiap elemen mengikut cfsqltype.
Apakah cara betul untuk menulis NULL ke pangkalan data?
Gunakan null = true dalam struktur parameter. Lucee menghantar SQL NULL dan mengabaikan kekunci value.
Bolehkah queryExecute menjadikan pertanyaan saya selamat daripada suntikan SQL?
Tidak secara automatik. Ia selamat hanya apabila setiap nilai dinamik dihantar melalui params. Cantuman nilai ke dalam rentetan masih terdedah.
Atribut cache mana yang sepatutnya saya guna?
Gunakan cachedwithin dengan createTimeSpan(), atau cachedafter dengan tarikh. Atribut cache boolean, cacheId dan cacheName sudah lapuk atau tidak dilaksanakan.
Sumber
- queryExecute() - Lucee Documentation
- Query tag - Lucee Documentation
- Query Parameterization Cheat Sheet - OWASP
Senarai semak
- Gunakan
queryExecute()untuk cfscript dancfqueryuntuk gaya tag, konsisten dalam satu fail. - Hantar setiap nilai dinamik melalui
params, tidak pernah dicantum ke dalam rentetan SQL. - Nyatakan
cfsqltypeyang sepadan dengan jenis lajur, dan gunakanlist,nullsertamaxlengthmengikut keperluan. - Semak
recordCountsebelum membaca nilai, dan gunakangetMetaData()untuk metadata lajur. - Gunakan
cachedwithinhanya untuk data yang jarang berubah, dan sahkan dengan benderacachedpada structresult.