4

我的问题实际上是我的最终目标。到目前为止,我有2个问题。

  1. 如何在mysql中将阿拉伯日期保存为“日期”?因为,我一直在将 Gregorian 转换为 Hijri,然后使用 preg_replace(php,目前,final 在 Java 中)将数字更改为阿拉伯 ascii hex ...然后,将其保存在 MySQL 中作为 varchar。

我知道排序规则 cp1256_general_ci 允许我们以阿拉伯语存储,但目前,为了简单起见,我把它放在一边。utf-8_general 也做得很好。所以存储为 varchar 不是问题,存储为“日期”是问题。

  1. 对其执行查询。我认为要求到此为止,但是,现在的任务是执行诸如日期“在”xyz 和 pqr 之间的查询……此外,约束是“仅将其存储为阿拉伯语”。

非常感谢任何输入。

4

2 回答 2

3

SQL 日期

我会这样想:服务器实际上将日期存储为对给定日期的引用。它是如何做到的与您无关。在将数据存储到此类日期列或从此类日期列读取数据时,服务器使用特定日历表示该日期,按照惯例,该日历是公历。我想说的是,我不会认为存储的值是公历的,尽管它很可能是。我宁愿认为转移日期是公历。

因此,在我看来,最好的解决方案是接受这一事实并在应用程序端在 Gregorian 和 Hijri 之间进行转换。这样,您可以between对其使用常规检查。

由数字组成的字符串

如果这是不可能的,因为依赖于语言环境的转换太复杂,或者因为回历和 Grogorian 之间的映射不是唯一的或事先不知道,那么您将不得不以其他形式存储日期。我想到的可能形式是varchar包含形式的字符串YYYY-MM-DD,其中字母表示数字。此方案确保字符串会像它们所代表的日期一样进行比较,因此您仍然可以between在它们上使用。不过,将这些字符串转回拼写日期仍然很棘手。

一个或多个数字列

因此,我实际上建议您使用三列。每列包含一个表示日期的数字,然后您可以使用它10000*year + 100*month + day_of_month来获取每天的单个数字,您可以将其用于比较和between. 另一方面,您可以ELT在查询中使用该函数将月份的数字转换回名称。如果性能是一个问题,您最好只存储一个数字,并在选择时将其分成几部分。在公历中,这看起来像这样:

CREATE TABLE tableName (myDate DECIMAL(8));

SELECT myDate DIV 10000 AS year,
       ELT((myDate DIV 100) MOD 100, "Jan", "Feb", …) AS month,
       myDate MOD 100 AS day_of_month
FROM tableName
WHERE myDate BETWEN 20121021 AND 20121023;

兼容性和便利性

如果您必须保持与需要单个文本日期列的代码的只读兼容性,您可以使用 aVIEW来提供它。例如,对于德语 GregorianDD. MMMM YYYY格式,您可以使用如下代码:

CREATE VIEW compatibleName AS
SELECT CONCAT(myDate MOD 100, ". ",
              ELT((myDate DIV 100) MOD 100, "Januar", "Februar", …), ". ",
              myDate DIV 10000) as dateString,
       * -- or explicitely name other columns needed for compatibility
FROM tableName

解码字符串

如果您需要另一个应用程序使用字符串格式进行读写访问,您必须自己解析这些字符串。您可以在 SQL 级别执行此操作。有用的工具是SUBSTRING_INDEX将字符串拆分为字段并将FIELD月份名称转换为数字。您可能希望向数据库添加一个触发器,以确保您的字符串始终采用您可以通过这种方式分解的有效格式。这个问题详细介绍了如何使用触发器来强制执行此类检查。

于 2012-10-22T05:24:17.810 回答
3

您可以直接存储为日期。我使用的是正常日期。我的mysql函数是

DELIMITER $$

DROP FUNCTION IF EXISTS `kdmtest`.`IntPart` $$
CREATE FUNCTION `kdmtest`.`IntPart` (FloatNum float) RETURNS INT
BEGIN
if (floatNum< -0.0000001) then
     return ceil(floatNum-0.0000001);
else
  return floor(floatNum+0.0000001);
end if;
END $$

DELIMITER ;


DELIMITER $$

DROP FUNCTION IF EXISTS `kdmtest`.`Hicri` $$
CREATE DEFINER=`root`@`localhost` FUNCTION `Hicri`(MiladiTarih date) RETURNS date
BEGIN
  declare d,m,y,jd,l,n,j int;
  set d=day(MiladiTarih);
  set m=month(MiladiTarih);
  set y=year(MiladiTarih);
  if ((y>1582) or((y=1582) and (m>10)) or ((y=1582) and (m=10) and (d>14))) then
    set jd=intpart((1461*(y+4800+intpart((m-14)/12)))/4)+intpart((367*(m-2-12*(intpart((m-14)/12))))/12)- intpart( (3* (intpart(  (y+4900+    intpart( (m-14)/12)     )/100)    )   ) /4)+d-32075;
  else
    set jd = 367*y-intpart((7*(y+5001+intpart((m-9)/7)))/4)+intpart((275*m)/9)+d+1729777;
  end if;
                    set l=jd-1948440+10632;
                    set n=intpart((l-1)/10631);
                    set l=l-10631*n+354;
                    set j=(intpart((10985-l)/5316))*(intpart((50*l)/17719))+(intpart(l/5670))*(intpart((43*l)/15238));
                    set l=l-(intpart((30-j)/15))*(intpart((17719*j)/50))-(intpart(j/16))*(intpart((15238*j)/43))+29;
                    set m=intpart((24*l)/709);
                    set d=l-intpart((709*m)/24);
                    set y=30*n+j-30;
return concat(y,'-',m,'-',d);
END $$

DELIMITER ;


DELIMITER $$

DROP FUNCTION IF EXISTS `kdmtest`.`Miladi` $$
CREATE FUNCTION `kdmtest`.`Miladi` (HicriTarih date) RETURNS date
BEGIN
  declare d,m,y,jd,l,n,j,i,k int;
  set d=day(HicriTarih);
    set m=month(HicriTarih);
    set y=year(HicriTarih);
    set jd=intPart((11*y+3)/30)+354*y+30*m-intPart((m-1)/2)+d+1948440-385;
  if (jd> 2299160 ) then
        set l=jd+68569;
        set n=intPart((4*l)/146097);
    set l=l-intPart((146097*n+3)/4);
        set i=intPart((4000*(l+1))/1461001);
    set l=l-intPart((1461*i)/4)+31;
    set j=intPart((80*l)/2447);
    set d=l-intPart((2447*j)/80);
        set l=intPart(j/11);
        set m=j+2-12*l;
        set y=100*(n-49)+i+l;
  else
    set j=jd+1402;
    set k=intPart((j-1)/1461);
    set l=j-1461*k;
    set n=intPart((l-1)/365)-intPart(l/1461);
    set i=l-365*n+30;
        set j=intPart((80*i)/2447);
        set d=i-intPart((2447*j)/80);
        set i=intPart(j/11);
        set m=j+2-12*i;
        set y=4*k+n+i-4716;
  end if;
  return concat(y,'-',m,'-',d);
END $$

DELIMITER ;
于 2013-11-22T06:18:12.360 回答