EXECUTE
pernyataan harus diberikan daftar argumen yang tetap, jadi Anda harus menyiapkan dan jalankan pernyataan dalam IF/THEN/ELSE
blokir.
IF articlesModule = 1 THEN
SET @query = ... UNION ...
PREPARE stmt FROM @query;
EXECUTE stmt USING @searchWordIn, @searchWordIn, @searchWordIn, @searchWordIn;
ELSE
SET @query = ...; /* no UNION */
PREPARE stmt FROM @query;
EXECUTE stmt USING @searchWordIn, @searchWordIn;
END IF;
Saya tidak tahu cara untuk menyelesaikan ini dalam lingkup terbatas bahasa prosedur tersimpan MySQL. Bagi saya, ini adalah alasan bagus lainnya untuk tidak menggunakan SQL dinamis dalam prosedur tersimpan.
Kembali komentar Anda:
Begitu... Anda bisa menggunakan CASE
pernyataan
bukannya IF/THEN/ELSE
, tetapi Anda sebenarnya memiliki 2 =128 kemungkinan kasus berbeda untuk string kueri, karena saya menganggap salah satu dari 7 modul tersebut dapat ditelusuri atau tidak.
Alternatif yang memungkinkan Anda menggunakan parameter kueri adalah melupakan penggunaan UNION
, dan sebagai gantinya tulis prosedur sedemikian rupa sehingga menjalankan hingga 7 SELECT
. yang terpisah kueri dan mengembalikan semuanya sebagai beberapa kumpulan hasil . Itu adalah sesuatu yang dimaksudkan untuk dilakukan oleh prosedur tersimpan. Tetapi Anda harus menulis kode di lapisan PHP Anda untuk mengambil setiap hasil yang ditetapkan secara bergantian. Artinya, loop di atas set hasil, dan di dalam loop itu, loop di atas baris set hasil saat ini. Lihat contoh di PDO::nextRowset()
atau mysqli::next_result()
.
Tidak, Anda tidak aman jika melakukannya! Menggunakan parameter kueri di PHP untuk meneruskan string ke CALL WEBSITE_mainSearch(?)
tidak berguna untuk melindungi dari injeksi SQL, jika Anda kemudian menggabungkan nilai parameter itu ke string lain di dalam prosedur dan melakukan parse-and-execute SQL dinamis. Menggunakan parameter kueri tidak membuat nilai parameter "aman", melainkan hanya memisahkan nilai tersebut dari fase penguraian SQL.
Anda lebih aman jika menggunakan fungsi bawaan MySQL KUTIPAN()
saat menggabungkan string. QUOTE()
tidak keluar dari karakter khusus, seperti mysql_real_escape_string()
. Kecuali itu sedikit berbeda, karena itu juga menghasilkan tanda kutip tunggal yang membatasi string, seperti PDO::quote()
tidak.
SET @query = CONCAT(@query, 'SELECT blockName AS itemName, blockPath AS seoName,
blockID AS itemID, MATCH(blockName, blockBody) AGAINST (',
QUOTE(searchWordIn), ') AS relevance, \'block\' AS itemType
FROM content_blocks WHERE MATCH(blockName, blockBody) AGAINST (',
QUOTE(searchWordIn),')') ;
Pembaruan:satu alternatif lagi:gunakan UNION
untuk menambahkan lebih banyak subkueri, dan menghitung jumlah modul. Kemudian gunakan CASE
untuk mengeksekusi kueri yang disiapkan dengan jumlah parameter yang berbeda berdasarkan jumlah akumulasi.
SET @n = 0;
IF articlesModule = 1 THEN
SET @query = ... UNION ...
SET @n = @n+1;
END IF;
IF newsModule = 1 THEN
SET @query = ... UNION ...
SET @n = @n+1;
END IF;
... and similar for the other 5 modules ...
PREPARE stmt FROM @query;
CASE @n
WHEN 1:
EXECUTE stmt USING @searchWordIn, @searchWordIn;
WHEN 2:
EXECUTE stmt USING @searchWordIn, @searchWordIn, @searchWordIn, @searchWordIn;
WHEN 3:
EXECUTE stmt USING @searchWordIn, @searchWordIn, @searchWordIn, @searchWordIn,
@searchWordIn, @searchWordIn;
WHEN 4:
EXECUTE stmt USING @searchWordIn, @searchWordIn, @searchWordIn, @searchWordIn,
@searchWordIn, @searchWordIn, @searchWordIn, @searchWordIn;
WHEN 5:
EXECUTE stmt USING @searchWordIn, @searchWordIn, @searchWordIn, @searchWordIn,
@searchWordIn, @searchWordIn, @searchWordIn, @searchWordIn,
@searchWordIn, @searchWordIn;
WHEN 6:
EXECUTE stmt USING @searchWordIn, @searchWordIn, @searchWordIn, @searchWordIn,
@searchWordIn, @searchWordIn, @searchWordIn, @searchWordIn,
@searchWordIn, @searchWordIn, @searchWordIn, @searchWordIn;
WHEN 7:
EXECUTE stmt USING @searchWordIn, @searchWordIn, @searchWordIn, @searchWordIn,
@searchWordIn, @searchWordIn, @searchWordIn, @searchWordIn,
@searchWordIn, @searchWordIn, @searchWordIn, @searchWordIn,
@searchWordIn, @searchWordIn;
END;