EXECUTE
câu lệnh phải được cung cấp một danh sách cố định các đối số, vì vậy bạn sẽ phải chuẩn bị và thực hiện câu lệnh trong IF / THEN / ELSE
khối.
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;
Tôi không biết bất kỳ cách nào để giải quyết vấn đề này trong phạm vi giới hạn của ngôn ngữ thủ tục được lưu trữ MySQL. Đối với tôi, đó là một lý do chính đáng khác để không sử dụng SQL động trong các thủ tục được lưu trữ.
Re nhận xét của bạn:
Tôi hiểu rồi ... bạn có thể sử dụng CASE tuyên bố
thay vì IF / THEN / ELSE
, nhưng bạn thực sự có 2 =128 trường hợp khác nhau có thể xảy ra cho các chuỗi truy vấn, bởi vì tôi cho rằng bất kỳ mô-đun nào trong số 7 mô-đun đó đều có thể được tìm kiếm hoặc không.
Một giải pháp thay thế cho phép bạn sử dụng các tham số truy vấn là quên sử dụng UNION
và thay vào đó, hãy viết thủ tục theo cách chạy tối đa 7 SELECT
riêng biệt truy vấn và trả về tất cả chúng dưới dạng nhiều bộ kết quả . Đó là một cái gì đó mà các thủ tục được lưu trữ nhằm mục đích làm. Nhưng bạn phải viết mã trong lớp PHP của mình để lần lượt tìm nạp từng tập kết quả. Đó là, lặp qua các tập kết quả và trong vòng lặp đó, lặp qua các hàng của tập kết quả hiện tại. Xem ví dụ tại PDO ::nextRowset ()
hoặc mysqli ::next_result ()
.
Không, bạn sẽ không an toàn nếu làm vậy! Sử dụng tham số truy vấn trong PHP để chuyển một chuỗi tới CALL WEBSITE_mainSearch (?)
là vô ích để bảo vệ chống lại việc tiêm SQL, nếu sau đó bạn nối giá trị tham số đó vào một chuỗi khác bên trong thủ tục và thực hiện phân tích cú pháp và thực thi SQL động. Việc sử dụng các tham số truy vấn không làm cho các giá trị tham số trở nên "an toàn", chúng chỉ tách các giá trị đó khỏi giai đoạn phân tích cú pháp SQL.
Bạn sẽ an toàn hơn nếu sử dụng hàm tích hợp sẵn của MySQL QUOTE ()
khi nối các chuỗi. QUOTE ()
thoát các ký tự đặc biệt, giống như mysql_real_escape_string ()
. Ngoại trừ nó hơi khác một chút, vì nó cũng tạo ra các dấu nháy đơn phân cách chuỗi, như PDO ::quote ()
không.
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),')') ;
Cập nhật:một giải pháp thay thế khác:sử dụng UNION
để thêm nhiều truy vấn con hơn và giữ số lượng mô-đun. Sau đó, sử dụng CASE
để thực hiện truy vấn đã chuẩn bị với một số tham số khác nhau dựa trên tổng số tích lũy.
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;