在我的数据库中有一个名为的表author,其中有4列:
例如,用户正在搜索Edgar Allan Poe.在我们的表中,Edgar Allan Poe保存为:firstName - Edgar,middleName - Allan和lastName - Poe.这个查询非常简单.但是如何编写一个不仅与Edgar Allan Poe相匹配的查询,还包括与Poe Allan Edgar,Edgar Poe,Allan Poe,Edgar Allan,Allan Edgar Poe匹配的查询,而不是自己编写所有这些可能的组合?此外,当用户搜索时,他/她完全搜索"Edgar Allan Poe"或"Poe Allan Edgar",而不是在单独的字段中搜索.
请尝试以下操作...
DROP PROCEDURE IF EXISTS SimilarNames;
DELIMITER //
CREATE PROCEDURE SimilarNames( authorFullName VARCHAR( 250 ) )
BEGIN
SET @authorFullNameCommad = CONCAT( '\'',
REPLACE( authorFullName,
' ',
'\', \'' ),
'\'' );
SET @selectStatementString := CONCAT( "SELECT authorID,",
" firstName,",
" middleName,",
" lastName ",
"FROM author ",
"WHERE ( ( firstName IN ( ",
@authorFullNameCommad,
" ) ) + ( middleName IN ( ",
@authorFullNameCommad,
" ) ) + ( lastName IN ( ",
@authorFullNameCommad,
" ) ) ) >=2;" );
PREPARE selectStatement FROM @selectStatementString;
EXECUTE selectStatement;
DEALLOCATE PREPARE selectStatement;
END //
DELIMITER ;
CALL SimilarNames( 'Edgar Allan Poe' );
Run Code Online (Sandbox Code Playgroud)
该解决方案首先创建一个PROCEDURE被调用的SimilarNames(在DROPping 任何现有版本之后PROCEDURE)。这PROCEDURE会将传递给它的名称(例如'Edgar Allan Poe')存储在参数变量中authorFullName。
一旦开始,PROCEDURE首先将字符串转换为Edgar Allan Poe并将'Edgar', 'Allan', 'Poe'其存储在变量 中@authorFullNameCommad。
然后该CONCAT()函数用于形成将产生结果的 SQL 语句文本。以下语句是authorFullName在哪里生成并存储在...Edgar Allan Poe@selectStatementString
SELECT authorID,
firstName,
middleName,
lastName
FROM author
WHERE ( ( firstName IN ( 'Edgar', 'Allan', 'Poe' ) ) + ( middleName IN ( 'Edgar', 'Allan', 'Poe' ) ) + ( lastName IN ( 'Edgar', 'Allan', 'Poe' ) ) ) >=2;
Run Code Online (Sandbox Code Playgroud)
然后 SQL 语句是PREPAREd 和EXECUTEd,从而在调用时生成所需的列表PROCEDURE,这可以使用...来完成
CALL SimilarNames( 'Edgar Allan Poe' );
Run Code Online (Sandbox Code Playgroud)
请注意,您不必PROCEDURE在第一次这样做后声明。即以下内容可以正常工作......
CALL SimilarNames( 'Edgar Allan Poe' );
CALL SimilarNames( 'James Tiberius Kirk' );
Run Code Online (Sandbox Code Playgroud)
另请注意,此特定方法容易受到SQL 注入攻击。如果你愿意的话,我可以开发一个版本来防止这种情况发生——现在已经很晚了,我很快就要上床睡觉了。
我的声明针对使用以下脚本创建的示例数据集进行了测试......
CREATE TABLE author
(
authorID INT NOT NULL AUTO_INCREMENT,
firstName VARCHAR( 50 ),
middleName VARCHAR( 50 ),
lastName VARCHAR( 50 ),
PRIMARY KEY ( authorID )
);
INSERT INTO author ( firstName,
middleName,
lastName )
VALUES ( 'Edgar', 'Allan', 'Poe' ),
( 'Poe', 'Allan', 'Edgar' ),
( 'Edgar', 'Poe', '' ),
( 'Edgar', '', 'Poe' ),
( '', 'Edgar', 'Poe' ),
( 'Allan', 'Poe', '' ),
( 'Edgar', 'Allan', '' ),
( 'Allan', 'Edgar', 'Poe' ),
( 'Edgar', 'Allan', 'Allan' ),
( 'James', 'Tiberius', 'Kirk' ),
( 'Karl', 'Ignatius', 'von Bach' ),
( 'Edgar', 'Poe', 'xyz' ),
( 'Allanah', 'Poelsen', '' );
Run Code Online (Sandbox Code Playgroud)
结果正如我所料。
如果您有任何问题或意见,请随时发表评论。
进一步阅读
https://dev.mysql.com/doc/refman/5.7/en/call.html(关于MySQL的CALL声明)
https://dev.mysql.com/doc/refman/5.7/en/string-functions.html#function_concat(关于MySQL的CONCAT()函数)
https://dev.mysql.com/doc/refman/5.7/en/create-procedure.html(关于MySQL的CREATE PROCEDURE声明)
https://dev.mysql.com/doc/refman/5.7/en/deallocate-prepare.html(关于MySQL的DEALLOCATE声明)
https://dev.mysql.com/doc/refman/5.7/en/stored-programs-defining.html(在MySQL的DELIMITER命令上)
https://dev.mysql.com/doc/refman/5.7/en/drop-procedure.html(关于MySQL的DROP PROCEDURE声明)
https://dev.mysql.com/doc/refman/5.7/en/execute.html(关于MySQL的EXECUTE声明)
https://dev.mysql.com/doc/refman/5.7/en/comparison-operators.html#function_in(关于MySQL的IN运算符)
https://dev.mysql.com/doc/refman/5.7/en/prepare.html(关于MySQL的PREPARE声明)
https://dev.mysql.com/doc/refman/5.7/en/string-functions.html#function_replace(关于MySQL的REPLACE()函数)
https://dev.mysql.com/doc/refman/5.7/en/set-statement.html(关于MySQL的SET声明)