我正在为我的业务目录应用程序编写存储过程。浏览列表表单有一个选择菜单,允许用户按特定字段订购列表。如果sortField参数不为null,则应按sortOrder(asc或desc)参数指定的顺序按该列排序。如果指定了sortField参数,那么将始终使用它指定sortOrder字段。我收到的错误是"Check the syntax near IF sortField != NUL .... ELSE ORDER BY l.lis"
这是我的问题:
CREATE PROCEDURE `ListingsRetrieve` (
IN listingId INT(15),
IN categoryID INT(15),
IN regionId INT(15),
IN memberId INT(15),
IN keywords VARCHAR(250),
IN filterDistance INT(3),
IN latitude DOUBLE,
IN longitude DOUBLE,
IN sortField VARCHAR(16),
IN sortOrder VARCHAR(16),
IN page INT(15),
IN perPage INT(3)
)
BEGIN
SELECT
l.listing_id AS id, l.member_id, l.category_id, l.banner_id, l.thumbnail_id, l.logo_id, l.title AS listing_title, l.description, l.address, l.city, l.zip, UNIX_TIMESTAMP(l.date_submitted) AS date_submitted, l.latitude, l.longitude,l.phone,l.website, l.phone, l.contact_email, l.facebook_url, l.twitter_url, l.slug AS listing_slug,
l.sunday_open, l.sunday_close, l.monday_open, l.monday_close, l.tuesday_open, l.tuesday_close, l.wednesday_open, l.wednesday_close, l.thursday_open, l.thursday_close, l.friday_open, l.friday_close, l.saturday_open, l.saturday_close,
( 6371 * acos( cos( radians(latitude) ) * cos( radians( l.latitude) ) * cos( radians( l.longitude ) - radians(longitude) ) + sin( radians(latitude) ) * sin( radians( l.latitude ) ) ) ) AS distance,
c.category_id AS cat_id, c.slug AS cat_slug, c.icon AS cat_icon,
r.region_id AS region_id, r.title AS region_title, r.slug AS region_slug, (FLOOR((AVG(rev.score)) * 2) / 2) AS stars,
(SELECT
AVG(FLOOR(AVG(rev.score) * 2) / 2)
FROM
reviews AS r
INNER JOIN
listings AS l ON r.review_listing_id = l.listing_id
) as totalAvg,
((COUNT(rev.review_id) / (COUNT(rev.review_id)+5)) * (FLOOR((AVG(rev.score)) * 2) / 2) + (5 / (COUNT(rev.review_id)+5)) * AVG(rev.score)) AS rating,
b.attachment_id AS banner_id, b.file_path AS banner_path,
t.attachment_id AS thumbnail_id, t.file_path AS thumbnail_path,
lgo.attachment_id AS logo_id, lgo.file_path AS logo_path,
CONCAT_WS('/', r.slug, c.slug, l.slug, l.listing_id) AS listing_uri
FROM listings AS l
LEFT JOIN categories AS c ON l.category_id = c.category_id
LEFT JOIN regions AS r ON l.region_id = r.region_id
LEFT JOIN reviews AS rev ON l.listing_id = rev.review_listing_id
LEFT JOIN attachments AS b ON l.banner_id = b.attachment_id
LEFT JOIN attachments AS t ON l.thumbnail_id = t.attachment_id
LEFT JOIN attachments AS lgo ON l.logo_id = lgo.attachment_id
WHERE (listingId IS NULL or l.listing_id = listingId) AND
(categoryId IS NULL or l.category_id = categoryId) AND
(regionId IS NULL or l.region_id = regionId) AND
(memberId IS NULL or l.member_id = memberId) AND
(keywords IS NULL or MATCH(l.title,l.description,r.title,c.title) AGAINST(keywords) AND
(filterDistance IS NULL OR distance = filterDistance)
IF sortField != NULL THEN
ORDER BY sortField sortOrder
ELSE
ORDER BY l.listing_id DESC
IF listingId != NULL THEN
LIMIT 1;
ELSE
LIMIT (IF page > 1 THEN ((page - 1) * perPage) ELSE 0),perPage
END IF;
END //
答案 0 :(得分:0)
您不能以这种方式构建动态查询。
您可以将查询组成一个变量中的字符串,然后使用该字符串prepare a statement并执行它:
# Put the common part of the query in a string. Take care to not include
# the variable names but use CONCAT() to join their *values* into the SQL syntax.
# Or, if possible, replace them with question marks (?) and pass
# them to EXECUTE as parameter values (see below or read the documentation)
SET @sql = 'SELECT l.listing_id AS id, ... OR distance = filterDistance)';
# Add the ORDER BY clause
IF sortField IS NOT NULL THEN
SET @sql = CONCAT(@sql, ' ORDER BY ', sortField, ' ', sortOrder);
ELSE
SET @sql = CONCAT(@sql, ' ORDER BY l.listing_id DESC');
END IF;
# Add the LIMIT clause; it uses parameters
SET @sql = CONCAT(@sql, ' LIMIT ?, ?');
# Compute the values of parameters to use in the LIMIT clause
IF listingId IS NOT NULL THEN
SET @start = 1;
SET @limit = 1;
ELSE
# Make sure @start is not negative
SET @start = MAX(0, (page - 1) * perPage);
SET @limit = perPage;
END IF;
# Use @sql to prepare a statement
PREPARE stmt1 FROM @sql;
# Run the prepared statement with parameters
EXECUTE stmt1 USING @start, @limit;
# Can run the prepared statement again, with different parameters if needed
# ...
# Remove the prepared statement when it is not needed any more
DEALLOCATE PREPARE stmt1;