我需要构建一个动态的SQL子句,我看到一些只使用case的例子,但由于某些原因我的源代码不起作用。
有人可以帮助我吗?
create procedure sp_test(in iduser bigint, in name varchar(50), in company varchar(50), in city varchar(50), in profession varchar(50))
begin
if not(name is null) then
begin
set name = '%' + lower(name) + '%';
end;
end if;
if not(company is null) then
begin
set company = '%' + lower(company) + '%';
end;
end if;
if not(city is null) then
begin
set city = '%' + lower(city) + '%';
end;
end if;
if not(profession is null) then
begin
set profession = '%' + lower(profession) + '%';
end;
end if;
select
usr.id_user,
usr.ds_icon,
usr.nm_user,
usr.ds_slug,
usr.ds_title,
usr.nm_company
from
tbl_user usr
left join tbl_profession pro on (pro.id_profession = usr.id_profession)
left join tbl_resume res on (res.id_user = usr.id_user)
where
(usr.ds_activation is null) and
usr.id_user <> iduser and
usr.id_user not in (select id_friend from tbl_user_friend where id_user = iduser) and
usr.id_user not in (select id_user from tbl_user_friend where id_friend = iduser) and
usr.id_user not in (select id_friend from tbl_user_friend_not_suggest where id_user = iduser) and
case when not(name is null) then
lower (usr.nm_user) like lower(name) or
end
case when not(company is null) then
lower (usr.nm_company) like lower(company) or
end
case when not(profession is null) then
lower (pro.nm_profession) like lower(profession) or
end
case when not(city is null) then
lower (res.ds_city) like lower(city) or
end
1 = 1
order by
usr.nm_user
limit
0,20
;
end$$
我想这个想法是正确的,我准备使用%value%
过滤字符串以在SQL命令上使用它,并在检查值是否为null之后,我想将它添加到WHERE子句中。
答案 0 :(得分:0)
好的,没有真正看到你的代码做了什么,但你最有可能找到的是预处理语句:你不能在存储过程中连接一个sql,因为那是编译代码,但你可以连接一个字符串并放置它在准备语句中+执行该语句。
简短的例子:
SET @sql = CONCAT('SELECT some_columns FROM table
WHERE a=b',
@your_generated_where_statement_parts);
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
答案 1 :(得分:0)
SQL是一种声明性语言。您告诉服务器您要查找的内容,而不是如何找到它。查询优化器的任务是确定如何查找行。
简单的解决方案是让查询优化器负责优化不必要的条件,它会自动执行
WHERE
... AND
(name IS NULL OR usr.nm_user LIKE CONCAT('%',name,'%') AND
(company IS NULL OR usr.nm_company LIKE CONCAT('%',company,'%') AND
... -- repeat for other variables
在准备查询计划时,优化程序的工作是确定如何以尽可能少的工作实际找到所需的行。
由于name
是在查询执行期间无法更改的变量,因此优化程序将其解析为常量。由于name
是常量,因此name IS NULL
是一个常量表达式,可以在查询执行开始之前解析为true或false。
如果为true,则OR
表达式始终为true,因此无需解析表达式CONCAT('%',name,'%')
,因此将其优化掉。
如果为false,则将表达式CONCAT('%',name,'%')
解析为常量,并将每行与其进行比较。不需要为每一行处理CONCAT()
,因为值也不会在行之间发生变化,因此无需提前执行此操作。
因此,无需重写您的查询。只需表达一个逻辑上有效的表达式,优化器将完成剩下的工作。
此外,默认情况下,字符排序规则不区分大小写,因此除非您更改此字符,否则LOWER()
是不必要的。
并且,如上所述,您之前用于将%
连接到变量的块也是不必要的,因为我们只有在需要时才能在WHERE
中执行这些操作(当变量不是时)空)。