在MySQL中,使用Like子句时与阿拉伯语字符串相关的日期类型问题
在MySQL中,使用Like子句时与阿拉伯语字符串相关的日期类型问题
我在一个旧系统上工作,弹出窗口中的搜索是动态生成的。例如,如果弹出窗口字段为:field1, field2, field3
,而用户在搜索文本框中键入كلمة或任何阿拉伯单词。系统将创建一个动态的搜索条件,如下所示:
field1 LIKE '%كلمة%' OR field2 LIKE '%كلمة%' OR field3 LIKE '%كلمة%'
当其中一个字段是日期类型时,就会出现问题,此时会给我一个mysql错误:
illegal mix of collations for operation 'like'
当我将搜索的单词改为英文单词时,会给我一个警告,但是正常工作,因为在这种情况下我不需要日期类型的字段(我搜索的是文本)。
我无法更改这个动态搜索php函数的核心,因为整个系统都已经构建好了,所以我不能像这样使用代码:
OR DATE_FORMAT(field1, '%Y-%m-%d') LIKE '%كلمة%'
因为我不知道哪个字段是Date
类型,它是一个动态搜索。
此问题仅发生在托管服务器上,而不是在我的本地主机上,我的主机是:Server version: 5.5.47-cll - MySQL Community Server (GPL)
,我的本地主机mysql版本是:5.5.5
。
以下是显示创建表脚本:
CREATE TABLE `POS_QUOTATIONS` ( `DEPT_ID` varchar(20) NOT NULL, `BILL_TYPE` int(11) NOT NULL, `BILL_NUMBER` int(11) NOT NULL, `BILL_NUMBER_TO_RTRN` int(11) NOT NULL, `SALESPERSON_NAME` varchar(255) NOT NULL, `BILL_DATE` date NOT NULL, `POS_ID` int(11) NOT NULL, `STOCK_ID` varchar(20) NOT NULL, `CURRENCY_ID` varchar(3) NOT NULL, `EXCHANGE_RATE` float NOT NULL, `SALESPERSON_TYPE` int(1) NOT NULL, `SALESPERSON_ID` int(10) NOT NULL, `CLIENT_TYPE` int(1) NOT NULL, `ACC_CODE` varchar(20) NOT NULL, `CLIENT_NAME` varchar(255) NOT NULL, `CLIENT_APPROVAL_NUMBER` varchar(20) NOT NULL, `NOTES` varchar(255) NOT NULL, `BILL_VALUE_BEFORE_DISCOUNT` double NOT NULL, `OVRALL_COST` double DEFAULT '0', `SALES_TAX` double NOT NULL, `ADITIONAL_AMOUNT` double NOT NULL, `DISCOUNT_PERCENTAGE` double NOT NULL, `DISCOUNT_AMOUNT` double NOT NULL, `BILL_VALUE_AFTER_DISCOUNT` double NOT NULL, `CLIENT_PAYMENT` decimal(13,2) NOT NULL, `REMAINING_AMOUNT` decimal(13,2) NOT NULL, `PAYMENT_METHOD` int(11) NOT NULL, `CREDIT_CARD_DETAILS` varchar(255) NOT NULL, `BANK_OPERATION_NUMBER` varchar(50) NOT NULL, `BANK_DETAILS` varchar(255) NOT NULL, `BANK_ACC_CODE` varchar(20) NOT NULL, `PAYMENT_METHOD_INFO` varchar(500) NOT NULL, `CONTRACT_PRODUCT_DETAILS` text NOT NULL, `CONTRACT_REC_VOUCHER_NO` varchar(255) NOT NULL, `CONTRACT_REPAYMENT_DATE` varchar(255) NOT NULL, `ROWID` varchar(255) NOT NULL, `YEAR` int(4) NOT NULL, `CREATION_USER` varchar(10) DEFAULT NULL, `CREATION_TIMESTAMP` varchar(14) DEFAULT NULL, `CREATION_COMPUTER_NAME` varchar(50) DEFAULT NULL, `LASTUPDATE_USER` varchar(10) DEFAULT NULL, `LASTUPDATE_TIMESTAMP` varchar(50) DEFAULT NULL, `LASTUPDATE_COMPUTER_NAME` varchar(50) DEFAULT NULL, `TRANS_FLAG` varchar(10) DEFAULT NULL, `RECORD_STATUS` varchar(1) DEFAULT NULL, `JOURNAL_STATUS` tinyint(1) DEFAULT NULL, `PROCESS_NUMBER` varchar(50) DEFAULT NULL, `OFFER_TERMS` text, `TECHNICAL_SPECIFICATIONS` text, `OFFER_STATUS` tinyint(1) DEFAULT NULL, `PROJECT_DESCRIPTION` varchar(500) DEFAULT NULL, `POS_CONTRACT_AGREEMENT_ID` varchar(50) DEFAULT NULL, `COST_CENTER_CODE` varchar(50) DEFAULT NULL, PRIMARY KEY (`ROWID`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8
无论托管服务器的数据库字符集是什么,当字符集为utf8_general_ci
或latin1_swedish_ci
时,都会产生此错误。
提前感谢。
问题的原因是在使用like
操作符时,日期字段被当作拉丁字符串处理。假设您使用的是utf8字符集,您需要在对日期字段进行like
操作之前将其转换为utf8编码:
convert(field1 using utf8) LIKE '%كلمة%' OR convert(field2 using utf8) LIKE '%كلمة%' OR convert(field3 using utf8) LIKE '%كلمة%'
理想情况下,如果您在这里添加一些逻辑,并有条件地将转换应用于仅日期字段。例如,如果您知道field2是唯一的日期字段,可以构建查询:
field1 LIKE '%كلمة%' OR convert(field2 using utf8) LIKE '%كلمة%' OR field3 LIKE '%كلمة%'
但为什么这个错误只在托管服务器上出现,在我的本地主机上没有出现任何错误。你知道原因吗?
服务器之间必须有某种不同之处。我会比较两个系统的show variables where value like '%utf%';
,但老实说,我对此并不了解。我只是从stackoverflow.com/questions/14519271/…中无耻地窃取了答案。
如果您必须对utf8进行转换,那么该字段不能包含阿拉伯字符。utf8(和utf8mb4)是MySQL中唯一能够表示阿拉伯字符的CHARACTER SETs
。因此,我不明白这个解决方案是如何起作用的。所以,也许这是一种COLLATIONs
的混合?在这种情况下,让我们看一下SHOW CREATE TABLE
的结果。's的评论更接近答案。
"they treated as latin strings" - 是这样吗,还是它们被转换为charset_connection/collation_connection?
你是对的,我的字符集是utf8,但问题出现在日期类型的列上,而不是varchar列上。