Query of Queries (QoQ) dalam CFML
Belajar Query of Queries (QoQ) dalam CFML: sintaks dbtype=query, tapis dan agregat hasil pertanyaan dalam memori, beza enjin asli dan HSQLDB, dan perubahan 7.1.

Kandungan
- Query of Queries (QoQ) dalam CFML
- Apa Itu Query of Queries
- Dua Syarat Utama: dbtype="query"
- Menapis Hasil Pertanyaan Sedia Ada
- Mengagregat dan Mengisih dalam Memori
- Enjin Asli dan HSQLDB
- Perubahan Lucee 7.1: Pemilihan Enjin dan Sensitiviti Huruf
- Susunan NULL dalam ORDER BY
- Bila Lebih Baik Guna SQL Terus
- Soalan Lazim (FAQ)
- Sumber
Query of Queries (QoQ) dalam CFML
Penulis: Thalhah · Tarikh: 16 Oktober 2026
Query of Queries (QoQ) ialah teknik menjalankan pertanyaan SQL terhadap objek pertanyaan yang sudah wujud dalam memori, tanpa panggilan kedua ke pangkalan data. Ia berguna untuk menapis, mengisih dan mengagregat hasil yang telah dimuatkan, malah boleh menggabungkan data daripada beberapa pangkalan data yang berbeza. Artikel ini menerangkan sintaks dbtype="query", perbezaan enjin asli lawan HSQLDB, dan perubahan yang dibawa Lucee 7.1.
Apa Itu Query of Queries
QoQ membolehkan anda menjadikan satu pertanyaan sebagai sumber bagi pertanyaan lain. Hasil pertanyaan pertama kekal dalam memori sebagai objek, dan pertanyaan kedua membaca objek itu seolah-olah ia sebuah jadual. Dokumentasi Lucee menyifatkan QoQ sebagai teknik menjalankan semula pertanyaan (re-querying) yang sedia ada tanpa perjalanan semula ke pangkalan data, dan ia membolehkan anda menggabungkan pertanyaan daripada pangkalan data yang berbeza secara dinamik.
Senario biasa ialah memuatkan satu set rekod besar daripada pangkalan data, kemudian membentuk beberapa paparan berbeza daripada set yang sama: senarai penuh, senarai ditapis mengikut kategori, dan ringkasan agregat. Dengan QoQ, anda memuatkan data sekali sahaja dan memproses paparan tambahan di dalam memori, menjimatkan panggilan pangkalan data.
Dua Syarat Utama: dbtype="query"
QoQ memerlukan dua perkara. Pertama, atribut dbtype="query" memberitahu Lucee bahawa sumbernya ialah objek pertanyaan, bukan pangkalan data. Kedua, klausa FROM merujuk nama pemboleh ubah pertanyaan sumber dan bukannya nama jadual sebenar.
<cfquery name="sourceQry" datasource="mydsn">
SELECT * FROM my_db_table
</cfquery>
<cfquery name="newQry" dbtype="query">
SELECT * FROM sourceQry
</cfquery>
Contoh di atas sekadar menyalin pertanyaan sumber, tetapi ia menunjukkan dua keperluan asas QoQ dengan jelas.
Menapis Hasil Pertanyaan Sedia Ada
Kegunaan paling lazim QoQ ialah menapis hasil tanpa menyentuh pangkalan data semula. Katakan anda memuatkan senarai orang dan mahu mengecualikan mereka yang bawah umur 18 tahun atau melebihi 90 tahun:
<cfquery name="filteredQry" dbtype="query">
SELECT Name, Age, Location
FROM myQuery
WHERE Age >= 18 AND Age <= 90
</cfquery>
Gaya skrip mencapai perkara yang sama melalui queryExecute dengan opsyen dbtype dalam struktur pilihan:
var dewasa = queryExecute(
sql = "SELECT Name, Age FROM myQuery WHERE Age >= 18",
options = { dbtype = "query" }
);
Dalam kedua-dua gaya, tiada panggilan pangkalan data berlaku pada pertanyaan kedua. Untuk asas menulis pertanyaan pangkalan data yang selamat, baca panduan cfquery dan cfqueryparam.
Mengagregat dan Mengisih dalam Memori
Enjin asli Lucee menyokong subset ANSI SQL92 yang merangkumi GROUP BY, HAVING, ORDER BY, DISTINCT, UNION, IN, LIKE, BETWEEN dan operator perbandingan. Fungsi agregat seperti COUNT, SUM, AVG, MIN dan MAX turut disokong, bersama fungsi rentetan seperti UPPER, LOWER, TRIM dan LENGTH.
<cfquery name="ringkasan" dbtype="query">
SELECT Location, COUNT(*) AS bilangan, AVG(Age) AS purata
FROM myQuery
GROUP BY Location
HAVING COUNT(*) > 1
ORDER BY Location ASC
</cfquery>
Jadual berikut meringkaskan sebahagian daripada apa yang tersedia dalam enjin asli:
| Kategori | Fungsi atau operator |
|---|---|
| Agregat | COUNT, SUM, AVG, MIN, MAX |
| Rentetan | UPPER, LOWER, TRIM, LENGTH, CONCAT |
| Penukaran jenis | CAST, CONVERT |
| Utiliti | COALESCE, ISNULL, RAND |
| Klausa | SELECT, FROM, WHERE, GROUP BY, HAVING, ORDER BY, UNION |
Enjin Asli dan HSQLDB
Lucee menggunakan dua enjin untuk QoQ. Enjin asli ialah pelaksanaan SQL pantas milik Lucee yang merangkumi subset ANSI92 asas. Jika pertanyaan terlalu kompleks untuk enjin asli, Lucee jatuh balik kepada HSQLDB, sebuah pangkalan data dalam memori yang lebih lengkap tetapi lebih perlahan kerana pertanyaan sumber dimuatkan secara dinamik ke dalamnya.
Perbezaan ini penting kerana sintaks yang berfungsi pada satu enjin mungkin tidak wujud pada enjin lain. Pertanyaan mudah seperti SELECT, WHERE dan ORDER BY hampir selalu ditangani enjin asli, manakala SQL lanjutan mungkin memerlukan HSQLDB. Sejak Lucee 7.1, HSQLDB menggunakan kolam tika pangkalan data yang terpencil dan bukannya satu tika segerak, yang meningkatkan daya pemprosesan di bawah beban serentak. Saiz kolam lalai ialah yang lebih kecil antara bilangan teras CPU dan 8, dan boleh dilaras melalui sifat sistem lucee.qoq.hsqldb.poolsize.
Perubahan Lucee 7.1: Pemilihan Enjin dan Sensitiviti Huruf
Sejak Lucee 7.1, anda boleh memilih enjin secara eksplisit melalui opsyen engine. Nilainya ialah auto (enjin asli dahulu, jatuh balik ke HSQLDB), native (enjin asli sahaja, ralat jika SQL tidak disokong), atau hsqldb (terus ke HSQLDB tanpa mencuba enjin asli).
Lucee 7.1 juga menambah opsyen caseSensitive. Secara lalai, perbandingan rentetan QoQ seperti LIKE, =, <> dan IN adalah tidak peka huruf, jadi WHERE name LIKE '%mod%' memadankan kedua-dua Modica dan mod-lower. Ini berbeza daripada Adobe ColdFusion yang peka huruf sejak ColdFusion MX 7.
var hasil = queryExecute(
"SELECT name FROM qry WHERE name LIKE '%mod%'",
{},
{ dbtype = { type = "query", caseSensitive = true, engine = "native" } }
);
Kedua-dua opsyen ini boleh ditetapkan pada tiga peringkat. Peringkat paling khusus ialah setiap pertanyaan melalui struktur dbtype, diikuti peringkat aplikasi melalui this.query.qoq dalam Application.cfc, dan akhirnya seluruh pelayan melalui sifat sistem seperti lucee.qoq.caseSensitive=true. Tetapan yang lebih khusus mengatasi yang lebih umum. Untuk konteks konfigurasi aplikasi, baca panduan Application.cfc.
Susunan NULL dalam ORDER BY
Satu lagi perubahan Lucee 7.1 menyelaraskan kedudukan NULL antara kedua-dua enjin. Sebelum ini, enjin HSQLDB meletakkan NULL dahulu tanpa mengira arah ASC atau DESC, manakala enjin asli dan Adobe ColdFusion menganggap NULL sebagai nilai rendah, iaitu dahulu dalam ASC dan akhir dalam DESC. Lucee 7.1 menjadikan kedua-dua enjin bersetuju pada kedudukan yang sama.
Jika kod anda bergantung pada tingkah laku lama, anda boleh memilih keluar dengan lucee.qoq.hsqldb.orderBy.nullsLastInDesc=false. Lucee 7.1 juga mengubah cara NULL dirawat dalam pencantuman rentetan: NULL kini dianggap rentetan kosong dalam || dan CONCAT, sejajar dengan Adobe ColdFusion, Oracle dan SQL Server. Perubahan sebegini ialah sebab penting untuk menyemak panduan Lucee 7 dan masa depan sebelum menaik taraf.
Bila Lebih Baik Guna SQL Terus
QoQ bukan pengganti SQL sebenar. Ia berjalan dalam memori JVM, jadi set data yang sangat besar boleh menjadi mahal dari segi masa dan ingatan. Peraturan am: jika penapisan boleh dilakukan oleh pangkalan data dalam pertanyaan asal, lakukan di sana, dan simpan QoQ untuk kes di mana anda sudah memuatkan data dan perlu membentuknya semula tanpa perjalanan tambahan.
QoQ juga bernilai untuk menggabungkan data daripada pertanyaan yang tidak boleh dicantum pada peringkat pangkalan data, contohnya hasil daripada dua datasource berbeza. Untuk menyediakan sambungan pangkalan data, rujuk konfigurasi datasource. Jika anda lebih banyak bekerja dengan objek berbanding pertanyaan mentah, pengenalan ORM Hibernate menerangkan pendekatan alternatif.
Soalan Lazim (FAQ)
Apakah beza QoQ dengan pertanyaan pangkalan data biasa?
Pertanyaan biasa menghantar SQL ke pangkalan data, manakala QoQ menjalankan SQL terhadap objek pertanyaan yang sudah ada dalam memori tanpa menghubungi pangkalan data.
Bagaimana saya mengaktifkan QoQ?
Gunakan atribut dbtype="query" pada tag cfquery, atau hantar options = { dbtype = "query" } kepada queryExecute, dan rujuk nama pemboleh ubah pertanyaan sumber dalam klausa FROM.
Adakah QoQ peka huruf?
Secara lalai tidak, tetapi sejak Lucee 7.1 anda boleh mengaktifkan sensitiviti huruf melalui opsyen caseSensitive.
Enjin mana yang digunakan Lucee untuk QoQ?
Lucee mencuba enjin asli dahulu dan jatuh balik kepada HSQLDB jika SQL terlalu kompleks. Sejak Lucee 7.1 anda boleh memilih enjin secara eksplisit dengan opsyen engine.
Bilakah saya tidak patut menggunakan QoQ?
Apabila set data besar dan penapisan boleh dilakukan oleh pangkalan data dalam pertanyaan asal, kerana QoQ berjalan dalam memori JVM dan boleh menjadi perlahan untuk data yang banyak.